From 184f7b5c5e861df261fb8abbb7efb99bd1108bcb Mon Sep 17 00:00:00 2001 From: Yihoi Jung Date: Sat, 27 Jan 2024 09:39:01 -0500 Subject: [PATCH 01/16] Added more items to the form --- __pycache__/webapp.cpython-311.pyc | Bin 1782 -> 2035 bytes templates/home.html | 24 ++++++++++++++++++++---- webapp.py | 10 +++++++--- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/__pycache__/webapp.cpython-311.pyc b/__pycache__/webapp.cpython-311.pyc index 333d01c8fa756e095528bf8557c45952a7b8ad1d..47799fb6190dca455f5b9617b799fc267da39356 100644 GIT binary patch delta 517 zcmeyy`&VOYR4nUPs|vM{p{ zD>E`rmL-L`hGjNG3QG+$kYuf41d?nuOtTs0a@4X;R%2GKXRl!e@|f0eEMsI~SPjGw zP|H@smcl6s<1%Ei!kD$}CA=^;149Z|4SOads@`A*O>VzioSAtgsYR*9CB?Tma`KZC zOEUBGsyN(=GE?(Ximj^HbQB!ZQ>|pHcy$y!VJfW@s(5r1e4whW6ejOscALz~;>XA_ zIfO;cm7}ycwJ1I@J@pn3n3V=G>=su+Vo_plD$u&(Tf*t7d8tKU+v0(?7v$#w^@so+ zTnq{}1qFr4GgxG~6oG63kl>NY`&kU)Ztx5DS9Dd(;JV1Ke1%`R!Q+Oo_;ia&7Bjpq z3aeicR&Vh6z{Vg{%s9j6f?yF4ZQy{=2kId7h2#PVqrvO0l+1kXS=u-FlP-iMTmX{% zNt1b5R|$y&ZM(%SVk(q%>>k6ah2PTk+ J*5o5>MgT${kl|18i*mFmbr#Gg-sI1WyoTMF>6^$cwuY?h7|T1mP|%ey}=Bc9FqlD z#3zTbxHA1>oIH!gpOJO)D;70Z;q=tJ)S|?a%>2CgqSWGo{Ji4SB2l1e#USGqK%j^R z$hsu}RhSx|oS#>cnpaXJ4-^&vsce~C!)hS+m5V`IcE0v3?Hl}M7s66507)Q9FM%*7 zbFr-wk^mXRT9jW}l3E0EagqGwV{A%{I+I_r9TXR0wEe&UBt9}TFlk+3)cn8%6497^ HklhFXxff7b diff --git a/templates/home.html b/templates/home.html index 72e6d0d6..7e524cef 100644 --- a/templates/home.html +++ b/templates/home.html @@ -11,15 +11,29 @@

Flask Cohere App


+
+ + +
+ + +
+
@@ -29,13 +43,15 @@

Flask Cohere App

function generateContent() { var interests = document.getElementById("interests").value; var location = document.getElementById("location").value; + var location = document.getElementById("friends").value; + var location = document.getElementById("age").value; fetch('/generate', { method: 'POST', headers: { 'Content-Type': 'application/json', }, - body: JSON.stringify({ interests, location }), + body: JSON.stringify({ age, location, friends, interests }), }) .then(response => response.json()) .then(data => { diff --git a/webapp.py b/webapp.py index 3c71ec40..a25f2ace 100644 --- a/webapp.py +++ b/webapp.py @@ -20,14 +20,18 @@ def generate_content(): # Get user inputs from the JSON data user_interests = data.get("interests") user_location = data.get("location") - #user_interests = "legos, beyblade, star wars" - #user_location = "Canada" + user_age = data.get("location") + user_friends = data.get("location") # Use Cohere to generate content based on user inputs + parameters = f'Friends:{user_friends}, Interests: {user_interests}, Location: {user_location}' generation_response = co.generate( - prompt=f'Please write a short story for nostalgia based on these parameters: {user_interests} {user_location}' + prompt=f'Please write a short story for nostalgia based on these parameters: {parameters}' ) + # User's age & location used for childhood Spotify + + # Access the 'text' attribute to get the generated content generated_content = generation_response[0].text From aa6da7eff14a2e4713f70534d9202a884084b10b Mon Sep 17 00:00:00 2001 From: Yihoi Jung Date: Sat, 27 Jan 2024 10:03:39 -0500 Subject: [PATCH 02/16] Create requirements.txt --- requirements.txt | Bin 0 -> 830 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..d139b8d7587d2537a5637097f2f12b2a03b57e35 GIT binary patch literal 830 zcmYjQO;3YR5ZtqgKgEWRTJ_MY2NO>oJOc&AQosTx_Q$I;vpg{5rKPhwGduhG`;%F1 zoxR(Lr?)+x)He2j6Wg_2nd1Yh-mJx2qna2v>p~5?&o&54gd{*CG34kf>)I|0KRbDn zxr_RANbY;_QQsMv4SkhDw?MacyI_qJGHI|o627sWDk>-saFW><7&m_>dleH2~6~Iz~Lu5cH*HY-&GA{ zP(_PsXb|DAK*#EL~Wuz*E4=UW2y-*Uhut|^Yg7UL#BHI-awHva05Oc zJ$a6-Ve+4-E0tupVbob&PpE3 Date: Sat, 27 Jan 2024 11:35:07 -0500 Subject: [PATCH 03/16] Fixed text generation for cohere portion --- .env | 4 + .../__pycache__/six.cpython-311.pyc | Bin 0 -> 46403 bytes .../redis-5.0.1.dist-info/INSTALLER | 1 + .../redis-5.0.1.dist-info/LICENSE | 21 + .../redis-5.0.1.dist-info/METADATA | 203 + .../redis-5.0.1.dist-info/RECORD | 147 + .../site-packages/redis-5.0.1.dist-info/WHEEL | 5 + .../redis-5.0.1.dist-info/top_level.txt | 1 + .venv/Lib/site-packages/redis/__init__.py | 94 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 2816 bytes .../redis/__pycache__/backoff.cpython-311.pyc | Bin 0 -> 6000 bytes .../redis/__pycache__/client.cpython-311.pyc | Bin 0 -> 70974 bytes .../redis/__pycache__/cluster.cpython-311.pyc | Bin 0 -> 97774 bytes .../redis/__pycache__/compat.cpython-311.pyc | Bin 0 -> 487 bytes .../__pycache__/connection.cpython-311.pyc | Bin 0 -> 58490 bytes .../redis/__pycache__/crc.cpython-311.pyc | Bin 0 -> 1095 bytes .../__pycache__/credentials.cpython-311.pyc | Bin 0 -> 1899 bytes .../__pycache__/exceptions.cpython-311.pyc | Bin 0 -> 10258 bytes .../redis/__pycache__/lock.cpython-311.pyc | Bin 0 -> 13842 bytes .../redis/__pycache__/ocsp.cpython-311.pyc | Bin 0 -> 16362 bytes .../redis/__pycache__/retry.cpython-311.pyc | Bin 0 -> 2771 bytes .../__pycache__/sentinel.cpython-311.pyc | Bin 0 -> 20084 bytes .../redis/__pycache__/typing.cpython-311.pyc | Bin 0 -> 2893 bytes .../redis/__pycache__/utils.cpython-311.pyc | Bin 0 -> 6459 bytes .../site-packages/redis/_parsers/__init__.py | 20 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 805 bytes .../_parsers/__pycache__/base.cpython-311.pyc | Bin 0 -> 11537 bytes .../__pycache__/commands.cpython-311.pyc | Bin 0 -> 13138 bytes .../__pycache__/encoders.cpython-311.pyc | Bin 0 -> 2580 bytes .../__pycache__/helpers.cpython-311.pyc | Bin 0 -> 47791 bytes .../__pycache__/hiredis.cpython-311.pyc | Bin 0 -> 10841 bytes .../__pycache__/resp2.cpython-311.pyc | Bin 0 -> 6101 bytes .../__pycache__/resp3.cpython-311.pyc | Bin 0 -> 12191 bytes .../__pycache__/socket.cpython-311.pyc | Bin 0 -> 8003 bytes .../Lib/site-packages/redis/_parsers/base.py | 225 + .../site-packages/redis/_parsers/commands.py | 281 + .../site-packages/redis/_parsers/encoders.py | 44 + .../site-packages/redis/_parsers/helpers.py | 852 +++ .../site-packages/redis/_parsers/hiredis.py | 217 + .../Lib/site-packages/redis/_parsers/resp2.py | 132 + .../Lib/site-packages/redis/_parsers/resp3.py | 259 + .../site-packages/redis/_parsers/socket.py | 162 + .../site-packages/redis/asyncio/__init__.py | 64 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 1697 bytes .../__pycache__/client.cpython-311.pyc | Bin 0 -> 74517 bytes .../__pycache__/cluster.cpython-311.pyc | Bin 0 -> 73954 bytes .../__pycache__/connection.cpython-311.pyc | Bin 0 -> 61192 bytes .../asyncio/__pycache__/lock.cpython-311.pyc | Bin 0 -> 14742 bytes .../asyncio/__pycache__/retry.cpython-311.pyc | Bin 0 -> 3485 bytes .../__pycache__/sentinel.cpython-311.pyc | Bin 0 -> 20387 bytes .../asyncio/__pycache__/utils.cpython-311.pyc | Bin 0 -> 1737 bytes .../Lib/site-packages/redis/asyncio/client.py | 1533 ++++ .../site-packages/redis/asyncio/cluster.py | 1620 +++++ .../site-packages/redis/asyncio/connection.py | 1180 +++ .venv/Lib/site-packages/redis/asyncio/lock.py | 313 + .../Lib/site-packages/redis/asyncio/retry.py | 67 + .../site-packages/redis/asyncio/sentinel.py | 375 + .../Lib/site-packages/redis/asyncio/utils.py | 28 + .venv/Lib/site-packages/redis/backoff.py | 114 + .venv/Lib/site-packages/redis/client.py | 1500 ++++ .venv/Lib/site-packages/redis/cluster.py | 2486 +++++++ .../site-packages/redis/commands/__init__.py | 18 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 784 bytes .../__pycache__/cluster.cpython-311.pyc | Bin 0 -> 40137 bytes .../commands/__pycache__/core.cpython-311.pyc | Bin 0 -> 279460 bytes .../__pycache__/helpers.cpython-311.pyc | Bin 0 -> 8521 bytes .../__pycache__/redismodules.cpython-311.pyc | Bin 0 -> 4210 bytes .../__pycache__/sentinel.cpython-311.pyc | Bin 0 -> 6543 bytes .../redis/commands/bf/__init__.py | 253 + .../bf/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 10763 bytes .../bf/__pycache__/commands.cpython-311.pyc | Bin 0 -> 28213 bytes .../bf/__pycache__/info.cpython-311.pyc | Bin 0 -> 6604 bytes .../redis/commands/bf/commands.py | 542 ++ .../site-packages/redis/commands/bf/info.py | 120 + .../site-packages/redis/commands/cluster.py | 928 +++ .../Lib/site-packages/redis/commands/core.py | 6305 +++++++++++++++++ .../redis/commands/graph/__init__.py | 263 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 13132 bytes .../__pycache__/commands.cpython-311.pyc | Bin 0 -> 13621 bytes .../graph/__pycache__/edge.cpython-311.pyc | Bin 0 -> 3685 bytes .../__pycache__/exceptions.cpython-311.pyc | Bin 0 -> 640 bytes .../execution_plan.cpython-311.pyc | Bin 0 -> 10162 bytes .../graph/__pycache__/node.cpython-311.pyc | Bin 0 -> 4247 bytes .../graph/__pycache__/path.cpython-311.pyc | Bin 0 -> 4708 bytes .../__pycache__/query_result.cpython-311.pyc | Bin 0 -> 25921 bytes .../redis/commands/graph/commands.py | 313 + .../redis/commands/graph/edge.py | 91 + .../redis/commands/graph/exceptions.py | 3 + .../redis/commands/graph/execution_plan.py | 211 + .../redis/commands/graph/node.py | 88 + .../redis/commands/graph/path.py | 78 + .../redis/commands/graph/query_result.py | 573 ++ .../site-packages/redis/commands/helpers.py | 166 + .../redis/commands/json/__init__.py | 147 + .../json/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 6838 bytes .../json/__pycache__/_util.cpython-311.pyc | Bin 0 -> 435 bytes .../json/__pycache__/commands.cpython-311.pyc | Bin 0 -> 21966 bytes .../json/__pycache__/decoders.cpython-311.pyc | Bin 0 -> 2862 bytes .../json/__pycache__/path.cpython-311.pyc | Bin 0 -> 1087 bytes .../redis/commands/json/_util.py | 3 + .../redis/commands/json/commands.py | 429 ++ .../redis/commands/json/decoders.py | 60 + .../site-packages/redis/commands/json/path.py | 16 + .../redis/commands/redismodules.py | 103 + .../redis/commands/search/__init__.py | 189 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 7584 bytes .../search/__pycache__/_util.cpython-311.pyc | Bin 0 -> 552 bytes .../__pycache__/aggregation.cpython-311.pyc | Bin 0 -> 16474 bytes .../__pycache__/commands.cpython-311.pyc | Bin 0 -> 45462 bytes .../__pycache__/document.cpython-311.pyc | Bin 0 -> 1276 bytes .../search/__pycache__/field.cpython-311.pyc | Bin 0 -> 7761 bytes .../indexDefinition.cpython-311.pyc | Bin 0 -> 4755 bytes .../search/__pycache__/query.cpython-311.pyc | Bin 0 -> 16750 bytes .../__pycache__/querystring.cpython-311.pyc | Bin 0 -> 16254 bytes .../__pycache__/reducers.cpython-311.pyc | Bin 0 -> 9239 bytes .../search/__pycache__/result.cpython-311.pyc | Bin 0 -> 2956 bytes .../__pycache__/suggestion.cpython-311.pyc | Bin 0 -> 3031 bytes .../redis/commands/search/_util.py | 7 + .../redis/commands/search/aggregation.py | 372 + .../redis/commands/search/commands.py | 1117 +++ .../redis/commands/search/document.py | 17 + .../redis/commands/search/field.py | 168 + .../redis/commands/search/indexDefinition.py | 79 + .../redis/commands/search/query.py | 362 + .../redis/commands/search/querystring.py | 317 + .../redis/commands/search/reducers.py | 182 + .../redis/commands/search/result.py | 73 + .../redis/commands/search/suggestion.py | 55 + .../site-packages/redis/commands/sentinel.py | 99 + .../redis/commands/timeseries/__init__.py | 108 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 4854 bytes .../__pycache__/commands.cpython-311.pyc | Bin 0 -> 39324 bytes .../__pycache__/info.cpython-311.pyc | Bin 0 -> 4522 bytes .../__pycache__/utils.cpython-311.pyc | Bin 0 -> 3415 bytes .../redis/commands/timeseries/commands.py | 896 +++ .../redis/commands/timeseries/info.py | 91 + .../redis/commands/timeseries/utils.py | 44 + .venv/Lib/site-packages/redis/compat.py | 6 + .venv/Lib/site-packages/redis/connection.py | 1336 ++++ .venv/Lib/site-packages/redis/crc.py | 23 + .venv/Lib/site-packages/redis/credentials.py | 26 + .venv/Lib/site-packages/redis/exceptions.py | 218 + .venv/Lib/site-packages/redis/lock.py | 308 + .venv/Lib/site-packages/redis/ocsp.py | 307 + .venv/Lib/site-packages/redis/py.typed | 0 .venv/Lib/site-packages/redis/retry.py | 54 + .venv/Lib/site-packages/redis/sentinel.py | 389 + .venv/Lib/site-packages/redis/typing.py | 65 + .venv/Lib/site-packages/redis/utils.py | 147 + .../six-1.16.0.dist-info/INSTALLER | 1 + .../six-1.16.0.dist-info/LICENSE | 18 + .../six-1.16.0.dist-info/METADATA | 49 + .../site-packages/six-1.16.0.dist-info/RECORD | 8 + .../site-packages/six-1.16.0.dist-info/WHEEL | 6 + .../six-1.16.0.dist-info/top_level.txt | 1 + .venv/Lib/site-packages/six.py | 998 +++ .../spotipy-2.23.0.dist-info/INSTALLER | 1 + .../spotipy-2.23.0.dist-info/LICENSE.md | 21 + .../spotipy-2.23.0.dist-info/METADATA | 100 + .../spotipy-2.23.0.dist-info/RECORD | 19 + .../spotipy-2.23.0.dist-info/REQUESTED | 0 .../spotipy-2.23.0.dist-info/WHEEL | 5 + .../spotipy-2.23.0.dist-info/top_level.txt | 1 + .venv/Lib/site-packages/spotipy/__init__.py | 5 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 340 bytes .../__pycache__/cache_handler.cpython-311.pyc | Bin 0 -> 10590 bytes .../__pycache__/client.cpython-311.pyc | Bin 0 -> 92355 bytes .../__pycache__/exceptions.cpython-311.pyc | Bin 0 -> 1134 bytes .../__pycache__/oauth2.cpython-311.pyc | Bin 0 -> 59824 bytes .../spotipy/__pycache__/util.cpython-311.pyc | Bin 0 -> 3847 bytes .../site-packages/spotipy/cache_handler.py | 210 + .venv/Lib/site-packages/spotipy/client.py | 2035 ++++++ .venv/Lib/site-packages/spotipy/exceptions.py | 16 + .venv/Lib/site-packages/spotipy/oauth2.py | 1308 ++++ .venv/Lib/site-packages/spotipy/util.py | 135 + __pycache__/webapp.cpython-311.pyc | Bin 2035 -> 2475 bytes requirements.txt | Bin 830 -> 964 bytes server.py | 60 + templates/home.html | 15 +- webapp.py | 17 +- 180 files changed, 34736 insertions(+), 6 deletions(-) create mode 100644 .env create mode 100644 .venv/Lib/site-packages/__pycache__/six.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis-5.0.1.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/redis-5.0.1.dist-info/LICENSE create mode 100644 .venv/Lib/site-packages/redis-5.0.1.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/redis-5.0.1.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/redis-5.0.1.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/redis-5.0.1.dist-info/top_level.txt create mode 100644 .venv/Lib/site-packages/redis/__init__.py create mode 100644 .venv/Lib/site-packages/redis/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/__pycache__/backoff.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/__pycache__/client.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/__pycache__/cluster.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/__pycache__/compat.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/__pycache__/connection.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/__pycache__/crc.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/__pycache__/credentials.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/__pycache__/exceptions.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/__pycache__/lock.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/__pycache__/ocsp.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/__pycache__/retry.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/__pycache__/sentinel.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/__pycache__/typing.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/__pycache__/utils.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/_parsers/__init__.py create mode 100644 .venv/Lib/site-packages/redis/_parsers/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/_parsers/__pycache__/base.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/_parsers/__pycache__/commands.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/_parsers/__pycache__/encoders.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/_parsers/__pycache__/helpers.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/_parsers/__pycache__/hiredis.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/_parsers/__pycache__/resp2.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/_parsers/__pycache__/resp3.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/_parsers/__pycache__/socket.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/_parsers/base.py create mode 100644 .venv/Lib/site-packages/redis/_parsers/commands.py create mode 100644 .venv/Lib/site-packages/redis/_parsers/encoders.py create mode 100644 .venv/Lib/site-packages/redis/_parsers/helpers.py create mode 100644 .venv/Lib/site-packages/redis/_parsers/hiredis.py create mode 100644 .venv/Lib/site-packages/redis/_parsers/resp2.py create mode 100644 .venv/Lib/site-packages/redis/_parsers/resp3.py create mode 100644 .venv/Lib/site-packages/redis/_parsers/socket.py create mode 100644 .venv/Lib/site-packages/redis/asyncio/__init__.py create mode 100644 .venv/Lib/site-packages/redis/asyncio/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/asyncio/__pycache__/client.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/asyncio/__pycache__/cluster.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/asyncio/__pycache__/connection.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/asyncio/__pycache__/lock.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/asyncio/__pycache__/retry.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/asyncio/__pycache__/sentinel.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/asyncio/__pycache__/utils.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/asyncio/client.py create mode 100644 .venv/Lib/site-packages/redis/asyncio/cluster.py create mode 100644 .venv/Lib/site-packages/redis/asyncio/connection.py create mode 100644 .venv/Lib/site-packages/redis/asyncio/lock.py create mode 100644 .venv/Lib/site-packages/redis/asyncio/retry.py create mode 100644 .venv/Lib/site-packages/redis/asyncio/sentinel.py create mode 100644 .venv/Lib/site-packages/redis/asyncio/utils.py create mode 100644 .venv/Lib/site-packages/redis/backoff.py create mode 100644 .venv/Lib/site-packages/redis/client.py create mode 100644 .venv/Lib/site-packages/redis/cluster.py create mode 100644 .venv/Lib/site-packages/redis/commands/__init__.py create mode 100644 .venv/Lib/site-packages/redis/commands/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/__pycache__/cluster.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/__pycache__/core.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/__pycache__/helpers.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/__pycache__/redismodules.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/__pycache__/sentinel.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/bf/__init__.py create mode 100644 .venv/Lib/site-packages/redis/commands/bf/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/bf/__pycache__/commands.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/bf/__pycache__/info.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/bf/commands.py create mode 100644 .venv/Lib/site-packages/redis/commands/bf/info.py create mode 100644 .venv/Lib/site-packages/redis/commands/cluster.py create mode 100644 .venv/Lib/site-packages/redis/commands/core.py create mode 100644 .venv/Lib/site-packages/redis/commands/graph/__init__.py create mode 100644 .venv/Lib/site-packages/redis/commands/graph/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/graph/__pycache__/commands.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/graph/__pycache__/edge.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/graph/__pycache__/exceptions.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/graph/__pycache__/execution_plan.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/graph/__pycache__/node.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/graph/__pycache__/path.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/graph/__pycache__/query_result.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/graph/commands.py create mode 100644 .venv/Lib/site-packages/redis/commands/graph/edge.py create mode 100644 .venv/Lib/site-packages/redis/commands/graph/exceptions.py create mode 100644 .venv/Lib/site-packages/redis/commands/graph/execution_plan.py create mode 100644 .venv/Lib/site-packages/redis/commands/graph/node.py create mode 100644 .venv/Lib/site-packages/redis/commands/graph/path.py create mode 100644 .venv/Lib/site-packages/redis/commands/graph/query_result.py create mode 100644 .venv/Lib/site-packages/redis/commands/helpers.py create mode 100644 .venv/Lib/site-packages/redis/commands/json/__init__.py create mode 100644 .venv/Lib/site-packages/redis/commands/json/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/json/__pycache__/_util.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/json/__pycache__/commands.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/json/__pycache__/decoders.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/json/__pycache__/path.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/json/_util.py create mode 100644 .venv/Lib/site-packages/redis/commands/json/commands.py create mode 100644 .venv/Lib/site-packages/redis/commands/json/decoders.py create mode 100644 .venv/Lib/site-packages/redis/commands/json/path.py create mode 100644 .venv/Lib/site-packages/redis/commands/redismodules.py create mode 100644 .venv/Lib/site-packages/redis/commands/search/__init__.py create mode 100644 .venv/Lib/site-packages/redis/commands/search/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/search/__pycache__/_util.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/search/__pycache__/aggregation.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/search/__pycache__/commands.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/search/__pycache__/document.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/search/__pycache__/field.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/search/__pycache__/indexDefinition.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/search/__pycache__/query.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/search/__pycache__/querystring.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/search/__pycache__/reducers.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/search/__pycache__/result.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/search/__pycache__/suggestion.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/search/_util.py create mode 100644 .venv/Lib/site-packages/redis/commands/search/aggregation.py create mode 100644 .venv/Lib/site-packages/redis/commands/search/commands.py create mode 100644 .venv/Lib/site-packages/redis/commands/search/document.py create mode 100644 .venv/Lib/site-packages/redis/commands/search/field.py create mode 100644 .venv/Lib/site-packages/redis/commands/search/indexDefinition.py create mode 100644 .venv/Lib/site-packages/redis/commands/search/query.py create mode 100644 .venv/Lib/site-packages/redis/commands/search/querystring.py create mode 100644 .venv/Lib/site-packages/redis/commands/search/reducers.py create mode 100644 .venv/Lib/site-packages/redis/commands/search/result.py create mode 100644 .venv/Lib/site-packages/redis/commands/search/suggestion.py create mode 100644 .venv/Lib/site-packages/redis/commands/sentinel.py create mode 100644 .venv/Lib/site-packages/redis/commands/timeseries/__init__.py create mode 100644 .venv/Lib/site-packages/redis/commands/timeseries/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/timeseries/__pycache__/commands.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/timeseries/__pycache__/info.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/timeseries/__pycache__/utils.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/redis/commands/timeseries/commands.py create mode 100644 .venv/Lib/site-packages/redis/commands/timeseries/info.py create mode 100644 .venv/Lib/site-packages/redis/commands/timeseries/utils.py create mode 100644 .venv/Lib/site-packages/redis/compat.py create mode 100644 .venv/Lib/site-packages/redis/connection.py create mode 100644 .venv/Lib/site-packages/redis/crc.py create mode 100644 .venv/Lib/site-packages/redis/credentials.py create mode 100644 .venv/Lib/site-packages/redis/exceptions.py create mode 100644 .venv/Lib/site-packages/redis/lock.py create mode 100644 .venv/Lib/site-packages/redis/ocsp.py create mode 100644 .venv/Lib/site-packages/redis/py.typed create mode 100644 .venv/Lib/site-packages/redis/retry.py create mode 100644 .venv/Lib/site-packages/redis/sentinel.py create mode 100644 .venv/Lib/site-packages/redis/typing.py create mode 100644 .venv/Lib/site-packages/redis/utils.py create mode 100644 .venv/Lib/site-packages/six-1.16.0.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/six-1.16.0.dist-info/LICENSE create mode 100644 .venv/Lib/site-packages/six-1.16.0.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/six-1.16.0.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/six-1.16.0.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/six-1.16.0.dist-info/top_level.txt create mode 100644 .venv/Lib/site-packages/six.py create mode 100644 .venv/Lib/site-packages/spotipy-2.23.0.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/spotipy-2.23.0.dist-info/LICENSE.md create mode 100644 .venv/Lib/site-packages/spotipy-2.23.0.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/spotipy-2.23.0.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/spotipy-2.23.0.dist-info/REQUESTED create mode 100644 .venv/Lib/site-packages/spotipy-2.23.0.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/spotipy-2.23.0.dist-info/top_level.txt create mode 100644 .venv/Lib/site-packages/spotipy/__init__.py create mode 100644 .venv/Lib/site-packages/spotipy/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/spotipy/__pycache__/cache_handler.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/spotipy/__pycache__/client.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/spotipy/__pycache__/exceptions.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/spotipy/__pycache__/oauth2.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/spotipy/__pycache__/util.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/spotipy/cache_handler.py create mode 100644 .venv/Lib/site-packages/spotipy/client.py create mode 100644 .venv/Lib/site-packages/spotipy/exceptions.py create mode 100644 .venv/Lib/site-packages/spotipy/oauth2.py create mode 100644 .venv/Lib/site-packages/spotipy/util.py create mode 100644 server.py diff --git a/.env b/.env new file mode 100644 index 00000000..9a54d9a1 --- /dev/null +++ b/.env @@ -0,0 +1,4 @@ +AUTH0_CLIENT_ID=J7Gt1oCReu3zJssOrG0osSxHFDTfMG63 +AUTH0_CLIENT_SECRET=4aC4oLZ41Oc7LIzfqYwo8suBItabyn7UspIfkBKKhz1srFkQCYUdPODTLBb_prW9 +AUTH0_DOMAIN=dev-h42ipc15kqwo8cw5.us.auth0.com +APP_SECRET_KEY=bd62c75d593e9e02fc505633ce4511d4bfaf22408a02f697ec7537cf258b9b8f \ No newline at end of file diff --git a/.venv/Lib/site-packages/__pycache__/six.cpython-311.pyc b/.venv/Lib/site-packages/__pycache__/six.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fa547f19803625ae7a81b3db9c460b7335e20840 GIT binary patch literal 46403 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 K#}8U;fd3z83u4az literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis-5.0.1.dist-info/INSTALLER b/.venv/Lib/site-packages/redis-5.0.1.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/.venv/Lib/site-packages/redis-5.0.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/Lib/site-packages/redis-5.0.1.dist-info/LICENSE b/.venv/Lib/site-packages/redis-5.0.1.dist-info/LICENSE new file mode 100644 index 00000000..8509ccd6 --- /dev/null +++ b/.venv/Lib/site-packages/redis-5.0.1.dist-info/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022-2023, Redis, inc. + +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/.venv/Lib/site-packages/redis-5.0.1.dist-info/METADATA b/.venv/Lib/site-packages/redis-5.0.1.dist-info/METADATA new file mode 100644 index 00000000..98242bc0 --- /dev/null +++ b/.venv/Lib/site-packages/redis-5.0.1.dist-info/METADATA @@ -0,0 +1,203 @@ +Metadata-Version: 2.1 +Name: redis +Version: 5.0.1 +Summary: Python client for Redis database and key-value store +Home-page: https://github.com/redis/redis-py +Author: Redis Inc. +Author-email: oss@redis.com +License: MIT +Project-URL: Documentation, https://redis.readthedocs.io/en/latest/ +Project-URL: Changes, https://github.com/redis/redis-py/releases +Project-URL: Code, https://github.com/redis/redis-py +Project-URL: Issue tracker, https://github.com/redis/redis-py/issues +Keywords: Redis,key-value store,database +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Console +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 :: Only +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Requires-Python: >=3.7 +Description-Content-Type: text/markdown +License-File: LICENSE +Requires-Dist: async-timeout >=4.0.2 ; python_full_version <= "3.11.2" +Requires-Dist: importlib-metadata >=1.0 ; python_version < "3.8" +Requires-Dist: typing-extensions ; python_version < "3.8" +Provides-Extra: hiredis +Requires-Dist: hiredis >=1.0.0 ; extra == 'hiredis' +Provides-Extra: ocsp +Requires-Dist: cryptography >=36.0.1 ; extra == 'ocsp' +Requires-Dist: pyopenssl ==20.0.1 ; extra == 'ocsp' +Requires-Dist: requests >=2.26.0 ; extra == 'ocsp' + +# redis-py + +The Python interface to the Redis key-value store. + +[![CI](https://github.com/redis/redis-py/workflows/CI/badge.svg?branch=master)](https://github.com/redis/redis-py/actions?query=workflow%3ACI+branch%3Amaster) +[![docs](https://readthedocs.org/projects/redis/badge/?version=stable&style=flat)](https://redis-py.readthedocs.io/en/stable/) +[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) +[![pypi](https://badge.fury.io/py/redis.svg)](https://pypi.org/project/redis/) +[![pre-release](https://img.shields.io/github/v/release/redis/redis-py?include_prereleases&label=latest-prerelease)](https://github.com/redis/redis-py/releases) +[![codecov](https://codecov.io/gh/redis/redis-py/branch/master/graph/badge.svg?token=yenl5fzxxr)](https://codecov.io/gh/redis/redis-py) + +[Installation](#installation) | [Usage](#usage) | [Advanced Topics](#advanced-topics) | [Contributing](https://github.com/redis/redis-py/blob/master/CONTRIBUTING.md) + +--------------------------------------------- + +**Note: ** redis-py 5.0 will be the last version of redis-py to support Python 3.7, as it has reached [end of life](https://devguide.python.org/versions/). redis-py 5.1 will support Python 3.8+. + +--------------------------------------------- + +## Installation + +Start a redis via docker: + +``` bash +docker run -p 6379:6379 -it redis/redis-stack:latest +``` + +To install redis-py, simply: + +``` bash +$ pip install redis +``` + +For faster performance, install redis with hiredis support, this provides a compiled response parser, and *for most cases* requires zero code changes. +By default, if hiredis >= 1.0 is available, redis-py will attempt to use it for response parsing. + +``` bash +$ pip install "redis[hiredis]" +``` + +Looking for a high-level library to handle object mapping? See [redis-om-python](https://github.com/redis/redis-om-python)! + +## Supported Redis Versions + +The most recent version of this library supports redis version [5.0](https://github.com/redis/redis/blob/5.0/00-RELEASENOTES), [6.0](https://github.com/redis/redis/blob/6.0/00-RELEASENOTES), [6.2](https://github.com/redis/redis/blob/6.2/00-RELEASENOTES), [7.0](https://github.com/redis/redis/blob/7.0/00-RELEASENOTES) and [7.2](https://github.com/redis/redis/blob/7.2/00-RELEASENOTES). + +The table below highlights version compatibility of the most-recent library versions and redis versions. + +| Library version | Supported redis versions | +|-----------------|-------------------| +| 3.5.3 | <= 6.2 Family of releases | +| >= 4.5.0 | Version 5.0 to 7.0 | +| >= 5.0.0 | Version 5.0 to current | + + +## Usage + +### Basic Example + +``` python +>>> import redis +>>> r = redis.Redis(host='localhost', port=6379, db=0) +>>> r.set('foo', 'bar') +True +>>> r.get('foo') +b'bar' +``` + +The above code connects to localhost on port 6379, sets a value in Redis, and retrieves it. All responses are returned as bytes in Python, to receive decoded strings, set *decode_responses=True*. For this, and more connection options, see [these examples](https://redis.readthedocs.io/en/stable/examples.html). + + +#### RESP3 Support +To enable support for RESP3, ensure you have at least version 5.0 of the client, and change your connection object to include *protocol=3* + +``` python +>>> import redis +>>> r = redis.Redis(host='localhost', port=6379, db=0, protocol=3) +``` + +### Connection Pools + +By default, redis-py uses a connection pool to manage connections. Each instance of a Redis class receives its own connection pool. You can however define your own [redis.ConnectionPool](https://redis.readthedocs.io/en/stable/connections.html#connection-pools). + +``` python +>>> pool = redis.ConnectionPool(host='localhost', port=6379, db=0) +>>> r = redis.Redis(connection_pool=pool) +``` + +Alternatively, you might want to look at [Async connections](https://redis.readthedocs.io/en/stable/examples/asyncio_examples.html), or [Cluster connections](https://redis.readthedocs.io/en/stable/connections.html#cluster-client), or even [Async Cluster connections](https://redis.readthedocs.io/en/stable/connections.html#async-cluster-client). + +### Redis Commands + +There is built-in support for all of the [out-of-the-box Redis commands](https://redis.io/commands). They are exposed using the raw Redis command names (`HSET`, `HGETALL`, etc.) except where a word (i.e. del) is reserved by the language. The complete set of commands can be found [here](https://github.com/redis/redis-py/tree/master/redis/commands), or [the documentation](https://redis.readthedocs.io/en/stable/commands.html). + +## Advanced Topics + +The [official Redis command documentation](https://redis.io/commands) +does a great job of explaining each command in detail. redis-py attempts +to adhere to the official command syntax. There are a few exceptions: + +- **MULTI/EXEC**: These are implemented as part of the Pipeline class. + The pipeline is wrapped with the MULTI and EXEC statements by + default when it is executed, which can be disabled by specifying + transaction=False. See more about Pipelines below. + +- **SUBSCRIBE/LISTEN**: Similar to pipelines, PubSub is implemented as + a separate class as it places the underlying connection in a state + where it can\'t execute non-pubsub commands. Calling the pubsub + method from the Redis client will return a PubSub instance where you + can subscribe to channels and listen for messages. You can only call + PUBLISH from the Redis client (see [this comment on issue + #151](https://github.com/redis/redis-py/issues/151#issuecomment-1545015) + for details). + +For more details, please see the documentation on [advanced topics page](https://redis.readthedocs.io/en/stable/advanced_features.html). + +### Pipelines + +The following is a basic example of a [Redis pipeline](https://redis.io/docs/manual/pipelining/), a method to optimize round-trip calls, by batching Redis commands, and receiving their results as a list. + + +``` python +>>> pipe = r.pipeline() +>>> pipe.set('foo', 5) +>>> pipe.set('bar', 18.5) +>>> pipe.set('blee', "hello world!") +>>> pipe.execute() +[True, True, True] +``` + +### PubSub + +The following example shows how to utilize [Redis Pub/Sub](https://redis.io/docs/manual/pubsub/) to subscribe to specific channels. + +``` python +>>> r = redis.Redis(...) +>>> p = r.pubsub() +>>> p.subscribe('my-first-channel', 'my-second-channel', ...) +>>> p.get_message() +{'pattern': None, 'type': 'subscribe', 'channel': b'my-second-channel', 'data': 1} +``` + + +-------------------------- + +### Author + +redis-py is developed and maintained by [Redis Inc](https://redis.com). It can be found [here]( +https://github.com/redis/redis-py), or downloaded from [pypi](https://pypi.org/project/redis/). + +Special thanks to: + +- Andy McCurdy () the original author of redis-py. +- Ludovico Magnocavallo, author of the original Python Redis client, + from which some of the socket code is still used. +- Alexander Solovyov for ideas on the generic response callback + system. +- Paul Hubbard for initial packaging support. + +[![Redis](./docs/logo-redis.png)](https://www.redis.com) + diff --git a/.venv/Lib/site-packages/redis-5.0.1.dist-info/RECORD b/.venv/Lib/site-packages/redis-5.0.1.dist-info/RECORD new file mode 100644 index 00000000..f6d8c78e --- /dev/null +++ b/.venv/Lib/site-packages/redis-5.0.1.dist-info/RECORD @@ -0,0 +1,147 @@ +redis-5.0.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +redis-5.0.1.dist-info/LICENSE,sha256=pXslClvwPXr-VbdAYzE_Ktt7ANVGwKsUmok5gzP-PMg,1074 +redis-5.0.1.dist-info/METADATA,sha256=xLwWid1Pns_mCEX6qn3qtFxtf7pphgPFPWOwEg5LWrQ,8910 +redis-5.0.1.dist-info/RECORD,, +redis-5.0.1.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92 +redis-5.0.1.dist-info/top_level.txt,sha256=OMAefszlde6ZoOtlM35AWzpRIrwtcqAMHGlRit-w2-4,6 +redis/__init__.py,sha256=PthSOEfXKlYV9xBgroOnO2tJD7uu0BWwvztgsKUvK48,2110 +redis/__pycache__/__init__.cpython-311.pyc,, +redis/__pycache__/backoff.cpython-311.pyc,, +redis/__pycache__/client.cpython-311.pyc,, +redis/__pycache__/cluster.cpython-311.pyc,, +redis/__pycache__/compat.cpython-311.pyc,, +redis/__pycache__/connection.cpython-311.pyc,, +redis/__pycache__/crc.cpython-311.pyc,, +redis/__pycache__/credentials.cpython-311.pyc,, +redis/__pycache__/exceptions.cpython-311.pyc,, +redis/__pycache__/lock.cpython-311.pyc,, +redis/__pycache__/ocsp.cpython-311.pyc,, +redis/__pycache__/retry.cpython-311.pyc,, +redis/__pycache__/sentinel.cpython-311.pyc,, +redis/__pycache__/typing.cpython-311.pyc,, +redis/__pycache__/utils.cpython-311.pyc,, +redis/_parsers/__init__.py,sha256=qkfgV2X9iyvQAvbLdSelwgz0dCk9SGAosCvuZC9-qDc,550 +redis/_parsers/__pycache__/__init__.cpython-311.pyc,, +redis/_parsers/__pycache__/base.cpython-311.pyc,, +redis/_parsers/__pycache__/commands.cpython-311.pyc,, +redis/_parsers/__pycache__/encoders.cpython-311.pyc,, +redis/_parsers/__pycache__/helpers.cpython-311.pyc,, +redis/_parsers/__pycache__/hiredis.cpython-311.pyc,, +redis/_parsers/__pycache__/resp2.cpython-311.pyc,, +redis/_parsers/__pycache__/resp3.cpython-311.pyc,, +redis/_parsers/__pycache__/socket.cpython-311.pyc,, +redis/_parsers/base.py,sha256=95SoPNwt4xJQB-ONIjxsR46n4EHnxnmkv9f0ReZSIR0,7480 +redis/_parsers/commands.py,sha256=pmR4hl4u93UvCmeDgePHFc6pWDr4slrKEvCsdMmtj_M,11052 +redis/_parsers/encoders.py,sha256=X0jvTp-E4TZUlZxV5LJJ88TuVrF1vly5tuC0xjxGaSc,1734 +redis/_parsers/helpers.py,sha256=xcRjjns6uQPb2pp0AOlOK9LhMJL4ofyEMFqVA7CwzsE,27947 +redis/_parsers/hiredis.py,sha256=X8yk0ElEEjHlhUgjs9fdHSOijlxYtunTrTJSLzkGrvQ,7581 +redis/_parsers/resp2.py,sha256=f22kH-_ZP2iNtOn6xOe65MSy_fJpu8OEn1u_hgeeojI,4813 +redis/_parsers/resp3.py,sha256=rXDA0R-wjCj2vyGaaWEf50NXN7UFBzefRnK3NGzWz2E,9657 +redis/_parsers/socket.py,sha256=CKD8QW_wFSNlIZzxlbNduaGpiv0I8wBcsGuAIojDfJg,5403 +redis/asyncio/__init__.py,sha256=uoDD8XYVi0Kj6mcufYwLDUTQXmBRx7a0bhKF9stZr7I,1489 +redis/asyncio/__pycache__/__init__.cpython-311.pyc,, +redis/asyncio/__pycache__/client.cpython-311.pyc,, +redis/asyncio/__pycache__/cluster.cpython-311.pyc,, +redis/asyncio/__pycache__/connection.cpython-311.pyc,, +redis/asyncio/__pycache__/lock.cpython-311.pyc,, +redis/asyncio/__pycache__/retry.cpython-311.pyc,, +redis/asyncio/__pycache__/sentinel.cpython-311.pyc,, +redis/asyncio/__pycache__/utils.cpython-311.pyc,, +redis/asyncio/client.py,sha256=BYurDT13lsw0N3a8sLqQFl00tFFolpET7_EujLw2Nbc,58826 +redis/asyncio/cluster.py,sha256=a0Za2icr03ytjF_WVohDMvEZejixUdVMhpsKWeMxYHY,63076 +redis/asyncio/connection.py,sha256=ZwClasZ2x0SQY90gDZvraFIx2lhGPnDm-xUUPPsb424,43426 +redis/asyncio/lock.py,sha256=lLasXEO2E1CskhX5ZZoaSGpmwZP1Q782R3HAUNG3wD4,11967 +redis/asyncio/retry.py,sha256=SnPPOlo5gcyIFtkC4DY7HFvmDgUaILsJ3DeHioogdB8,2219 +redis/asyncio/sentinel.py,sha256=sTVJCbi1KtIbHJc3fkHRZb_LGav_UtCAq-ipxltkGsE,14198 +redis/asyncio/utils.py,sha256=Yxc5YQumhLjtDDwCS4mgxI6yy2Z21AzLlFxVbxCohic,704 +redis/backoff.py,sha256=x-sAjV7u4MmdOjFZSZ8RnUnCaQtPhCBbGNBgICvCW3I,2966 +redis/client.py,sha256=IkqYEPg2WA35jBjPCpEgcKcVW3Hx8lm89j_IQ2dnoOw,57514 +redis/cluster.py,sha256=HcH2YM057xpWMQhGYBLWv5l9yrb7hzcSuPXXbqJl_DY,92754 +redis/commands/__init__.py,sha256=cTUH-MGvaLYS0WuoytyqtN1wniw2A1KbkUXcpvOSY3I,576 +redis/commands/__pycache__/__init__.cpython-311.pyc,, +redis/commands/__pycache__/cluster.cpython-311.pyc,, +redis/commands/__pycache__/core.cpython-311.pyc,, +redis/commands/__pycache__/helpers.cpython-311.pyc,, +redis/commands/__pycache__/redismodules.cpython-311.pyc,, +redis/commands/__pycache__/sentinel.cpython-311.pyc,, +redis/commands/bf/__init__.py,sha256=ESmQXH4p9Dp37tNCwQGDiF_BHDEaKnXSF7ZfASEqkFY,8027 +redis/commands/bf/__pycache__/__init__.cpython-311.pyc,, +redis/commands/bf/__pycache__/commands.cpython-311.pyc,, +redis/commands/bf/__pycache__/info.cpython-311.pyc,, +redis/commands/bf/commands.py,sha256=kVWUatdS0zLcu8-fVIqLLQBU5u8fJWIOCVUD3fqYVp0,21462 +redis/commands/bf/info.py,sha256=tpE4hv1zApxoOgyV9_8BEDZcl4Wf6tS1dSvtlxV7uTE,3395 +redis/commands/cluster.py,sha256=5BDwdeUnWVWOalF5fHD12HPQeDq_rc2vhuCI3sChrYE,31562 +redis/commands/core.py,sha256=2WM9nZ3f0Xqny8o5yucORe0fLRItJO4SWU68W5Wr1mw,223552 +redis/commands/graph/__init__.py,sha256=NmklyOuzIa20yEWrhnKQxgQlaXKYkcwBkGHpvQyo5J8,7237 +redis/commands/graph/__pycache__/__init__.cpython-311.pyc,, +redis/commands/graph/__pycache__/commands.cpython-311.pyc,, +redis/commands/graph/__pycache__/edge.cpython-311.pyc,, +redis/commands/graph/__pycache__/exceptions.cpython-311.pyc,, +redis/commands/graph/__pycache__/execution_plan.cpython-311.pyc,, +redis/commands/graph/__pycache__/node.cpython-311.pyc,, +redis/commands/graph/__pycache__/path.cpython-311.pyc,, +redis/commands/graph/__pycache__/query_result.cpython-311.pyc,, +redis/commands/graph/commands.py,sha256=rLGV58ZJKEf6yxzk1oD3IwiS03lP6bpbo0249pFI0OY,10379 +redis/commands/graph/edge.py,sha256=_TljVB4a1pPS9pb8_Cvw8rclbBOOI__-fY9fybU4djQ,2460 +redis/commands/graph/exceptions.py,sha256=kRDBsYLgwIaM4vqioO_Bp_ugWvjfqCH7DIv4Gpc9HCM,107 +redis/commands/graph/execution_plan.py,sha256=Pxr8_zhPWT_EdZSgGrbiWw8wFL6q5JF7O-Z6Xzm55iw,6742 +redis/commands/graph/node.py,sha256=Pasfsl5dF6WqT9KCNFAKKwGubyK_2ORCoAQE4VtnXkQ,2400 +redis/commands/graph/path.py,sha256=m6Gz4DYfMIQ8VReDLHlnQw_KI2rVdepWYk_AU0_x_GM,2080 +redis/commands/graph/query_result.py,sha256=GTEnBE0rAiUk4JquaxcVKdL1kzSMDWW5ky-iFTvRN84,17040 +redis/commands/helpers.py,sha256=WgfhdH3NCBW2Vqg-9PcP2EIKwzBkzb5CeqfdnPm2tTQ,4531 +redis/commands/json/__init__.py,sha256=llpDQz2kBNnJyfQfuh0-2oY-knMb6gAS0ADtPmaTKsM,4854 +redis/commands/json/__pycache__/__init__.cpython-311.pyc,, +redis/commands/json/__pycache__/_util.cpython-311.pyc,, +redis/commands/json/__pycache__/commands.cpython-311.pyc,, +redis/commands/json/__pycache__/decoders.cpython-311.pyc,, +redis/commands/json/__pycache__/path.cpython-311.pyc,, +redis/commands/json/_util.py,sha256=b_VQTh10FyLl8BtREfJfDagOJCyd6wTQQs8g63pi5GI,116 +redis/commands/json/commands.py,sha256=9P3NBFyWuRxWer5i__NtJx7oJZNnTOisfrHGhwaRfoA,15603 +redis/commands/json/decoders.py,sha256=a_IoMV_wgeJyUifD4P6HTcM9s6FhricwmzQcZRmc-Gw,1411 +redis/commands/json/path.py,sha256=0zaO6_q_FVMk1Bkhkb7Wcr8AF2Tfr69VhkKy1IBVhpA,393 +redis/commands/redismodules.py,sha256=7TfVzLj319mhsA6WEybsOdIPk4pC-1hScJg3H5hv3T4,2454 +redis/commands/search/__init__.py,sha256=happQFVF0j7P87p7LQsUK5AK0kuem9cA-xvVRdQWpos,5744 +redis/commands/search/__pycache__/__init__.cpython-311.pyc,, +redis/commands/search/__pycache__/_util.cpython-311.pyc,, +redis/commands/search/__pycache__/aggregation.cpython-311.pyc,, +redis/commands/search/__pycache__/commands.cpython-311.pyc,, +redis/commands/search/__pycache__/document.cpython-311.pyc,, +redis/commands/search/__pycache__/field.cpython-311.pyc,, +redis/commands/search/__pycache__/indexDefinition.cpython-311.pyc,, +redis/commands/search/__pycache__/query.cpython-311.pyc,, +redis/commands/search/__pycache__/querystring.cpython-311.pyc,, +redis/commands/search/__pycache__/reducers.cpython-311.pyc,, +redis/commands/search/__pycache__/result.cpython-311.pyc,, +redis/commands/search/__pycache__/suggestion.cpython-311.pyc,, +redis/commands/search/_util.py,sha256=VAguSwh_3dNtJwNU6Vle2CNdPE10_NUkPffD7GWFX48,193 +redis/commands/search/aggregation.py,sha256=8yQ1P31Qiy29xehlmN2ToCh73e-MHmOg_y0_UXfQDS8,10772 +redis/commands/search/commands.py,sha256=dpSMZ7hXjbAlrUL4h5GX6BtP4WibQZCO6Ylfo8qkAF0,36751 +redis/commands/search/document.py,sha256=g2R-PRgq-jN33_GLXzavvse4cpIHBMfjPfPK7tnE9Gc,413 +redis/commands/search/field.py,sha256=WxtOHgtm9S82_C0nzeT7fHRrWPkGflJnSXQRIiaVJmU,4518 +redis/commands/search/indexDefinition.py,sha256=VL2CMzjxN0HEIaTn88evnHX1fCEmytbik4vAmiiYSC8,2489 +redis/commands/search/query.py,sha256=blBcgFnurT9rkg4gI6j14EekWU_J9e_aDlryVCCWDjM,11564 +redis/commands/search/querystring.py,sha256=dE577kOqkCErNgO-IXI4xFVHI8kQE-JiH5ZRI_CKjHE,7597 +redis/commands/search/reducers.py,sha256=Scceylx8BjyqS-TJOdhNW63n6tecL9ojt4U5Sqho5UY,4220 +redis/commands/search/result.py,sha256=4H7LnOVWScti7WO2XYxjhiTu3QNIt2pZHO1eptXZDBk,2149 +redis/commands/search/suggestion.py,sha256=V_re6suDCoNc0ETn_P1t51FeK4pCamPwxZRxCY8jscE,1612 +redis/commands/sentinel.py,sha256=hRcIQ9x9nEkdcCsJzo6Ves6vk-3tsfQqfJTT_v3oLY0,4110 +redis/commands/timeseries/__init__.py,sha256=gkz6wshEzzQQryBOnrAqqQzttS-AHfXmuN_H1J38EbM,3459 +redis/commands/timeseries/__pycache__/__init__.cpython-311.pyc,, +redis/commands/timeseries/__pycache__/commands.cpython-311.pyc,, +redis/commands/timeseries/__pycache__/info.cpython-311.pyc,, +redis/commands/timeseries/__pycache__/utils.cpython-311.pyc,, +redis/commands/timeseries/commands.py,sha256=bFdk-609CnL-dTqMU5yQEiY-UCjVpLknHGDENQ2t-1U,33438 +redis/commands/timeseries/info.py,sha256=5deBInBtLPb3ZrVoSB4EhWkRPkSIW5Qd_98rMDnutnk,3207 +redis/commands/timeseries/utils.py,sha256=o7q7Fe1wgpdTLKyGY8Qi2VV6XKEBprhzmPdrFz3OIvo,1309 +redis/compat.py,sha256=tr-t9oHdeosrK3TvZySaLvP3ZlGqTZQaXtlTqiqp_8I,242 +redis/connection.py,sha256=fxHl5icHS3Mk2AhHeSGxcpMcY5aeHmq5589g2XyI_xg,50524 +redis/crc.py,sha256=Z3kXFtkY2LdgefnQMud1xr4vG5UYvA9LCMqNMX1ywu4,729 +redis/credentials.py,sha256=6VvFeReFp6vernGIWlIVOm8OmbNgoFYdd1wgsjZTnlk,738 +redis/exceptions.py,sha256=AzWeYEpVR1koUddMgvz0WZxmPX_jyksagoRf8FSSWKA,5103 +redis/lock.py,sha256=CwB_qo7ADDGSt_JqjQKSL1nKDCwdb-ASJsAlv0JO6mA,11564 +redis/ocsp.py,sha256=WwiGby6yZYR0D3lgnnQYmPKy-UAgYqGXi6A4jDBZGL4,11450 +redis/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +redis/retry.py,sha256=Ssp9s2hhDfyRs0rCRCaTgRtLR7NAYO5QMw4QflourGo,1817 +redis/sentinel.py,sha256=CErsD-c3mYFnXDttCY1OvpyUdfKcyD5F9Jv9Fd3iHuU,14175 +redis/typing.py,sha256=wjyihEjyGiJrigcs0-zhy7K-MzVy7uLidjszNdPHMug,2212 +redis/utils.py,sha256=87p7ImnihyIhiaqalVYh9Qq9JeaVwi_Y4GBzNaHAXJg,3381 diff --git a/.venv/Lib/site-packages/redis-5.0.1.dist-info/WHEEL b/.venv/Lib/site-packages/redis-5.0.1.dist-info/WHEEL new file mode 100644 index 00000000..7e688737 --- /dev/null +++ b/.venv/Lib/site-packages/redis-5.0.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.41.2) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/.venv/Lib/site-packages/redis-5.0.1.dist-info/top_level.txt b/.venv/Lib/site-packages/redis-5.0.1.dist-info/top_level.txt new file mode 100644 index 00000000..7800f0fa --- /dev/null +++ b/.venv/Lib/site-packages/redis-5.0.1.dist-info/top_level.txt @@ -0,0 +1 @@ +redis diff --git a/.venv/Lib/site-packages/redis/__init__.py b/.venv/Lib/site-packages/redis/__init__.py new file mode 100644 index 00000000..495d2d99 --- /dev/null +++ b/.venv/Lib/site-packages/redis/__init__.py @@ -0,0 +1,94 @@ +import sys + +from redis import asyncio # noqa +from redis.backoff import default_backoff +from redis.client import Redis, StrictRedis +from redis.cluster import RedisCluster +from redis.connection import ( + BlockingConnectionPool, + Connection, + ConnectionPool, + SSLConnection, + UnixDomainSocketConnection, +) +from redis.credentials import CredentialProvider, UsernamePasswordCredentialProvider +from redis.exceptions import ( + AuthenticationError, + AuthenticationWrongNumberOfArgsError, + BusyLoadingError, + ChildDeadlockedError, + ConnectionError, + DataError, + InvalidResponse, + OutOfMemoryError, + PubSubError, + ReadOnlyError, + RedisError, + ResponseError, + TimeoutError, + WatchError, +) +from redis.sentinel import ( + Sentinel, + SentinelConnectionPool, + SentinelManagedConnection, + SentinelManagedSSLConnection, +) +from redis.utils import from_url + +if sys.version_info >= (3, 8): + from importlib import metadata +else: + import importlib_metadata as metadata + + +def int_or_str(value): + try: + return int(value) + except ValueError: + return value + + +try: + __version__ = metadata.version("redis") +except metadata.PackageNotFoundError: + __version__ = "99.99.99" + + +try: + VERSION = tuple(map(int_or_str, __version__.split("."))) +except AttributeError: + VERSION = tuple([99, 99, 99]) + +__all__ = [ + "AuthenticationError", + "AuthenticationWrongNumberOfArgsError", + "BlockingConnectionPool", + "BusyLoadingError", + "ChildDeadlockedError", + "Connection", + "ConnectionError", + "ConnectionPool", + "CredentialProvider", + "DataError", + "from_url", + "default_backoff", + "InvalidResponse", + "OutOfMemoryError", + "PubSubError", + "ReadOnlyError", + "Redis", + "RedisCluster", + "RedisError", + "ResponseError", + "Sentinel", + "SentinelConnectionPool", + "SentinelManagedConnection", + "SentinelManagedSSLConnection", + "SSLConnection", + "UsernamePasswordCredentialProvider", + "StrictRedis", + "TimeoutError", + "UnixDomainSocketConnection", + "WatchError", +] diff --git a/.venv/Lib/site-packages/redis/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/redis/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..781551897c448191e46c22b9a8add6e235c6a2c0 GIT binary patch literal 2816 zcmd5-%}*Og6rc6l*!W`&<|9D(Fvdx7DA2T}Q9cwYfh3I}fN)5Z5t6m+4rG&^T{OE( zLX?A5Rcb2rKu_tdQ4X!DUV7<2ko*HCvQ%rNNRfKthLj7+sq=O*#z{`?rMt5~&%F2M zea)NaUsI_#63=)2f0Bzag#Ly_{Sj;bd0UeZdWv+UOD4kb8!{yt!XXLfvMJLr4*T=4 z8KEt>g+_7IUq{RsZN;tryv2;u1WwQ-PSO-kQ3WeBjnh6aYPQjK+)gt% z&eIe41U-pQ`t-Q@2_40w5+dkcp&q85xF3Nzi;8HH<|#Uc$0THh{dhmcV|waagvVP^ z2$8XS6NkH$Uqn`Z7hmw;Nh>n~5}(y6dBh^ZY8p@85!xQ0hw>ftK=SpR7P>ws<7D#L z7j@~Qzj|AjrfHq5sh;VUR#ol3y|z{e@yHU<4TmR+E;BUOUkJgZKbbZ?$0e)~ z;oX-_Tf1*q>(jPn5zRGhYtgn%9&fC<(wO_aRIxbMAo0Fs%Xm0rQ`NAFLKkrxJmE%W znh~8?uA!QX%-%F~!gy}kAN7;uAzq>f)O5qufY3Uly6OS%y0xjA zhQ36c4cl@EZ(H!(g|!=m+H5NjNi2G+MQ=4&q?Uy81z+FgHM2=iDGBDRRhyX&)tkAC)h>+~C{rLGgb!RGz%v6{|F9DZz#*|g*_vk=;q zMG@^n#{fDduBwa3wZrQn7-8{&)Z429o}yOd9^pPl%>`RTBgj20d4z(?^cZQOJE(~2 zm#HAli;|EH%jNM~s_Bs+Y>7uisy*U>f$X~*Gv`(`8_sTJ*|a zXeJIiiEo}K1Da+UqC5k`psOyc1^vW#hPNHa9yXL9Tt7%ZKHnd3fVUrril3lGI6?5> zY+Vm|sF4k50M3yFHge~u%}>_HQq)L{A2kHbmB6TTaM3=NGM)%zJl8NC{}gy~lQ2hk zAqs2F=B)c*NN-4VOo6U0Et#Uzq30C0F$ERnHBs43Cyds%e%=zoECnK4S3i_%3#V+PY_w zi|mS6!ew%vi#sU_SCVQdUiRNNsJGHQYN$|Y9yK&p`PitTla=PN7iy70d+5J{f}~}s zf^L2|_Cjee@c)Hu1pNDVkVMjO1!a$pH*!l=?%3XZB@a~Ofm%3M`Cz;W7b^9!*AkXQ zvpNJtmIi8>-1cZSlY4e%Co@*fjFo50v-`DZx*E-k-X;w+pqA+eW_cD$WI*(`y_hWJ zYD&iwvOT>${Zste>|gn*SNW+ww4MC9YX00#=lN>q`5om#Rk={UR=y_GLaUT=4G4D6 zZHsqD8LleBAXmNy7II*rWhf!?RflpEUI#AG3#sjL2EE86FAvKvvJ&8l(P;&}R5H^e J^2?kg@E;G9^rip+ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/__pycache__/backoff.cpython-311.pyc b/.venv/Lib/site-packages/redis/__pycache__/backoff.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..14997d304800d92cd8c0d8db2996ffbcaf122ef4 GIT binary patch literal 6000 zcmc&&&2JmW6`x%$$<+r%OSWXmlC7oU*rgq*NgCUUj~(_~1k9TJWVPTEM;aPap#V6&46!pr_m@NQc7cq3_LpkV{f_ z+)Ibrr`dV)@#ekXd-G=h6pM8eC|`~JjsCuekbmKeSHf;(s}7a>L?^nCCu#gI=7oZo z77L+tNFaJBE$LD^ERv6i9==2L2o)cN2zdgJQ_>O6ivmxkkrrN*^SXf7O`|P5ne%#p z*V{I(i}PZ@>uck6b6y;HyV`g?oYxP$fi_;RzWWYI$8_N`N$&Xpg-<0#J2X9W#_rP= zOp9q5t3a(qL%;f;_08`-TX=Tbt*o5RxSQqwME7ND3M%&rC22t?X;Bx_Azg$eBpTL3 zcgQ2)K5@Gel8)#SEF8Au)9zX`TIM%KHe2p@D@v|tQI^#*G$Z)K2*Elkdn*D2429y0 z+liX!$(V6{DDe z&X!^=;?S$PVlh{|su)>+2)#ksE#6zP3}yZjwb-pG9IXB}XDzA>-{<|_sdch0*pf-} zSrf%qo?ke7axP=&FzejsM)u0buyu3p5-rfe0tIO@6a<)?xq~%>sR8@5&qpGYI1~Caq zKN6ITPsGJwh#5{$RP!v575}#(jaH=5x)ce=>cl6zNMui46tNA+W(Z#IeA#H=th&wihq!V8DA_K`NJm$MVn(=bDA|0+vVpu^GxI`Ah`|G5g zI2ggH0vPeUa0^BLss$yhBr8A!mDAEHxhbT>5a~j8SITfzUEZ5Ad{YLn;UN#^bh5N*6;s#^#!zK<6b&4)Lg7zmq4-P@JjF@65JRBKevjjnvE71c@m#Sv+nrW)4 zW3&~={ZP;40e=HNR+7+eCV>2Vg?ul^zK-6F{!pFaWy7)wxS(# zSI$rf#%fYv2XSr`{zFFw1*#0mA$ZIWfWV^OZ$nB{q(og3!eeN}A443&;)I|iY&5P{&?4N}2q$o+Kpn4N45MR1B21npu_bU9jQ37EGqchjc z3{-+n03pZM3e-`Dyy(KRP=*7f47uSWXno>yFy%=7fUn??p+c_6-heurMAA7@?dz}? zH&|g*F~@-b_TvNh-udReHT}W0$8SAeTz|iM;CMBDq82|BzIuLyzb1Fx=Nlb_wBk(L-8^ z;|(}z1|Gk7n%jB>Z|FZ?%I9Zu79@ebGhmZ)jkoy#4MaXPu~%?WZt@AJyxbWWMj>_- z2_~`~0J*PCB0qwi#$j(E!6Pq#Jj}hg7>iH|BCmlvU9h|x2=oFJ`Wu0|1Wml?;!cQc z!)M3|&+KO~5VGtD(~7!Lu%o474pQL)dk5NIirSI(4ZEQI2!@-eD+KM}-QTTgf871> z${&9HXX&rqPcQyM{`(izH$Sc>KB*->sm5n(@!5(z>j0P?!MCe;Bnv_=9@u4CV1Qb50RtoGWn29!ESeeq#q1#LZ2Wc zUp*M=LK#y0+v2ilMSTSaK`RE~S%z+y%cM9uoirlcibzBP`#F%Lb5=0S4{gb!g{7ct zV%}EX*Fh03RDT70^CXZL#n-2aYW)3G39`j+v)>dSUVJQ7hbC)7lhycSMV@>Ca=GIp z`4pF#;mdf~-H?t}q@yngqGEUoQ^!`~fEFk14B8{Wd3j0!iG{3V&KR*r&cd~gF`9?F zupUJ4Pnub;4rDxsUlv*+>+t*yzNVnz8Sa4FJq0iR*=hHyON`#g870%Zh3piHCz{0$ z?8wLem#~JZ0BKJVHWCx7QcXTk;eTA+fo}{bE)UtxeF_qR=KB<2mrXzqNG{LAKZXI` zxz{_%3tmCX<2wt;ujN;95JDOPTnA}>&-918k$vyq{nFTay2q4;o<4?%M2WJz3czKb_}KPmCV&~f%2=XeMJ$Dl&;^feJFe5LR?1txkv@aI*WoeyfPlJt_E&qxYdzx?X`D-v>|~^X4s}^^hP48zi>Ee;eer zN~gbigv9r(^gIL7TaWY!@TsSr+{vn@RAq#NRZzuPRO>Et6u!bZ7Zj$ZfUVIZ< zw;Qa!UI8-dcCt3UiLKiW)`4CD^PSFg4JJko_V;@ohzW4ev=f{gTDKc4Ww!ueY9|k2 TT4>#Fu-*^^`0mk8xUv5WSpn>u literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/__pycache__/client.cpython-311.pyc b/.venv/Lib/site-packages/redis/__pycache__/client.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5129a5ac3ffe80d8e9d2471ea9729a5b657a4e08 GIT binary patch literal 70974 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 Fe*vQTp4I>W literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/__pycache__/compat.cpython-311.pyc b/.venv/Lib/site-packages/redis/__pycache__/compat.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ff20bc50c2094eee10a7f495474eadf9b049ce5d GIT binary patch literal 487 zcmah@yGjE=6uq-Eo0mo~wsx9g3$+kah*(8X3=%XJ2@A5>9mC?z&N8#+0aiA4w*G)1 zet`dxa@p3(ZZXZ0%Gvk`HhMX8=3MT%hx=46mq69s>I;2W|7+HK7x@yCrVmVws14r}p%rVng=^tl%<{iKgw_$(`{Vj_(aGYfiy)LlC?kieNu6WKLFS9D_J;#@ciT)#J)%_s4~5ev8o4}{<%UjFo4 z&|ye@>2hB_!$j@F^tirj+T2kA<~hG?9a{F4G*2m`tV;!zHuY_4ZuY6)Hydu(lhM(W8MMF~a-C4`__M7GEOA&v5t1T<8e hQ$&pMZ$xBg{3jA!C8TL8vrBGEOK`tZ#gC|pKLC0KhXeos literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/__pycache__/connection.cpython-311.pyc b/.venv/Lib/site-packages/redis/__pycache__/connection.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eaad95c133152bfa3855cf840d60c21f403ab346 GIT binary patch literal 58490 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 ibuf=S3ScE0zyTawk+VS(C`ec(3Jwt!hlyHH z@u5e-YzRlvC?4Gr0ppSvGO4K-@7)I&o_9CF6+p1PJ!>FI@AnY5>XkEiCVW{Gf5rG!_hV?yrx5(K2c9J~j$g&L>>>)(QIVyaILbc?oa6*?+gGG?e|@#~S-yC6NiD!ws}|uc17aPY9zg zO~ieV-CYCW;K8^Jsjeaf?5Xt^Ny9d)w!w)86lj7bt>9A4&{nKf;t1n(L<30^qTM7l zreTY5YUQikaviMaf5PC zAr5AOdXfM4)Z9!C+QM>Ha?5TZlQPT_%Po;IDd!0#%p{IUa??=rYHq>G=a|LGR0W)j z6~c0USqW&d=}L`?Uhvfr0Oo>PL;WE%eE3;vGu6s$EIwUao9~5&*6G9gTD>=NOB=IKXWMr^L?^m|i2*!`7UN+roVOf{q;0^7v&ubN^l8VYH{4?@G zx^CFEu6qj5>Sz8M(WBxx2I_nGGJIpzCReCvA;B*bz1UYIN$R2T?!oaDo$MYQ{V*B_ q+t}CWX!rQJZsh!0sIQ{4NvV&b(kWlHCjF(8^p|(+_sPGIpW9CJh2(0fe{mlPV2>A<@{?dEG$qER2gb_w-q)yAUu9TI!T2?7h$Q{Cz9m3QDc>5VV z$tr8HM+1+}wF4D=@br8-Gge74^8(eP8kt`-LND;0TBP4=HflW5*L=|3-uC#%=qV?k zfv`t7DN{zu3ZrF}DO}?^H{MS7qsEP@GO&!wOx@AS8KyxJdNh4oaK`=6b80Ih*z_0| zt(gf6*1#dHzH1@&M26sDQ}`}TV-kY(;d5dE?2&ND$LIlQ&r-`HT2xA{xeXrLZW>)$ z^`;E1b#8fe=t3QG;;cxcd?^U;4lJJv5r{(?X_D8f5|6ZAuY7X7;s(s~H!5pE_1?1M zej_Vi!V&d#F1U2L@AAsRCigchpL^>S>4p4i12#DuTvi|fPc9DSvCw!JO^xN&njLf_ z?Zw!hGmwjX3t*f4k-O5Fz4Lo+`FU=+V=kY7k(7#NWZJgx)VXa(6SiFsShI%mq-}rO zbZR|M#2wzpkR_W|ttCRKH8x7uwCI ztNX1VuN~!&+@r!zA9v=Lo?p4$CFuQkOhRI`(QqV*IaEXe_6clIQ5BOYrv{0q!u-XzjFjXh=W)>H z+l8ld``V^Zw=^MBVcD1HD=$Ct7F)v$LuOCk3+p;Nr^63wqp@x{gc E4J1#$wg3PC literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/__pycache__/exceptions.cpython-311.pyc b/.venv/Lib/site-packages/redis/__pycache__/exceptions.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ae8f83a086aafeadce194a431f1f3a0cee966458 GIT binary patch literal 10258 zcmbVROKcq1m91_z$tFeWOG=_7+vP~HMTH+vqKspXte7GdiH=AbByAxAC+%X_BUxd0 zRr^&ne?w!m2qqe27EBPp%p|~Qk$56_77365K^9qM8$brKU>XPzAgin*fm{S$<(ymn zuNK9gCi-^qo%`N>pZk6Fzun!P20q`p@GJGVQ-<*u{!{w26(9C=i(!0Z*v360Zrn2L z*tZQku3{gf^%H!<&%L-{Ex-~gUWc^^)(WgGf+YlN2bNSVb^Tfe>j2gn!P*2n0<0^7 zwF}k_>}W(@Qm|vdjz_Q#!A<}>8NoUQI|ZyKf*ld87ue|t)+N{(U}sfF-TJx(>jQQ! zf*lp?Jg^H9?3iFL0DCcl9T)5+U}gk6A=t~nJ{Q4G3U(3LB^6hvK2G3t@hzTikD#9i z`iknQTSc#6uL8Rq(TdZ8^#i*Sk$6V1F8~{e^gAoqAh4mxj`j&Q4D2=4hf!;1dQQ-P z0{X>>#PfoE3E0&Lc0sT&1N-L)_JUxq1N(|PU$^=f1$zV7h&oq?y(HMb0K2Bn)?ub# zZvwj>(chQtug)6%Z*5)~^RzP6dRpZI$8&vCTaK@6b78{_mX$f9Y{xg#8ArK6x^z_h zjTQgdJBo*o3}xJl!FuC%45P*iozm~7)}Eev)KW;MQm&O%sZ^memCAZ{KEvm(RO*Ag zl?jnY#vVufYWp(O0W3yGb*dH3rZ_Lt=zPlA6ixJ>iivNVcvHF zHJAgFwWR!c&DjoD7BiIFpkpzFP}BB~f!r_u?Ix1<$8|@EqlpC`8}nROrMYF{Dm91K zNfH^4K2LX-h_oLmgKTd?Sl67BRbDur^R5-7mk*Hh5{D-lsFlN}CggNad9!Kl zkT3%3-GPv?W_#YvU*^oA_XdN*bmohCjLu1y

vRS%{4d$Q#tSrdPMr0=9OY>$Xe@g&X6#e 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 ZRIL50_)}gNPOowK8T1%MDv&^}(qs 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/__pycache__/retry.cpython-311.pyc b/.venv/Lib/site-packages/redis/__pycache__/retry.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..526add448ae66758c8161210698d0eff6eec9ffd GIT binary patch literal 2771 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/_parsers/__pycache__/base.cpython-311.pyc b/.venv/Lib/site-packages/redis/_parsers/__pycache__/base.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a75cac1b36971aa3c2e37e2c4410fc623ceafa10 GIT binary patch literal 11537 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/_parsers/__pycache__/commands.cpython-311.pyc b/.venv/Lib/site-packages/redis/_parsers/__pycache__/commands.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d5f50bfb98993d80c43c8aabda2e964ae107158d GIT binary patch literal 13138 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/_parsers/__pycache__/encoders.cpython-311.pyc b/.venv/Lib/site-packages/redis/_parsers/__pycache__/encoders.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..80d82a037a8f78555046f0c4935843512b1577c9 GIT binary patch literal 2580 zcmb7F&2JM&6rb^~zv8T&fYX?dhy@WGx50#dNEL!gRbomYic~&&u-vX3@0cz)yY9>; zZHyyD6;gfZ0V<@Vw5T}{DB{AU|3c4kwNkB>A|X{s?ae5(2Tpyn>ve1gRCVlqJ2UUi z``Y(=^H7rd5R7jQ{z85YAoK@cctdPWw#Q+zid3ZH5}L!ZRS{@F z4XJ^fI2%-hpf_v>GkU>L39X!QCo(gsre9^UX~=U+CSk`*+I1r5byZdgm+agHnU?q? z!446w3C`LvZ>A9LDYFOMqY5RgZ0L-zf|m-yNd6OQv$Tty1scSh9*E8JcQu=0Y1 z1VRXSmO`FUO0-2rN<|uk1r2c$2Ew=@8OF;`rcUKt|8iH1;^lMs!gZFrNao4>909)y z;4{gk7m2=@o6+WSOf$*xG6?0b5|*Px)z}H8oTrRXcEX7dCh78$9a0oc*GxsJ3}oC? zroA1_XvpiR=(IXu*xxcNU;s;>!aog_KxW@;l%3Wcz-#dlSE+3AV zu^n!;N9#KOPP@hf*m>OEUB>$99@~4`Ow=6%OPWJFyk2Y9A|7wq*A=U;>iYqZcTf0_ zm|ts`%2oX8SgPn+J3BC!JP*44UdH@OrNqjai^N=@x}0}W=0H(4XeZ_f557`d5ptA+&IJRg)TpW6Oex4}G4(L+?)XdoPI>`l~Wwxr=T|2?xV9kryR zO%x4BpY1u&^x?txo(sa>=nDj-i3BP7cL+rjYyJ&k|H>}~eYUj3GJCpe5 z_nQb0PU23w+j##Q5W}T<d@{91J&N@mfFS z@t-a5GS#sXu-TUA0LMaIU`yS9niZ@~dK}EZyUyu*V3H74$R`vm$a6iQ)5jJ>$N& zV*A!cH}=feq1h=2N*{3M;hPqG!klFo;^2I{F11`!#d4!yzav{e*7UhIj3HunxO8eIkCpX2(rvo3ZOgBZr4`^$Xz9Iim6SYY? z$d|7nt~G9BHYM17SgG(8{G#q2@HPQv1uSp0b|@iM>f0v T&A=E2^SjA&zW3r449C>JRWC#% literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/_parsers/__pycache__/helpers.cpython-311.pyc b/.venv/Lib/site-packages/redis/_parsers/__pycache__/helpers.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2fa674d7cb9045d65a9c9032e2a04d939a15530a GIT binary patch literal 47791 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 bhC*sDK#C!cTmW5Em5441P&@u*8@>M*DSn=t literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/_parsers/__pycache__/hiredis.cpython-311.pyc b/.venv/Lib/site-packages/redis/_parsers/__pycache__/hiredis.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0b8dbd8d505cebb42464bd9edd24221fbd07f27f GIT binary patch literal 10841 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 o8$#q7T}Vqfn`2H)ox%Jes?bDO03w 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/_parsers/base.py b/.venv/Lib/site-packages/redis/_parsers/base.py new file mode 100644 index 00000000..8e59249b --- /dev/null +++ b/.venv/Lib/site-packages/redis/_parsers/base.py @@ -0,0 +1,225 @@ +import sys +from abc import ABC +from asyncio import IncompleteReadError, StreamReader, TimeoutError +from typing import List, Optional, Union + +if sys.version_info.major >= 3 and sys.version_info.minor >= 11: + from asyncio import timeout as async_timeout +else: + from async_timeout import timeout as async_timeout + +from ..exceptions import ( + AuthenticationError, + AuthenticationWrongNumberOfArgsError, + BusyLoadingError, + ConnectionError, + ExecAbortError, + ModuleError, + NoPermissionError, + NoScriptError, + OutOfMemoryError, + ReadOnlyError, + RedisError, + ResponseError, +) +from ..typing import EncodableT +from .encoders import Encoder +from .socket import SERVER_CLOSED_CONNECTION_ERROR, SocketBuffer + +MODULE_LOAD_ERROR = "Error loading the extension. " "Please check the server logs." +NO_SUCH_MODULE_ERROR = "Error unloading module: no such module with that name" +MODULE_UNLOAD_NOT_POSSIBLE_ERROR = "Error unloading module: operation not " "possible." +MODULE_EXPORTS_DATA_TYPES_ERROR = ( + "Error unloading module: the module " + "exports one or more module-side data " + "types, can't unload" +) +# user send an AUTH cmd to a server without authorization configured +NO_AUTH_SET_ERROR = { + # Redis >= 6.0 + "AUTH called without any password " + "configured for the default user. Are you sure " + "your configuration is correct?": AuthenticationError, + # Redis < 6.0 + "Client sent AUTH, but no password is set": AuthenticationError, +} + + +class BaseParser(ABC): + EXCEPTION_CLASSES = { + "ERR": { + "max number of clients reached": ConnectionError, + "invalid password": AuthenticationError, + # some Redis server versions report invalid command syntax + # in lowercase + "wrong number of arguments " + "for 'auth' command": AuthenticationWrongNumberOfArgsError, + # some Redis server versions report invalid command syntax + # in uppercase + "wrong number of arguments " + "for 'AUTH' command": AuthenticationWrongNumberOfArgsError, + MODULE_LOAD_ERROR: ModuleError, + MODULE_EXPORTS_DATA_TYPES_ERROR: ModuleError, + NO_SUCH_MODULE_ERROR: ModuleError, + MODULE_UNLOAD_NOT_POSSIBLE_ERROR: ModuleError, + **NO_AUTH_SET_ERROR, + }, + "OOM": OutOfMemoryError, + "WRONGPASS": AuthenticationError, + "EXECABORT": ExecAbortError, + "LOADING": BusyLoadingError, + "NOSCRIPT": NoScriptError, + "READONLY": ReadOnlyError, + "NOAUTH": AuthenticationError, + "NOPERM": NoPermissionError, + } + + @classmethod + def parse_error(cls, response): + "Parse an error response" + error_code = response.split(" ")[0] + if error_code in cls.EXCEPTION_CLASSES: + response = response[len(error_code) + 1 :] + exception_class = cls.EXCEPTION_CLASSES[error_code] + if isinstance(exception_class, dict): + exception_class = exception_class.get(response, ResponseError) + return exception_class(response) + return ResponseError(response) + + def on_disconnect(self): + raise NotImplementedError() + + def on_connect(self, connection): + raise NotImplementedError() + + +class _RESPBase(BaseParser): + """Base class for sync-based resp parsing""" + + def __init__(self, socket_read_size): + self.socket_read_size = socket_read_size + self.encoder = None + self._sock = None + self._buffer = None + + def __del__(self): + try: + self.on_disconnect() + except Exception: + pass + + def on_connect(self, connection): + "Called when the socket connects" + self._sock = connection._sock + self._buffer = SocketBuffer( + self._sock, self.socket_read_size, connection.socket_timeout + ) + self.encoder = connection.encoder + + def on_disconnect(self): + "Called when the socket disconnects" + self._sock = None + if self._buffer is not None: + self._buffer.close() + self._buffer = None + self.encoder = None + + def can_read(self, timeout): + return self._buffer and self._buffer.can_read(timeout) + + +class AsyncBaseParser(BaseParser): + """Base parsing class for the python-backed async parser""" + + __slots__ = "_stream", "_read_size" + + def __init__(self, socket_read_size: int): + self._stream: Optional[StreamReader] = None + self._read_size = socket_read_size + + async def can_read_destructive(self) -> bool: + raise NotImplementedError() + + async def read_response( + self, disable_decoding: bool = False + ) -> Union[EncodableT, ResponseError, None, List[EncodableT]]: + raise NotImplementedError() + + +class _AsyncRESPBase(AsyncBaseParser): + """Base class for async resp parsing""" + + __slots__ = AsyncBaseParser.__slots__ + ("encoder", "_buffer", "_pos", "_chunks") + + def __init__(self, socket_read_size: int): + super().__init__(socket_read_size) + self.encoder: Optional[Encoder] = None + self._buffer = b"" + self._chunks = [] + self._pos = 0 + + def _clear(self): + self._buffer = b"" + self._chunks.clear() + + def on_connect(self, connection): + """Called when the stream connects""" + self._stream = connection._reader + if self._stream is None: + raise RedisError("Buffer is closed.") + self.encoder = connection.encoder + self._clear() + self._connected = True + + def on_disconnect(self): + """Called when the stream disconnects""" + self._connected = False + + async def can_read_destructive(self) -> bool: + if not self._connected: + raise RedisError("Buffer is closed.") + if self._buffer: + return True + try: + async with async_timeout(0): + return await self._stream.read(1) + except TimeoutError: + return False + + async def _read(self, length: int) -> bytes: + """ + Read `length` bytes of data. These are assumed to be followed + by a '\r\n' terminator which is subsequently discarded. + """ + want = length + 2 + end = self._pos + want + if len(self._buffer) >= end: + result = self._buffer[self._pos : end - 2] + else: + tail = self._buffer[self._pos :] + try: + data = await self._stream.readexactly(want - len(tail)) + except IncompleteReadError as error: + raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR) from error + result = (tail + data)[:-2] + self._chunks.append(data) + self._pos += want + return result + + async def _readline(self) -> bytes: + """ + read an unknown number of bytes up to the next '\r\n' + line separator, which is discarded. + """ + found = self._buffer.find(b"\r\n", self._pos) + if found >= 0: + result = self._buffer[self._pos : found] + else: + tail = self._buffer[self._pos :] + data = await self._stream.readline() + if not data.endswith(b"\r\n"): + raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR) + result = (tail + data)[:-2] + self._chunks.append(data) + self._pos += len(result) + 2 + return result diff --git a/.venv/Lib/site-packages/redis/_parsers/commands.py b/.venv/Lib/site-packages/redis/_parsers/commands.py new file mode 100644 index 00000000..b5109252 --- /dev/null +++ b/.venv/Lib/site-packages/redis/_parsers/commands.py @@ -0,0 +1,281 @@ +from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, Union + +from redis.exceptions import RedisError, ResponseError +from redis.utils import str_if_bytes + +if TYPE_CHECKING: + from redis.asyncio.cluster import ClusterNode + + +class AbstractCommandsParser: + def _get_pubsub_keys(self, *args): + """ + Get the keys from pubsub command. + Although PubSub commands have predetermined key locations, they are not + supported in the 'COMMAND's output, so the key positions are hardcoded + in this method + """ + if len(args) < 2: + # The command has no keys in it + return None + args = [str_if_bytes(arg) for arg in args] + command = args[0].upper() + keys = None + if command == "PUBSUB": + # the second argument is a part of the command name, e.g. + # ['PUBSUB', 'NUMSUB', 'foo']. + pubsub_type = args[1].upper() + if pubsub_type in ["CHANNELS", "NUMSUB", "SHARDCHANNELS", "SHARDNUMSUB"]: + keys = args[2:] + elif command in ["SUBSCRIBE", "PSUBSCRIBE", "UNSUBSCRIBE", "PUNSUBSCRIBE"]: + # format example: + # SUBSCRIBE channel [channel ...] + keys = list(args[1:]) + elif command in ["PUBLISH", "SPUBLISH"]: + # format example: + # PUBLISH channel message + keys = [args[1]] + return keys + + def parse_subcommand(self, command, **options): + cmd_dict = {} + cmd_name = str_if_bytes(command[0]) + cmd_dict["name"] = cmd_name + cmd_dict["arity"] = int(command[1]) + cmd_dict["flags"] = [str_if_bytes(flag) for flag in command[2]] + cmd_dict["first_key_pos"] = command[3] + cmd_dict["last_key_pos"] = command[4] + cmd_dict["step_count"] = command[5] + if len(command) > 7: + cmd_dict["tips"] = command[7] + cmd_dict["key_specifications"] = command[8] + cmd_dict["subcommands"] = command[9] + return cmd_dict + + +class CommandsParser(AbstractCommandsParser): + """ + Parses Redis commands to get command keys. + COMMAND output is used to determine key locations. + Commands that do not have a predefined key location are flagged with + 'movablekeys', and these commands' keys are determined by the command + 'COMMAND GETKEYS'. + """ + + def __init__(self, redis_connection): + self.commands = {} + self.initialize(redis_connection) + + def initialize(self, r): + commands = r.command() + uppercase_commands = [] + for cmd in commands: + if any(x.isupper() for x in cmd): + uppercase_commands.append(cmd) + for cmd in uppercase_commands: + commands[cmd.lower()] = commands.pop(cmd) + self.commands = commands + + # As soon as this PR is merged into Redis, we should reimplement + # our logic to use COMMAND INFO changes to determine the key positions + # https://github.com/redis/redis/pull/8324 + def get_keys(self, redis_conn, *args): + """ + Get the keys from the passed command. + + NOTE: Due to a bug in redis<7.0, this function does not work properly + for EVAL or EVALSHA when the `numkeys` arg is 0. + - issue: https://github.com/redis/redis/issues/9493 + - fix: https://github.com/redis/redis/pull/9733 + + So, don't use this function with EVAL or EVALSHA. + """ + if len(args) < 2: + # The command has no keys in it + return None + + cmd_name = args[0].lower() + if cmd_name not in self.commands: + # try to split the command name and to take only the main command, + # e.g. 'memory' for 'memory usage' + cmd_name_split = cmd_name.split() + cmd_name = cmd_name_split[0] + if cmd_name in self.commands: + # save the splitted command to args + args = cmd_name_split + list(args[1:]) + else: + # We'll try to reinitialize the commands cache, if the engine + # version has changed, the commands may not be current + self.initialize(redis_conn) + if cmd_name not in self.commands: + raise RedisError( + f"{cmd_name.upper()} command doesn't exist in Redis commands" + ) + + command = self.commands.get(cmd_name) + if "movablekeys" in command["flags"]: + keys = self._get_moveable_keys(redis_conn, *args) + elif "pubsub" in command["flags"] or command["name"] == "pubsub": + keys = self._get_pubsub_keys(*args) + else: + if ( + command["step_count"] == 0 + and command["first_key_pos"] == 0 + and command["last_key_pos"] == 0 + ): + is_subcmd = False + if "subcommands" in command: + subcmd_name = f"{cmd_name}|{args[1].lower()}" + for subcmd in command["subcommands"]: + if str_if_bytes(subcmd[0]) == subcmd_name: + command = self.parse_subcommand(subcmd) + is_subcmd = True + + # The command doesn't have keys in it + if not is_subcmd: + return None + last_key_pos = command["last_key_pos"] + if last_key_pos < 0: + last_key_pos = len(args) - abs(last_key_pos) + keys_pos = list( + range(command["first_key_pos"], last_key_pos + 1, command["step_count"]) + ) + keys = [args[pos] for pos in keys_pos] + + return keys + + def _get_moveable_keys(self, redis_conn, *args): + """ + NOTE: Due to a bug in redis<7.0, this function does not work properly + for EVAL or EVALSHA when the `numkeys` arg is 0. + - issue: https://github.com/redis/redis/issues/9493 + - fix: https://github.com/redis/redis/pull/9733 + + So, don't use this function with EVAL or EVALSHA. + """ + # The command name should be splitted into separate arguments, + # e.g. 'MEMORY USAGE' will be splitted into ['MEMORY', 'USAGE'] + pieces = args[0].split() + list(args[1:]) + try: + keys = redis_conn.execute_command("COMMAND GETKEYS", *pieces) + except ResponseError as e: + message = e.__str__() + if ( + "Invalid arguments" in message + or "The command has no key arguments" in message + ): + return None + else: + raise e + return keys + + +class AsyncCommandsParser(AbstractCommandsParser): + """ + Parses Redis commands to get command keys. + + COMMAND output is used to determine key locations. + Commands that do not have a predefined key location are flagged with 'movablekeys', + and these commands' keys are determined by the command 'COMMAND GETKEYS'. + + NOTE: Due to a bug in redis<7.0, this does not work properly + for EVAL or EVALSHA when the `numkeys` arg is 0. + - issue: https://github.com/redis/redis/issues/9493 + - fix: https://github.com/redis/redis/pull/9733 + + So, don't use this with EVAL or EVALSHA. + """ + + __slots__ = ("commands", "node") + + def __init__(self) -> None: + self.commands: Dict[str, Union[int, Dict[str, Any]]] = {} + + async def initialize(self, node: Optional["ClusterNode"] = None) -> None: + if node: + self.node = node + + commands = await self.node.execute_command("COMMAND") + self.commands = {cmd.lower(): command for cmd, command in commands.items()} + + # As soon as this PR is merged into Redis, we should reimplement + # our logic to use COMMAND INFO changes to determine the key positions + # https://github.com/redis/redis/pull/8324 + async def get_keys(self, *args: Any) -> Optional[Tuple[str, ...]]: + """ + Get the keys from the passed command. + + NOTE: Due to a bug in redis<7.0, this function does not work properly + for EVAL or EVALSHA when the `numkeys` arg is 0. + - issue: https://github.com/redis/redis/issues/9493 + - fix: https://github.com/redis/redis/pull/9733 + + So, don't use this function with EVAL or EVALSHA. + """ + if len(args) < 2: + # The command has no keys in it + return None + + cmd_name = args[0].lower() + if cmd_name not in self.commands: + # try to split the command name and to take only the main command, + # e.g. 'memory' for 'memory usage' + cmd_name_split = cmd_name.split() + cmd_name = cmd_name_split[0] + if cmd_name in self.commands: + # save the splitted command to args + args = cmd_name_split + list(args[1:]) + else: + # We'll try to reinitialize the commands cache, if the engine + # version has changed, the commands may not be current + await self.initialize() + if cmd_name not in self.commands: + raise RedisError( + f"{cmd_name.upper()} command doesn't exist in Redis commands" + ) + + command = self.commands.get(cmd_name) + if "movablekeys" in command["flags"]: + keys = await self._get_moveable_keys(*args) + elif "pubsub" in command["flags"] or command["name"] == "pubsub": + keys = self._get_pubsub_keys(*args) + else: + if ( + command["step_count"] == 0 + and command["first_key_pos"] == 0 + and command["last_key_pos"] == 0 + ): + is_subcmd = False + if "subcommands" in command: + subcmd_name = f"{cmd_name}|{args[1].lower()}" + for subcmd in command["subcommands"]: + if str_if_bytes(subcmd[0]) == subcmd_name: + command = self.parse_subcommand(subcmd) + is_subcmd = True + + # The command doesn't have keys in it + if not is_subcmd: + return None + last_key_pos = command["last_key_pos"] + if last_key_pos < 0: + last_key_pos = len(args) - abs(last_key_pos) + keys_pos = list( + range(command["first_key_pos"], last_key_pos + 1, command["step_count"]) + ) + keys = [args[pos] for pos in keys_pos] + + return keys + + async def _get_moveable_keys(self, *args: Any) -> Optional[Tuple[str, ...]]: + try: + keys = await self.node.execute_command("COMMAND GETKEYS", *args) + except ResponseError as e: + message = e.__str__() + if ( + "Invalid arguments" in message + or "The command has no key arguments" in message + ): + return None + else: + raise e + return keys diff --git a/.venv/Lib/site-packages/redis/_parsers/encoders.py b/.venv/Lib/site-packages/redis/_parsers/encoders.py new file mode 100644 index 00000000..6fdf0ad8 --- /dev/null +++ b/.venv/Lib/site-packages/redis/_parsers/encoders.py @@ -0,0 +1,44 @@ +from ..exceptions import DataError + + +class Encoder: + "Encode strings to bytes-like and decode bytes-like to strings" + + __slots__ = "encoding", "encoding_errors", "decode_responses" + + def __init__(self, encoding, encoding_errors, decode_responses): + self.encoding = encoding + self.encoding_errors = encoding_errors + self.decode_responses = decode_responses + + def encode(self, value): + "Return a bytestring or bytes-like representation of the value" + if isinstance(value, (bytes, memoryview)): + return value + elif isinstance(value, bool): + # special case bool since it is a subclass of int + raise DataError( + "Invalid input of type: 'bool'. Convert to a " + "bytes, string, int or float first." + ) + elif isinstance(value, (int, float)): + value = repr(value).encode() + elif not isinstance(value, str): + # a value we don't know how to deal with. throw an error + typename = type(value).__name__ + raise DataError( + f"Invalid input of type: '{typename}'. " + f"Convert to a bytes, string, int or float first." + ) + if isinstance(value, str): + value = value.encode(self.encoding, self.encoding_errors) + return value + + def decode(self, value, force=False): + "Return a unicode string from the bytes-like representation" + if self.decode_responses or force: + if isinstance(value, memoryview): + value = value.tobytes() + if isinstance(value, bytes): + value = value.decode(self.encoding, self.encoding_errors) + return value diff --git a/.venv/Lib/site-packages/redis/_parsers/helpers.py b/.venv/Lib/site-packages/redis/_parsers/helpers.py new file mode 100644 index 00000000..fb5da831 --- /dev/null +++ b/.venv/Lib/site-packages/redis/_parsers/helpers.py @@ -0,0 +1,852 @@ +import datetime + +from redis.utils import str_if_bytes + + +def timestamp_to_datetime(response): + "Converts a unix timestamp to a Python datetime object" + if not response: + return None + try: + response = int(response) + except ValueError: + return None + return datetime.datetime.fromtimestamp(response) + + +def parse_debug_object(response): + "Parse the results of Redis's DEBUG OBJECT command into a Python dict" + # The 'type' of the object is the first item in the response, but isn't + # prefixed with a name + response = str_if_bytes(response) + response = "type:" + response + response = dict(kv.split(":") for kv in response.split()) + + # parse some expected int values from the string response + # note: this cmd isn't spec'd so these may not appear in all redis versions + int_fields = ("refcount", "serializedlength", "lru", "lru_seconds_idle") + for field in int_fields: + if field in response: + response[field] = int(response[field]) + + return response + + +def parse_info(response): + """Parse the result of Redis's INFO command into a Python dict""" + info = {} + response = str_if_bytes(response) + + def get_value(value): + if "," not in value or "=" not in value: + try: + if "." in value: + return float(value) + else: + return int(value) + except ValueError: + return value + else: + sub_dict = {} + for item in value.split(","): + k, v = item.rsplit("=", 1) + sub_dict[k] = get_value(v) + return sub_dict + + for line in response.splitlines(): + if line and not line.startswith("#"): + if line.find(":") != -1: + # Split, the info fields keys and values. + # Note that the value may contain ':'. but the 'host:' + # pseudo-command is the only case where the key contains ':' + key, value = line.split(":", 1) + if key == "cmdstat_host": + key, value = line.rsplit(":", 1) + + if key == "module": + # Hardcode a list for key 'modules' since there could be + # multiple lines that started with 'module' + info.setdefault("modules", []).append(get_value(value)) + else: + info[key] = get_value(value) + else: + # if the line isn't splittable, append it to the "__raw__" key + info.setdefault("__raw__", []).append(line) + + return info + + +def parse_memory_stats(response, **kwargs): + """Parse the results of MEMORY STATS""" + stats = pairs_to_dict(response, decode_keys=True, decode_string_values=True) + for key, value in stats.items(): + if key.startswith("db."): + stats[key] = pairs_to_dict( + value, decode_keys=True, decode_string_values=True + ) + return stats + + +SENTINEL_STATE_TYPES = { + "can-failover-its-master": int, + "config-epoch": int, + "down-after-milliseconds": int, + "failover-timeout": int, + "info-refresh": int, + "last-hello-message": int, + "last-ok-ping-reply": int, + "last-ping-reply": int, + "last-ping-sent": int, + "master-link-down-time": int, + "master-port": int, + "num-other-sentinels": int, + "num-slaves": int, + "o-down-time": int, + "pending-commands": int, + "parallel-syncs": int, + "port": int, + "quorum": int, + "role-reported-time": int, + "s-down-time": int, + "slave-priority": int, + "slave-repl-offset": int, + "voted-leader-epoch": int, +} + + +def parse_sentinel_state(item): + result = pairs_to_dict_typed(item, SENTINEL_STATE_TYPES) + flags = set(result["flags"].split(",")) + for name, flag in ( + ("is_master", "master"), + ("is_slave", "slave"), + ("is_sdown", "s_down"), + ("is_odown", "o_down"), + ("is_sentinel", "sentinel"), + ("is_disconnected", "disconnected"), + ("is_master_down", "master_down"), + ): + result[name] = flag in flags + return result + + +def parse_sentinel_master(response): + return parse_sentinel_state(map(str_if_bytes, response)) + + +def parse_sentinel_state_resp3(response): + result = {} + for key in response: + try: + value = SENTINEL_STATE_TYPES[key](str_if_bytes(response[key])) + result[str_if_bytes(key)] = value + except Exception: + result[str_if_bytes(key)] = response[str_if_bytes(key)] + flags = set(result["flags"].split(",")) + result["flags"] = flags + return result + + +def parse_sentinel_masters(response): + result = {} + for item in response: + state = parse_sentinel_state(map(str_if_bytes, item)) + result[state["name"]] = state + return result + + +def parse_sentinel_masters_resp3(response): + return [parse_sentinel_state(master) for master in response] + + +def parse_sentinel_slaves_and_sentinels(response): + return [parse_sentinel_state(map(str_if_bytes, item)) for item in response] + + +def parse_sentinel_slaves_and_sentinels_resp3(response): + return [parse_sentinel_state_resp3(item) for item in response] + + +def parse_sentinel_get_master(response): + return response and (response[0], int(response[1])) or None + + +def pairs_to_dict(response, decode_keys=False, decode_string_values=False): + """Create a dict given a list of key/value pairs""" + if response is None: + return {} + if decode_keys or decode_string_values: + # the iter form is faster, but I don't know how to make that work + # with a str_if_bytes() map + keys = response[::2] + if decode_keys: + keys = map(str_if_bytes, keys) + values = response[1::2] + if decode_string_values: + values = map(str_if_bytes, values) + return dict(zip(keys, values)) + else: + it = iter(response) + return dict(zip(it, it)) + + +def pairs_to_dict_typed(response, type_info): + it = iter(response) + result = {} + for key, value in zip(it, it): + if key in type_info: + try: + value = type_info[key](value) + except Exception: + # if for some reason the value can't be coerced, just use + # the string value + pass + result[key] = value + return result + + +def zset_score_pairs(response, **options): + """ + If ``withscores`` is specified in the options, return the response as + a list of (value, score) pairs + """ + if not response or not options.get("withscores"): + return response + score_cast_func = options.get("score_cast_func", float) + it = iter(response) + return list(zip(it, map(score_cast_func, it))) + + +def sort_return_tuples(response, **options): + """ + If ``groups`` is specified, return the response as a list of + n-element tuples with n being the value found in options['groups'] + """ + if not response or not options.get("groups"): + return response + n = options["groups"] + return list(zip(*[response[i::n] for i in range(n)])) + + +def parse_stream_list(response): + if response is None: + return None + data = [] + for r in response: + if r is not None: + data.append((r[0], pairs_to_dict(r[1]))) + else: + data.append((None, None)) + return data + + +def pairs_to_dict_with_str_keys(response): + return pairs_to_dict(response, decode_keys=True) + + +def parse_list_of_dicts(response): + return list(map(pairs_to_dict_with_str_keys, response)) + + +def parse_xclaim(response, **options): + if options.get("parse_justid", False): + return response + return parse_stream_list(response) + + +def parse_xautoclaim(response, **options): + if options.get("parse_justid", False): + return response[1] + response[1] = parse_stream_list(response[1]) + return response + + +def parse_xinfo_stream(response, **options): + if isinstance(response, list): + data = pairs_to_dict(response, decode_keys=True) + else: + data = {str_if_bytes(k): v for k, v in response.items()} + if not options.get("full", False): + first = data.get("first-entry") + if first is not None: + data["first-entry"] = (first[0], pairs_to_dict(first[1])) + last = data["last-entry"] + if last is not None: + data["last-entry"] = (last[0], pairs_to_dict(last[1])) + else: + data["entries"] = {_id: pairs_to_dict(entry) for _id, entry in data["entries"]} + if isinstance(data["groups"][0], list): + data["groups"] = [ + pairs_to_dict(group, decode_keys=True) for group in data["groups"] + ] + else: + data["groups"] = [ + {str_if_bytes(k): v for k, v in group.items()} + for group in data["groups"] + ] + return data + + +def parse_xread(response): + if response is None: + return [] + return [[r[0], parse_stream_list(r[1])] for r in response] + + +def parse_xread_resp3(response): + if response is None: + return {} + return {key: [parse_stream_list(value)] for key, value in response.items()} + + +def parse_xpending(response, **options): + if options.get("parse_detail", False): + return parse_xpending_range(response) + consumers = [{"name": n, "pending": int(p)} for n, p in response[3] or []] + return { + "pending": response[0], + "min": response[1], + "max": response[2], + "consumers": consumers, + } + + +def parse_xpending_range(response): + k = ("message_id", "consumer", "time_since_delivered", "times_delivered") + return [dict(zip(k, r)) for r in response] + + +def float_or_none(response): + if response is None: + return None + return float(response) + + +def bool_ok(response): + return str_if_bytes(response) == "OK" + + +def parse_zadd(response, **options): + if response is None: + return None + if options.get("as_score"): + return float(response) + return int(response) + + +def parse_client_list(response, **options): + clients = [] + for c in str_if_bytes(response).splitlines(): + # Values might contain '=' + clients.append(dict(pair.split("=", 1) for pair in c.split(" "))) + return clients + + +def parse_config_get(response, **options): + response = [str_if_bytes(i) if i is not None else None for i in response] + return response and pairs_to_dict(response) or {} + + +def parse_scan(response, **options): + cursor, r = response + return int(cursor), r + + +def parse_hscan(response, **options): + cursor, r = response + return int(cursor), r and pairs_to_dict(r) or {} + + +def parse_zscan(response, **options): + score_cast_func = options.get("score_cast_func", float) + cursor, r = response + it = iter(r) + return int(cursor), list(zip(it, map(score_cast_func, it))) + + +def parse_zmscore(response, **options): + # zmscore: list of scores (double precision floating point number) or nil + return [float(score) if score is not None else None for score in response] + + +def parse_slowlog_get(response, **options): + space = " " if options.get("decode_responses", False) else b" " + + def parse_item(item): + result = {"id": item[0], "start_time": int(item[1]), "duration": int(item[2])} + # Redis Enterprise injects another entry at index [3], which has + # the complexity info (i.e. the value N in case the command has + # an O(N) complexity) instead of the command. + if isinstance(item[3], list): + result["command"] = space.join(item[3]) + result["client_address"] = item[4] + result["client_name"] = item[5] + else: + result["complexity"] = item[3] + result["command"] = space.join(item[4]) + result["client_address"] = item[5] + result["client_name"] = item[6] + return result + + return [parse_item(item) for item in response] + + +def parse_stralgo(response, **options): + """ + Parse the response from `STRALGO` command. + Without modifiers the returned value is string. + When LEN is given the command returns the length of the result + (i.e integer). + When IDX is given the command returns a dictionary with the LCS + length and all the ranges in both the strings, start and end + offset for each string, where there are matches. + When WITHMATCHLEN is given, each array representing a match will + also have the length of the match at the beginning of the array. + """ + if options.get("len", False): + return int(response) + if options.get("idx", False): + if options.get("withmatchlen", False): + matches = [ + [(int(match[-1]))] + list(map(tuple, match[:-1])) + for match in response[1] + ] + else: + matches = [list(map(tuple, match)) for match in response[1]] + return { + str_if_bytes(response[0]): matches, + str_if_bytes(response[2]): int(response[3]), + } + return str_if_bytes(response) + + +def parse_cluster_info(response, **options): + response = str_if_bytes(response) + return dict(line.split(":") for line in response.splitlines() if line) + + +def _parse_node_line(line): + line_items = line.split(" ") + node_id, addr, flags, master_id, ping, pong, epoch, connected = line.split(" ")[:8] + addr = addr.split("@")[0] + node_dict = { + "node_id": node_id, + "flags": flags, + "master_id": master_id, + "last_ping_sent": ping, + "last_pong_rcvd": pong, + "epoch": epoch, + "slots": [], + "migrations": [], + "connected": True if connected == "connected" else False, + } + if len(line_items) >= 9: + slots, migrations = _parse_slots(line_items[8:]) + node_dict["slots"], node_dict["migrations"] = slots, migrations + return addr, node_dict + + +def _parse_slots(slot_ranges): + slots, migrations = [], [] + for s_range in slot_ranges: + if "->-" in s_range: + slot_id, dst_node_id = s_range[1:-1].split("->-", 1) + migrations.append( + {"slot": slot_id, "node_id": dst_node_id, "state": "migrating"} + ) + elif "-<-" in s_range: + slot_id, src_node_id = s_range[1:-1].split("-<-", 1) + migrations.append( + {"slot": slot_id, "node_id": src_node_id, "state": "importing"} + ) + else: + s_range = [sl for sl in s_range.split("-")] + slots.append(s_range) + + return slots, migrations + + +def parse_cluster_nodes(response, **options): + """ + @see: https://redis.io/commands/cluster-nodes # string / bytes + @see: https://redis.io/commands/cluster-replicas # list of string / bytes + """ + if isinstance(response, (str, bytes)): + response = response.splitlines() + return dict(_parse_node_line(str_if_bytes(node)) for node in response) + + +def parse_geosearch_generic(response, **options): + """ + Parse the response of 'GEOSEARCH', GEORADIUS' and 'GEORADIUSBYMEMBER' + commands according to 'withdist', 'withhash' and 'withcoord' labels. + """ + try: + if options["store"] or options["store_dist"]: + # `store` and `store_dist` cant be combined + # with other command arguments. + # relevant to 'GEORADIUS' and 'GEORADIUSBYMEMBER' + return response + except KeyError: # it means the command was sent via execute_command + return response + + if type(response) != list: + response_list = [response] + else: + response_list = response + + if not options["withdist"] and not options["withcoord"] and not options["withhash"]: + # just a bunch of places + return response_list + + cast = { + "withdist": float, + "withcoord": lambda ll: (float(ll[0]), float(ll[1])), + "withhash": int, + } + + # zip all output results with each casting function to get + # the properly native Python value. + f = [lambda x: x] + f += [cast[o] for o in ["withdist", "withhash", "withcoord"] if options[o]] + return [list(map(lambda fv: fv[0](fv[1]), zip(f, r))) for r in response_list] + + +def parse_command(response, **options): + commands = {} + for command in response: + cmd_dict = {} + cmd_name = str_if_bytes(command[0]) + cmd_dict["name"] = cmd_name + cmd_dict["arity"] = int(command[1]) + cmd_dict["flags"] = [str_if_bytes(flag) for flag in command[2]] + cmd_dict["first_key_pos"] = command[3] + cmd_dict["last_key_pos"] = command[4] + cmd_dict["step_count"] = command[5] + if len(command) > 7: + cmd_dict["tips"] = command[7] + cmd_dict["key_specifications"] = command[8] + cmd_dict["subcommands"] = command[9] + commands[cmd_name] = cmd_dict + return commands + + +def parse_command_resp3(response, **options): + commands = {} + for command in response: + cmd_dict = {} + cmd_name = str_if_bytes(command[0]) + cmd_dict["name"] = cmd_name + cmd_dict["arity"] = command[1] + cmd_dict["flags"] = {str_if_bytes(flag) for flag in command[2]} + cmd_dict["first_key_pos"] = command[3] + cmd_dict["last_key_pos"] = command[4] + cmd_dict["step_count"] = command[5] + cmd_dict["acl_categories"] = command[6] + if len(command) > 7: + cmd_dict["tips"] = command[7] + cmd_dict["key_specifications"] = command[8] + cmd_dict["subcommands"] = command[9] + + commands[cmd_name] = cmd_dict + return commands + + +def parse_pubsub_numsub(response, **options): + return list(zip(response[0::2], response[1::2])) + + +def parse_client_kill(response, **options): + if isinstance(response, int): + return response + return str_if_bytes(response) == "OK" + + +def parse_acl_getuser(response, **options): + if response is None: + return None + if isinstance(response, list): + data = pairs_to_dict(response, decode_keys=True) + else: + data = {str_if_bytes(key): value for key, value in response.items()} + + # convert everything but user-defined data in 'keys' to native strings + data["flags"] = list(map(str_if_bytes, data["flags"])) + data["passwords"] = list(map(str_if_bytes, data["passwords"])) + data["commands"] = str_if_bytes(data["commands"]) + if isinstance(data["keys"], str) or isinstance(data["keys"], bytes): + data["keys"] = list(str_if_bytes(data["keys"]).split(" ")) + if data["keys"] == [""]: + data["keys"] = [] + if "channels" in data: + if isinstance(data["channels"], str) or isinstance(data["channels"], bytes): + data["channels"] = list(str_if_bytes(data["channels"]).split(" ")) + if data["channels"] == [""]: + data["channels"] = [] + if "selectors" in data: + if data["selectors"] != [] and isinstance(data["selectors"][0], list): + data["selectors"] = [ + list(map(str_if_bytes, selector)) for selector in data["selectors"] + ] + elif data["selectors"] != []: + data["selectors"] = [ + {str_if_bytes(k): str_if_bytes(v) for k, v in selector.items()} + for selector in data["selectors"] + ] + + # split 'commands' into separate 'categories' and 'commands' lists + commands, categories = [], [] + for command in data["commands"].split(" "): + categories.append(command) if "@" in command else commands.append(command) + + data["commands"] = commands + data["categories"] = categories + data["enabled"] = "on" in data["flags"] + return data + + +def parse_acl_log(response, **options): + if response is None: + return None + if isinstance(response, list): + data = [] + for log in response: + log_data = pairs_to_dict(log, True, True) + client_info = log_data.get("client-info", "") + log_data["client-info"] = parse_client_info(client_info) + + # float() is lossy comparing to the "double" in C + log_data["age-seconds"] = float(log_data["age-seconds"]) + data.append(log_data) + else: + data = bool_ok(response) + return data + + +def parse_client_info(value): + """ + Parsing client-info in ACL Log in following format. + "key1=value1 key2=value2 key3=value3" + """ + client_info = {} + for info in str_if_bytes(value).strip().split(): + key, value = info.split("=") + client_info[key] = value + + # Those fields are defined as int in networking.c + for int_key in { + "id", + "age", + "idle", + "db", + "sub", + "psub", + "multi", + "qbuf", + "qbuf-free", + "obl", + "argv-mem", + "oll", + "omem", + "tot-mem", + }: + client_info[int_key] = int(client_info[int_key]) + return client_info + + +def parse_set_result(response, **options): + """ + Handle SET result since GET argument is available since Redis 6.2. + Parsing SET result into: + - BOOL + - String when GET argument is used + """ + if options.get("get"): + # Redis will return a getCommand result. + # See `setGenericCommand` in t_string.c + return response + return response and str_if_bytes(response) == "OK" + + +def string_keys_to_dict(key_string, callback): + return dict.fromkeys(key_string.split(), callback) + + +_RedisCallbacks = { + **string_keys_to_dict( + "AUTH COPY EXPIRE EXPIREAT HEXISTS HMSET MOVE MSETNX PERSIST PSETEX " + "PEXPIRE PEXPIREAT RENAMENX SETEX SETNX SMOVE", + bool, + ), + **string_keys_to_dict("HINCRBYFLOAT INCRBYFLOAT", float), + **string_keys_to_dict( + "ASKING FLUSHALL FLUSHDB LSET LTRIM MSET PFMERGE READONLY READWRITE " + "RENAME SAVE SELECT SHUTDOWN SLAVEOF SWAPDB WATCH UNWATCH", + bool_ok, + ), + **string_keys_to_dict("XREAD XREADGROUP", parse_xread), + **string_keys_to_dict( + "GEORADIUS GEORADIUSBYMEMBER GEOSEARCH", + parse_geosearch_generic, + ), + **string_keys_to_dict("XRANGE XREVRANGE", parse_stream_list), + "ACL GETUSER": parse_acl_getuser, + "ACL LOAD": bool_ok, + "ACL LOG": parse_acl_log, + "ACL SETUSER": bool_ok, + "ACL SAVE": bool_ok, + "CLIENT INFO": parse_client_info, + "CLIENT KILL": parse_client_kill, + "CLIENT LIST": parse_client_list, + "CLIENT PAUSE": bool_ok, + "CLIENT SETINFO": bool_ok, + "CLIENT SETNAME": bool_ok, + "CLIENT UNBLOCK": bool, + "CLUSTER ADDSLOTS": bool_ok, + "CLUSTER ADDSLOTSRANGE": bool_ok, + "CLUSTER DELSLOTS": bool_ok, + "CLUSTER DELSLOTSRANGE": bool_ok, + "CLUSTER FAILOVER": bool_ok, + "CLUSTER FORGET": bool_ok, + "CLUSTER INFO": parse_cluster_info, + "CLUSTER MEET": bool_ok, + "CLUSTER NODES": parse_cluster_nodes, + "CLUSTER REPLICAS": parse_cluster_nodes, + "CLUSTER REPLICATE": bool_ok, + "CLUSTER RESET": bool_ok, + "CLUSTER SAVECONFIG": bool_ok, + "CLUSTER SET-CONFIG-EPOCH": bool_ok, + "CLUSTER SETSLOT": bool_ok, + "CLUSTER SLAVES": parse_cluster_nodes, + "COMMAND": parse_command, + "CONFIG RESETSTAT": bool_ok, + "CONFIG SET": bool_ok, + "FUNCTION DELETE": bool_ok, + "FUNCTION FLUSH": bool_ok, + "FUNCTION RESTORE": bool_ok, + "GEODIST": float_or_none, + "HSCAN": parse_hscan, + "INFO": parse_info, + "LASTSAVE": timestamp_to_datetime, + "MEMORY PURGE": bool_ok, + "MODULE LOAD": bool, + "MODULE UNLOAD": bool, + "PING": lambda r: str_if_bytes(r) == "PONG", + "PUBSUB NUMSUB": parse_pubsub_numsub, + "PUBSUB SHARDNUMSUB": parse_pubsub_numsub, + "QUIT": bool_ok, + "SET": parse_set_result, + "SCAN": parse_scan, + "SCRIPT EXISTS": lambda r: list(map(bool, r)), + "SCRIPT FLUSH": bool_ok, + "SCRIPT KILL": bool_ok, + "SCRIPT LOAD": str_if_bytes, + "SENTINEL CKQUORUM": bool_ok, + "SENTINEL FAILOVER": bool_ok, + "SENTINEL FLUSHCONFIG": bool_ok, + "SENTINEL GET-MASTER-ADDR-BY-NAME": parse_sentinel_get_master, + "SENTINEL MONITOR": bool_ok, + "SENTINEL RESET": bool_ok, + "SENTINEL REMOVE": bool_ok, + "SENTINEL SET": bool_ok, + "SLOWLOG GET": parse_slowlog_get, + "SLOWLOG RESET": bool_ok, + "SORT": sort_return_tuples, + "SSCAN": parse_scan, + "TIME": lambda x: (int(x[0]), int(x[1])), + "XAUTOCLAIM": parse_xautoclaim, + "XCLAIM": parse_xclaim, + "XGROUP CREATE": bool_ok, + "XGROUP DESTROY": bool, + "XGROUP SETID": bool_ok, + "XINFO STREAM": parse_xinfo_stream, + "XPENDING": parse_xpending, + "ZSCAN": parse_zscan, +} + + +_RedisCallbacksRESP2 = { + **string_keys_to_dict( + "SDIFF SINTER SMEMBERS SUNION", lambda r: r and set(r) or set() + ), + **string_keys_to_dict( + "ZDIFF ZINTER ZPOPMAX ZPOPMIN ZRANGE ZRANGEBYSCORE ZRANK ZREVRANGE " + "ZREVRANGEBYSCORE ZREVRANK ZUNION", + zset_score_pairs, + ), + **string_keys_to_dict("ZINCRBY ZSCORE", float_or_none), + **string_keys_to_dict("BGREWRITEAOF BGSAVE", lambda r: True), + **string_keys_to_dict("BLPOP BRPOP", lambda r: r and tuple(r) or None), + **string_keys_to_dict( + "BZPOPMAX BZPOPMIN", lambda r: r and (r[0], r[1], float(r[2])) or None + ), + "ACL CAT": lambda r: list(map(str_if_bytes, r)), + "ACL GENPASS": str_if_bytes, + "ACL HELP": lambda r: list(map(str_if_bytes, r)), + "ACL LIST": lambda r: list(map(str_if_bytes, r)), + "ACL USERS": lambda r: list(map(str_if_bytes, r)), + "ACL WHOAMI": str_if_bytes, + "CLIENT GETNAME": str_if_bytes, + "CLIENT TRACKINGINFO": lambda r: list(map(str_if_bytes, r)), + "CLUSTER GETKEYSINSLOT": lambda r: list(map(str_if_bytes, r)), + "COMMAND GETKEYS": lambda r: list(map(str_if_bytes, r)), + "CONFIG GET": parse_config_get, + "DEBUG OBJECT": parse_debug_object, + "GEOHASH": lambda r: list(map(str_if_bytes, r)), + "GEOPOS": lambda r: list( + map(lambda ll: (float(ll[0]), float(ll[1])) if ll is not None else None, r) + ), + "HGETALL": lambda r: r and pairs_to_dict(r) or {}, + "MEMORY STATS": parse_memory_stats, + "MODULE LIST": lambda r: [pairs_to_dict(m) for m in r], + "RESET": str_if_bytes, + "SENTINEL MASTER": parse_sentinel_master, + "SENTINEL MASTERS": parse_sentinel_masters, + "SENTINEL SENTINELS": parse_sentinel_slaves_and_sentinels, + "SENTINEL SLAVES": parse_sentinel_slaves_and_sentinels, + "STRALGO": parse_stralgo, + "XINFO CONSUMERS": parse_list_of_dicts, + "XINFO GROUPS": parse_list_of_dicts, + "ZADD": parse_zadd, + "ZMSCORE": parse_zmscore, +} + + +_RedisCallbacksRESP3 = { + **string_keys_to_dict( + "ZRANGE ZINTER ZPOPMAX ZPOPMIN ZRANGEBYSCORE ZREVRANGE ZREVRANGEBYSCORE " + "ZUNION HGETALL XREADGROUP", + lambda r, **kwargs: r, + ), + **string_keys_to_dict("XREAD XREADGROUP", parse_xread_resp3), + "ACL LOG": lambda r: [ + {str_if_bytes(key): str_if_bytes(value) for key, value in x.items()} for x in r + ] + if isinstance(r, list) + else bool_ok(r), + "COMMAND": parse_command_resp3, + "CONFIG GET": lambda r: { + str_if_bytes(key) + if key is not None + else None: str_if_bytes(value) + if value is not None + else None + for key, value in r.items() + }, + "MEMORY STATS": lambda r: {str_if_bytes(key): value for key, value in r.items()}, + "SENTINEL MASTER": parse_sentinel_state_resp3, + "SENTINEL MASTERS": parse_sentinel_masters_resp3, + "SENTINEL SENTINELS": parse_sentinel_slaves_and_sentinels_resp3, + "SENTINEL SLAVES": parse_sentinel_slaves_and_sentinels_resp3, + "STRALGO": lambda r, **options: { + str_if_bytes(key): str_if_bytes(value) for key, value in r.items() + } + if isinstance(r, dict) + else str_if_bytes(r), + "XINFO CONSUMERS": lambda r: [ + {str_if_bytes(key): value for key, value in x.items()} for x in r + ], + "XINFO GROUPS": lambda r: [ + {str_if_bytes(key): value for key, value in d.items()} for d in r + ], +} diff --git a/.venv/Lib/site-packages/redis/_parsers/hiredis.py b/.venv/Lib/site-packages/redis/_parsers/hiredis.py new file mode 100644 index 00000000..b3247b71 --- /dev/null +++ b/.venv/Lib/site-packages/redis/_parsers/hiredis.py @@ -0,0 +1,217 @@ +import asyncio +import socket +import sys +from typing import Callable, List, Optional, Union + +if sys.version_info.major >= 3 and sys.version_info.minor >= 11: + from asyncio import timeout as async_timeout +else: + from async_timeout import timeout as async_timeout + +from redis.compat import TypedDict + +from ..exceptions import ConnectionError, InvalidResponse, RedisError +from ..typing import EncodableT +from ..utils import HIREDIS_AVAILABLE +from .base import AsyncBaseParser, BaseParser +from .socket import ( + NONBLOCKING_EXCEPTION_ERROR_NUMBERS, + NONBLOCKING_EXCEPTIONS, + SENTINEL, + SERVER_CLOSED_CONNECTION_ERROR, +) + + +class _HiredisReaderArgs(TypedDict, total=False): + protocolError: Callable[[str], Exception] + replyError: Callable[[str], Exception] + encoding: Optional[str] + errors: Optional[str] + + +class _HiredisParser(BaseParser): + "Parser class for connections using Hiredis" + + def __init__(self, socket_read_size): + if not HIREDIS_AVAILABLE: + raise RedisError("Hiredis is not installed") + self.socket_read_size = socket_read_size + self._buffer = bytearray(socket_read_size) + + def __del__(self): + try: + self.on_disconnect() + except Exception: + pass + + def on_connect(self, connection, **kwargs): + import hiredis + + self._sock = connection._sock + self._socket_timeout = connection.socket_timeout + kwargs = { + "protocolError": InvalidResponse, + "replyError": self.parse_error, + "errors": connection.encoder.encoding_errors, + } + + if connection.encoder.decode_responses: + kwargs["encoding"] = connection.encoder.encoding + self._reader = hiredis.Reader(**kwargs) + self._next_response = False + + def on_disconnect(self): + self._sock = None + self._reader = None + self._next_response = False + + def can_read(self, timeout): + if not self._reader: + raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR) + + if self._next_response is False: + self._next_response = self._reader.gets() + if self._next_response is False: + return self.read_from_socket(timeout=timeout, raise_on_timeout=False) + return True + + def read_from_socket(self, timeout=SENTINEL, raise_on_timeout=True): + sock = self._sock + custom_timeout = timeout is not SENTINEL + try: + if custom_timeout: + sock.settimeout(timeout) + bufflen = self._sock.recv_into(self._buffer) + if bufflen == 0: + raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR) + self._reader.feed(self._buffer, 0, bufflen) + # data was read from the socket and added to the buffer. + # return True to indicate that data was read. + return True + except socket.timeout: + if raise_on_timeout: + raise TimeoutError("Timeout reading from socket") + return False + except NONBLOCKING_EXCEPTIONS as ex: + # if we're in nonblocking mode and the recv raises a + # blocking error, simply return False indicating that + # there's no data to be read. otherwise raise the + # original exception. + allowed = NONBLOCKING_EXCEPTION_ERROR_NUMBERS.get(ex.__class__, -1) + if not raise_on_timeout and ex.errno == allowed: + return False + raise ConnectionError(f"Error while reading from socket: {ex.args}") + finally: + if custom_timeout: + sock.settimeout(self._socket_timeout) + + def read_response(self, disable_decoding=False): + if not self._reader: + raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR) + + # _next_response might be cached from a can_read() call + if self._next_response is not False: + response = self._next_response + self._next_response = False + return response + + if disable_decoding: + response = self._reader.gets(False) + else: + response = self._reader.gets() + + while response is False: + self.read_from_socket() + if disable_decoding: + response = self._reader.gets(False) + else: + response = self._reader.gets() + # if the response is a ConnectionError or the response is a list and + # the first item is a ConnectionError, raise it as something bad + # happened + if isinstance(response, ConnectionError): + raise response + elif ( + isinstance(response, list) + and response + and isinstance(response[0], ConnectionError) + ): + raise response[0] + return response + + +class _AsyncHiredisParser(AsyncBaseParser): + """Async implementation of parser class for connections using Hiredis""" + + __slots__ = ("_reader",) + + def __init__(self, socket_read_size: int): + if not HIREDIS_AVAILABLE: + raise RedisError("Hiredis is not available.") + super().__init__(socket_read_size=socket_read_size) + self._reader = None + + def on_connect(self, connection): + import hiredis + + self._stream = connection._reader + kwargs: _HiredisReaderArgs = { + "protocolError": InvalidResponse, + "replyError": self.parse_error, + } + if connection.encoder.decode_responses: + kwargs["encoding"] = connection.encoder.encoding + kwargs["errors"] = connection.encoder.encoding_errors + + self._reader = hiredis.Reader(**kwargs) + self._connected = True + + def on_disconnect(self): + self._connected = False + + async def can_read_destructive(self): + if not self._connected: + raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR) + if self._reader.gets(): + return True + try: + async with async_timeout(0): + return await self.read_from_socket() + except asyncio.TimeoutError: + return False + + async def read_from_socket(self): + buffer = await self._stream.read(self._read_size) + if not buffer or not isinstance(buffer, bytes): + raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR) from None + self._reader.feed(buffer) + # data was read from the socket and added to the buffer. + # return True to indicate that data was read. + return True + + async def read_response( + self, disable_decoding: bool = False + ) -> Union[EncodableT, List[EncodableT]]: + # If `on_disconnect()` has been called, prohibit any more reads + # even if they could happen because data might be present. + # We still allow reads in progress to finish + if not self._connected: + raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR) from None + + response = self._reader.gets() + while response is False: + await self.read_from_socket() + response = self._reader.gets() + + # if the response is a ConnectionError or the response is a list and + # the first item is a ConnectionError, raise it as something bad + # happened + if isinstance(response, ConnectionError): + raise response + elif ( + isinstance(response, list) + and response + and isinstance(response[0], ConnectionError) + ): + raise response[0] + return response diff --git a/.venv/Lib/site-packages/redis/_parsers/resp2.py b/.venv/Lib/site-packages/redis/_parsers/resp2.py new file mode 100644 index 00000000..d5adc1a8 --- /dev/null +++ b/.venv/Lib/site-packages/redis/_parsers/resp2.py @@ -0,0 +1,132 @@ +from typing import Any, Union + +from ..exceptions import ConnectionError, InvalidResponse, ResponseError +from ..typing import EncodableT +from .base import _AsyncRESPBase, _RESPBase +from .socket import SERVER_CLOSED_CONNECTION_ERROR + + +class _RESP2Parser(_RESPBase): + """RESP2 protocol implementation""" + + def read_response(self, disable_decoding=False): + pos = self._buffer.get_pos() if self._buffer else None + try: + result = self._read_response(disable_decoding=disable_decoding) + except BaseException: + if self._buffer: + self._buffer.rewind(pos) + raise + else: + self._buffer.purge() + return result + + def _read_response(self, disable_decoding=False): + raw = self._buffer.readline() + if not raw: + raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR) + + byte, response = raw[:1], raw[1:] + + # server returned an error + if byte == b"-": + response = response.decode("utf-8", errors="replace") + error = self.parse_error(response) + # if the error is a ConnectionError, raise immediately so the user + # is notified + if isinstance(error, ConnectionError): + raise error + # otherwise, we're dealing with a ResponseError that might belong + # inside a pipeline response. the connection's read_response() + # and/or the pipeline's execute() will raise this error if + # necessary, so just return the exception instance here. + return error + # single value + elif byte == b"+": + pass + # int value + elif byte == b":": + return int(response) + # bulk response + elif byte == b"$" and response == b"-1": + return None + elif byte == b"$": + response = self._buffer.read(int(response)) + # multi-bulk response + elif byte == b"*" and response == b"-1": + return None + elif byte == b"*": + response = [ + self._read_response(disable_decoding=disable_decoding) + for i in range(int(response)) + ] + else: + raise InvalidResponse(f"Protocol Error: {raw!r}") + + if disable_decoding is False: + response = self.encoder.decode(response) + return response + + +class _AsyncRESP2Parser(_AsyncRESPBase): + """Async class for the RESP2 protocol""" + + async def read_response(self, disable_decoding: bool = False): + if not self._connected: + raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR) + if self._chunks: + # augment parsing buffer with previously read data + self._buffer += b"".join(self._chunks) + self._chunks.clear() + self._pos = 0 + response = await self._read_response(disable_decoding=disable_decoding) + # Successfully parsing a response allows us to clear our parsing buffer + self._clear() + return response + + async def _read_response( + self, disable_decoding: bool = False + ) -> Union[EncodableT, ResponseError, None]: + raw = await self._readline() + response: Any + byte, response = raw[:1], raw[1:] + + # server returned an error + if byte == b"-": + response = response.decode("utf-8", errors="replace") + error = self.parse_error(response) + # if the error is a ConnectionError, raise immediately so the user + # is notified + if isinstance(error, ConnectionError): + self._clear() # Successful parse + raise error + # otherwise, we're dealing with a ResponseError that might belong + # inside a pipeline response. the connection's read_response() + # and/or the pipeline's execute() will raise this error if + # necessary, so just return the exception instance here. + return error + # single value + elif byte == b"+": + pass + # int value + elif byte == b":": + return int(response) + # bulk response + elif byte == b"$" and response == b"-1": + return None + elif byte == b"$": + response = await self._read(int(response)) + # multi-bulk response + elif byte == b"*" and response == b"-1": + return None + elif byte == b"*": + response = [ + (await self._read_response(disable_decoding)) + for _ in range(int(response)) # noqa + ] + else: + raise InvalidResponse(f"Protocol Error: {raw!r}") + + if disable_decoding is False: + response = self.encoder.decode(response) + return response diff --git a/.venv/Lib/site-packages/redis/_parsers/resp3.py b/.venv/Lib/site-packages/redis/_parsers/resp3.py new file mode 100644 index 00000000..ad766a8f --- /dev/null +++ b/.venv/Lib/site-packages/redis/_parsers/resp3.py @@ -0,0 +1,259 @@ +from logging import getLogger +from typing import Any, Union + +from ..exceptions import ConnectionError, InvalidResponse, ResponseError +from ..typing import EncodableT +from .base import _AsyncRESPBase, _RESPBase +from .socket import SERVER_CLOSED_CONNECTION_ERROR + + +class _RESP3Parser(_RESPBase): + """RESP3 protocol implementation""" + + def __init__(self, socket_read_size): + super().__init__(socket_read_size) + self.push_handler_func = self.handle_push_response + + def handle_push_response(self, response): + logger = getLogger("push_response") + logger.info("Push response: " + str(response)) + return response + + def read_response(self, disable_decoding=False, push_request=False): + pos = self._buffer.get_pos() if self._buffer else None + try: + result = self._read_response( + disable_decoding=disable_decoding, push_request=push_request + ) + except BaseException: + if self._buffer: + self._buffer.rewind(pos) + raise + else: + self._buffer.purge() + return result + + def _read_response(self, disable_decoding=False, push_request=False): + raw = self._buffer.readline() + if not raw: + raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR) + + byte, response = raw[:1], raw[1:] + + # server returned an error + if byte in (b"-", b"!"): + if byte == b"!": + response = self._buffer.read(int(response)) + response = response.decode("utf-8", errors="replace") + error = self.parse_error(response) + # if the error is a ConnectionError, raise immediately so the user + # is notified + if isinstance(error, ConnectionError): + raise error + # otherwise, we're dealing with a ResponseError that might belong + # inside a pipeline response. the connection's read_response() + # and/or the pipeline's execute() will raise this error if + # necessary, so just return the exception instance here. + return error + # single value + elif byte == b"+": + pass + # null value + elif byte == b"_": + return None + # int and big int values + elif byte in (b":", b"("): + return int(response) + # double value + elif byte == b",": + return float(response) + # bool value + elif byte == b"#": + return response == b"t" + # bulk response + elif byte == b"$": + response = self._buffer.read(int(response)) + # verbatim string response + elif byte == b"=": + response = self._buffer.read(int(response))[4:] + # array response + elif byte == b"*": + response = [ + self._read_response(disable_decoding=disable_decoding) + for _ in range(int(response)) + ] + # set response + elif byte == b"~": + # redis can return unhashable types (like dict) in a set, + # so we need to first convert to a list, and then try to convert it to a set + response = [ + self._read_response(disable_decoding=disable_decoding) + for _ in range(int(response)) + ] + try: + response = set(response) + except TypeError: + pass + # map response + elif byte == b"%": + # we use this approach and not dict comprehension here + # because this dict comprehension fails in python 3.7 + resp_dict = {} + for _ in range(int(response)): + key = self._read_response(disable_decoding=disable_decoding) + resp_dict[key] = self._read_response( + disable_decoding=disable_decoding, push_request=push_request + ) + response = resp_dict + # push response + elif byte == b">": + response = [ + self._read_response( + disable_decoding=disable_decoding, push_request=push_request + ) + for _ in range(int(response)) + ] + res = self.push_handler_func(response) + if not push_request: + return self._read_response( + disable_decoding=disable_decoding, push_request=push_request + ) + else: + return res + else: + raise InvalidResponse(f"Protocol Error: {raw!r}") + + if isinstance(response, bytes) and disable_decoding is False: + response = self.encoder.decode(response) + return response + + def set_push_handler(self, push_handler_func): + self.push_handler_func = push_handler_func + + +class _AsyncRESP3Parser(_AsyncRESPBase): + def __init__(self, socket_read_size): + super().__init__(socket_read_size) + self.push_handler_func = self.handle_push_response + + def handle_push_response(self, response): + logger = getLogger("push_response") + logger.info("Push response: " + str(response)) + return response + + async def read_response( + self, disable_decoding: bool = False, push_request: bool = False + ): + if self._chunks: + # augment parsing buffer with previously read data + self._buffer += b"".join(self._chunks) + self._chunks.clear() + self._pos = 0 + response = await self._read_response( + disable_decoding=disable_decoding, push_request=push_request + ) + # Successfully parsing a response allows us to clear our parsing buffer + self._clear() + return response + + async def _read_response( + self, disable_decoding: bool = False, push_request: bool = False + ) -> Union[EncodableT, ResponseError, None]: + if not self._stream or not self.encoder: + raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR) + raw = await self._readline() + response: Any + byte, response = raw[:1], raw[1:] + + # if byte not in (b"-", b"+", b":", b"$", b"*"): + # raise InvalidResponse(f"Protocol Error: {raw!r}") + + # server returned an error + if byte in (b"-", b"!"): + if byte == b"!": + response = await self._read(int(response)) + response = response.decode("utf-8", errors="replace") + error = self.parse_error(response) + # if the error is a ConnectionError, raise immediately so the user + # is notified + if isinstance(error, ConnectionError): + self._clear() # Successful parse + raise error + # otherwise, we're dealing with a ResponseError that might belong + # inside a pipeline response. the connection's read_response() + # and/or the pipeline's execute() will raise this error if + # necessary, so just return the exception instance here. + return error + # single value + elif byte == b"+": + pass + # null value + elif byte == b"_": + return None + # int and big int values + elif byte in (b":", b"("): + return int(response) + # double value + elif byte == b",": + return float(response) + # bool value + elif byte == b"#": + return response == b"t" + # bulk response + elif byte == b"$": + response = await self._read(int(response)) + # verbatim string response + elif byte == b"=": + response = (await self._read(int(response)))[4:] + # array response + elif byte == b"*": + response = [ + (await self._read_response(disable_decoding=disable_decoding)) + for _ in range(int(response)) + ] + # set response + elif byte == b"~": + # redis can return unhashable types (like dict) in a set, + # so we need to first convert to a list, and then try to convert it to a set + response = [ + (await self._read_response(disable_decoding=disable_decoding)) + for _ in range(int(response)) + ] + try: + response = set(response) + except TypeError: + pass + # map response + elif byte == b"%": + response = { + (await self._read_response(disable_decoding=disable_decoding)): ( + await self._read_response(disable_decoding=disable_decoding) + ) + for _ in range(int(response)) + } + # push response + elif byte == b">": + response = [ + ( + await self._read_response( + disable_decoding=disable_decoding, push_request=push_request + ) + ) + for _ in range(int(response)) + ] + res = self.push_handler_func(response) + if not push_request: + return await self._read_response( + disable_decoding=disable_decoding, push_request=push_request + ) + else: + return res + else: + raise InvalidResponse(f"Protocol Error: {raw!r}") + + if isinstance(response, bytes) and disable_decoding is False: + response = self.encoder.decode(response) + return response + + def set_push_handler(self, push_handler_func): + self.push_handler_func = push_handler_func diff --git a/.venv/Lib/site-packages/redis/_parsers/socket.py b/.venv/Lib/site-packages/redis/_parsers/socket.py new file mode 100644 index 00000000..8147243b --- /dev/null +++ b/.venv/Lib/site-packages/redis/_parsers/socket.py @@ -0,0 +1,162 @@ +import errno +import io +import socket +from io import SEEK_END +from typing import Optional, Union + +from ..exceptions import ConnectionError, TimeoutError +from ..utils import SSL_AVAILABLE + +NONBLOCKING_EXCEPTION_ERROR_NUMBERS = {BlockingIOError: errno.EWOULDBLOCK} + +if SSL_AVAILABLE: + import ssl + + if hasattr(ssl, "SSLWantReadError"): + NONBLOCKING_EXCEPTION_ERROR_NUMBERS[ssl.SSLWantReadError] = 2 + NONBLOCKING_EXCEPTION_ERROR_NUMBERS[ssl.SSLWantWriteError] = 2 + else: + NONBLOCKING_EXCEPTION_ERROR_NUMBERS[ssl.SSLError] = 2 + +NONBLOCKING_EXCEPTIONS = tuple(NONBLOCKING_EXCEPTION_ERROR_NUMBERS.keys()) + +SERVER_CLOSED_CONNECTION_ERROR = "Connection closed by server." +SENTINEL = object() + +SYM_CRLF = b"\r\n" + + +class SocketBuffer: + def __init__( + self, socket: socket.socket, socket_read_size: int, socket_timeout: float + ): + self._sock = socket + self.socket_read_size = socket_read_size + self.socket_timeout = socket_timeout + self._buffer = io.BytesIO() + + def unread_bytes(self) -> int: + """ + Remaining unread length of buffer + """ + pos = self._buffer.tell() + end = self._buffer.seek(0, SEEK_END) + self._buffer.seek(pos) + return end - pos + + def _read_from_socket( + self, + length: Optional[int] = None, + timeout: Union[float, object] = SENTINEL, + raise_on_timeout: Optional[bool] = True, + ) -> bool: + sock = self._sock + socket_read_size = self.socket_read_size + marker = 0 + custom_timeout = timeout is not SENTINEL + + buf = self._buffer + current_pos = buf.tell() + buf.seek(0, SEEK_END) + if custom_timeout: + sock.settimeout(timeout) + try: + while True: + data = self._sock.recv(socket_read_size) + # an empty string indicates the server shutdown the socket + if isinstance(data, bytes) and len(data) == 0: + raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR) + buf.write(data) + data_length = len(data) + marker += data_length + + if length is not None and length > marker: + continue + return True + except socket.timeout: + if raise_on_timeout: + raise TimeoutError("Timeout reading from socket") + return False + except NONBLOCKING_EXCEPTIONS as ex: + # if we're in nonblocking mode and the recv raises a + # blocking error, simply return False indicating that + # there's no data to be read. otherwise raise the + # original exception. + allowed = NONBLOCKING_EXCEPTION_ERROR_NUMBERS.get(ex.__class__, -1) + if not raise_on_timeout and ex.errno == allowed: + return False + raise ConnectionError(f"Error while reading from socket: {ex.args}") + finally: + buf.seek(current_pos) + if custom_timeout: + sock.settimeout(self.socket_timeout) + + def can_read(self, timeout: float) -> bool: + return bool(self.unread_bytes()) or self._read_from_socket( + timeout=timeout, raise_on_timeout=False + ) + + def read(self, length: int) -> bytes: + length = length + 2 # make sure to read the \r\n terminator + # BufferIO will return less than requested if buffer is short + data = self._buffer.read(length) + missing = length - len(data) + if missing: + # fill up the buffer and read the remainder + self._read_from_socket(missing) + data += self._buffer.read(missing) + return data[:-2] + + def readline(self) -> bytes: + buf = self._buffer + data = buf.readline() + while not data.endswith(SYM_CRLF): + # there's more data in the socket that we need + self._read_from_socket() + data += buf.readline() + + return data[:-2] + + def get_pos(self) -> int: + """ + Get current read position + """ + return self._buffer.tell() + + def rewind(self, pos: int) -> None: + """ + Rewind the buffer to a specific position, to re-start reading + """ + self._buffer.seek(pos) + + def purge(self) -> None: + """ + After a successful read, purge the read part of buffer + """ + unread = self.unread_bytes() + + # Only if we have read all of the buffer do we truncate, to + # reduce the amount of memory thrashing. This heuristic + # can be changed or removed later. + if unread > 0: + return + + if unread > 0: + # move unread data to the front + view = self._buffer.getbuffer() + view[:unread] = view[-unread:] + self._buffer.truncate(unread) + self._buffer.seek(0) + + def close(self) -> None: + try: + self._buffer.close() + except Exception: + # issue #633 suggests the purge/close somehow raised a + # BadFileDescriptor error. Perhaps the client ran out of + # memory or something else? It's probably OK to ignore + # any error being raised from purge/close since we're + # removing the reference to the instance below. + pass + self._buffer = None + self._sock = None diff --git a/.venv/Lib/site-packages/redis/asyncio/__init__.py b/.venv/Lib/site-packages/redis/asyncio/__init__.py new file mode 100644 index 00000000..3545ab44 --- /dev/null +++ b/.venv/Lib/site-packages/redis/asyncio/__init__.py @@ -0,0 +1,64 @@ +from redis.asyncio.client import Redis, StrictRedis +from redis.asyncio.cluster import RedisCluster +from redis.asyncio.connection import ( + BlockingConnectionPool, + Connection, + ConnectionPool, + SSLConnection, + UnixDomainSocketConnection, +) +from redis.asyncio.sentinel import ( + Sentinel, + SentinelConnectionPool, + SentinelManagedConnection, + SentinelManagedSSLConnection, +) +from redis.asyncio.utils import from_url +from redis.backoff import default_backoff +from redis.exceptions import ( + AuthenticationError, + AuthenticationWrongNumberOfArgsError, + BusyLoadingError, + ChildDeadlockedError, + ConnectionError, + DataError, + InvalidResponse, + OutOfMemoryError, + PubSubError, + ReadOnlyError, + RedisError, + ResponseError, + TimeoutError, + WatchError, +) + +__all__ = [ + "AuthenticationError", + "AuthenticationWrongNumberOfArgsError", + "BlockingConnectionPool", + "BusyLoadingError", + "ChildDeadlockedError", + "Connection", + "ConnectionError", + "ConnectionPool", + "DataError", + "from_url", + "default_backoff", + "InvalidResponse", + "PubSubError", + "OutOfMemoryError", + "ReadOnlyError", + "Redis", + "RedisCluster", + "RedisError", + "ResponseError", + "Sentinel", + "SentinelConnectionPool", + "SentinelManagedConnection", + "SentinelManagedSSLConnection", + "SSLConnection", + "StrictRedis", + "TimeoutError", + "UnixDomainSocketConnection", + "WatchError", +] diff --git a/.venv/Lib/site-packages/redis/asyncio/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/redis/asyncio/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..53424d1659845577612ac79a509cbaaebfeb72ae GIT binary patch literal 1697 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/asyncio/__pycache__/cluster.cpython-311.pyc b/.venv/Lib/site-packages/redis/asyncio/__pycache__/cluster.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1b61c3bdb0eaee75beb815cdf123a02bf3270d44 GIT binary patch literal 73954 zcmce<3vgW5c_w)KiEf~QZlLjgUc870@gVpn_yhs)A(9|PK$O*z+-Tx9NRVg%zTFf> zxM?f45~*ozJFLP?N||^!wbNSK z8I5;qcfbFf`)q)e?0H-?&OP_sbIv`_|NQ@d{{KIJR9svr;QB`W52MmQ3BupegLZjU z&!cXKAiOC^f@GT&Li}zE+1Rr^WM_9r$ieQ;kP~p=@oUMpehALxKp{iJQ zsG5bjW@}=#p<3p5&(_82L-nzSP(!RS)EH|DHL>u5SuxfeYG!`VY)h;))XMzc*|u1F zsGa!>XSc;VLLITrP-mWlS<`eQpnJ7NQ&f!NN_ z&e*QdE*94}yF0cgv?sPVw3j^>&+d!u5ABZ~2pwS0C9{LEgQ0`W@1H#sI~+P3I}$n) zI~qC~I~F`e{c)aJc;p1rBVoBA#Dd?C7hM0oLJ=*8%Zt6$Xe zGvB2KsnMF}YS{c<^M4PX_q7Ls@{^jbvl7a-I|FF1$>g0y zcTTY~izsum^~<4%WE&T{T7FIm$GUu3$I#rZtY>~EjwI>n=(lJdrIp7g<=CnY)tpoL@-H%+Ez;v#yC73rOdjxU~??7La=>B4=IC z%;9yHJsTW~-F|4Ie*ye)!DjNO<`CxpPBfBjeeE z3l~qH8@l*hw&3FEg|nxJhq49ZXU|WBPmg5FE!hmu-iRmAXuh-a5$SkjHZnJbr^?H- zC~bIQW+6H|GZzg{@fOY&Ux_Bdb7{WVTfCOadhPLczF2iGvgDe>ZzgeQ(-FUc-C`0dW&U=wkjKzqf&G(F%y}+AkV)v zL%r+IdWPcHM`an~Cvf~m{1(*!qlbr7s1+NQ=i~8l6ikh%29M0&oZ}%rHH1I;jqc+C z-jPTmqP{y9p{6pD2G2!aHsZ&5tip5iFGVHpuP|47^yR528`fwaby)FOK`P$Zd}0_0 zQB5A`o0y43=WnRRE}oEY4PA-M@G@hh6kuMRiQbyX7P7%klWQXDq>wIGHYi0GotLcnC( zTkbsA;galt9gb|V`WZf{y4(OF<7e=3K14>&KRcH74qrS!j>&c&4RCIVMh**hojZSN zbR_GUxcJ=A$)VF@1c5wZHde#oY+*PYo0o3PM&b8`!(X})nWa%24$DI*wp_fmB3r5Dc5Tz(-wlZf^%AX4N?H2wlQeJ0)?Ay76m-#^9Y zNZ-OO`4oMIoH6{zN8r4o|7EIMRthto3dPg05vt;xaPLsmG`_GW#5w*wioI4<%R9Xv(Na7bO6s4)QeZ_ z(aQYZd`!KZ7!6NJgRiC$lo$Lk!lR#om+&TM|js3;TI6zE!~!$#(g{P7jf^A zz9LQF-s=_UPx|T>bH&>3&*b%s6Jx_PYoX>20>iwNH<{g(7a-1kXglwmTu zpS7i1iXiL&dg=08Huh!;tuAe=h@k&c_pz;x=(|VO~y5vP3LAo`}ea8w(7jj8F0eN%5I@RGgfQ+>Fd5 zCMU%~WOsFNa%OIZ(7&0*=%kpK7pG_DB$R?7uOeZjab!Qm%R8kb=jsdd|pEx^oa(vR%VCqYb#Gf7=H=0a+qhj@&Uksf+8>T!rzqts) z;QYBwIgN~-7<%UH1WTm$0C3Uhpg3`LCa%_8gl}%1Dv1V``WNK+sc1ajKRqvB7YTDz z$H5@$e33ePQ0-$;Op3$2{x{-LiF$5fer66?&0|=p-Ou`uHww>zTGX7w1!`fIer8(i z?xqiPcT=HI5+Vj9b7ISwGUqZlHH(2dIQf-66CTS36U#ahe?p05(5*9a6zKHqET|#i z&A{BunLm3qIw!`XtYVXsCnB>LS(AfoSn#ID$9B6}r9WQ|; zMu0YR_{=0IlN7CuHzD6(ZD-UohG|YyNUbXk9!yhEDmSM1%u{P+DwhhN#M4h~Go$Qg z=%!O@lf2HC&CSRfV9s3n@u+Deh~m{mVj(`*-_Nl6J|Ohc{8YRj3<}U2{qZS)u(>P! zt?X^D)*GnJ^vsnTV1|Gi17V=SP*x#zTG7-CPs{VMupC{OotcUN!cz0ml@v$khz1lX zl1P!@C-6KJhdBv-5auu^_7=gyoxMo)b!vzI*Kyq-z6wu%9cSG zAxk~w?SA^!t0fGLIWBQm#fU$zX zK=npseF#Km;#54WRV*v~BLRm?y`{>!Uo8QuSNDwbDrOUGk)s;o^>Wo-hs0JKG~+|t1XEi+io7%x63kFD2cx8`PsBK$!aTVW1$gPf3;;$N!8D2|01C}tF%6^} ztix$GwXmVkLaWrxd0Dayuvp|}EchD7*D|KS{+o&2h?(GxDWbRl5JXEbgB17*`kGp8 z4!ElvrL|1Y6L==xn@WanJ|SbuB{ECE8+a&gnATYRP05V`xdnrAlG<6uXpc&0H3Bw# zyvHIm7uckjLGuGyK$C;_YlhsHZ;2}YX_S7;;mK!+3c4c_sF!#glQR}sFhlL3IdNWP z^kY5ZTLc)MGgDW4_$bxTI}XV(HGw%sW$X(8j3>}j*G-jHzd}$S^a|R&M~wCX0gs52 zorExAPymbU0=`E(3itq_W9auAGGD9I^rjpE0npMkJ}5iZY|#h?8P?f8QALlfs4eQp z;;VT9%tS2knX0B|7#G8U^>f$56oNHUMxg+e%xQUJ&_HJ77S_dErt+cdd3G@X&KvNe z&luEV`GLiV{=^5+mxL$3d`rdBlb8>LAx`t6%2#g0u+$(aH3(Zh*!)9Lj6tc7D2~*q ztja!P6!Z=2!x;k%s2S}esKrsoD5vfQ+0cul474x9A)=0N8G{3`fygY7P-^LD(9g`h z1ndc`q%7W;yFLdNexEpcMJJmWMJZjL6q^r=J1Ei^NG`p-K!svmygI4p$&k|{gz8!mYm)ZU{11yh*#{ zB*wN~ND7i`26??>`(4`8b4UK2Q)LU#x(Ap_GY5DZb)+^xRY;DOWaup52*X8b4qcf6 z_gj4C;#qYVQYI(RNzs=hF-*uoQ#aBpHqd}YKmR<4Gfeqd^u@vF39J)sru6+mkcj#TFCng;HbEnpmPk_XYQZdCia45nQXymC>epE7*5(7#rf^@$)7fPEvYh>5Zl#X}mkaP#KPzM05eq;Fonf~^2TrrEUYzah``szo8f`z20S z9MKD`6@#j4E(dl;#G5iURM83leaaL+qH%l(I!1|LXC23vW9qja#v7o{q%a_-jAjMc z!KSc$3rGTCV3^}K)Mn?XfL>K1y>48&3Mv+p3fotGAe7?Kz8iC2x&e*_h*uy5_zKot zhTSd9MyAl-03%q6u>+InC0q;K0`(Jmz8ao9BLfBi@uodr+R7n}g7#a%%rXtyp}g|) zC5(>~5M_)5fB}!p(D?E^XdvRDUAUFFO4vPiu;YE=@p;e`kvY8t2AorwMRAp&QIU9S z)3gwU+|u8|xC|`>=~|wP#t|?!-(p~5mv}oest36e=YXI)N)(krMX;hyMbJqYw3Cx8 zHpf~SON3AX6-hV`P_CDhH90zxrnI@&j2cj%s)&>hYkBLam|bFC&+XS+SJ>jFt|mr3 zPxJK~^Q{>Te|R`mbPT^t zy|{E@dCzO-GXAoq_|omA+sl{8O?m3sW*_#-i^4jI3o(o^ZSQC6pF})mi&YvwJUtt^ z63_ZIl0VFbfSheIH55Z3^QfPyD#1iCjY@Gcl)|{kMwl>4A`#-*0Ky=oVT6p${2%DPi4#Ak#rNmbQ~yW~U3NjH zwR6$KV0-Vvtwq<3#B}fetefT_q*m~Pu>z%^Q@pH`)}XADaLa751s{-4(EExlIfwEr z-pO<1NaS3hsQx@sBWsr~BWJ+LY!IVfm467U2!@>XXaF|r(H6#R5yup{c!r0z_?e(a zk!7==bpqx`*01?E5|5U`#y)k7)`;Zd08e z(=JktIk%a-abgn^#`c_Wtyud|UR~OyTGl@8t0h_t^Igg-ja2`VAUC5`YmLkw(`$`J zKKV786F*lD;^T8jwxiYc9!fgo!7IY;ZAk}28h76ANN!s-^?{K~qQmefJFe+{1Am3~ zX4($oM7XBsO=L=b`S0vXZoBQ6v*VkNq)qNj+GTwEb9~d5w11xb6TMn#FmfG9Cu-aF zLBsbjQs38SCF)NI0=p6enh){IlEGxTRZanM_3lc#@KmeCPrC6$kda-<0zB30PaZrq zXiri#p7cIV9M!@%%?=?fYVXjF&6?kka9GvHqV|sNdE-(Dw`y-KxwL7apEDO7(ppCx z>atDC$&$Z5LOy5yomwtZsBiwB~f&6VATkIcF(MhpGy4)dZ zn^HQffyfVy=}#Lii@PAE`m!j^#~`?;(S)Ft2@}@|%KSu;0jwz(P0SHc!VKR43Z1{X zM`RA$xu)GYLdeyx_Z42CT|k`|VcL2I(_?ma{w5*E#6>|I^S5+-lrds@8MVe}G`1mY ziOP6thg)9Wgr$bXmo1?)5O?^3`w$yp}nTjab!&hNn?EEFB1V@D)}${eTO~N~ZT304GD(@oaAVsR;^j%n=p(<`H z(@K+dPR%de$~qwCAqOc5Eno6gdgCTm%bdipe)%Q^zf8eC8q;yej1X-jU#IW@IWy#J zK?TS$dO`S&Ox>RKhWSV)`Bg(!M7~DvidAuMEFsTD{;SL?-Ua`h@+0j2$uo*g7dA!M z$fH?KTxt$mvQ9=p(uf7%`COMumTO}(k1W@M{|-6E4`L|?S^fo^;48@q4sXfBvW`q( z=o5!MSn>-24#sA2NzNnq0>!62Dp}1jXF4sl=ZlSU+Q!VCt=|Rw(C3kM8 z;PdAMpSNVgSN6?wub=z4b5EviN2awe)4r2D-G|`M`8}m&IRVZmj>2Lz6`UM%ss&#o z`oMc|V|)JxN0&~df*omJ=SD^ClJibsrU<>_^$skLv0G}}=ts8oZKqS)PH)sus@jrw z+aCs+(t&0r(41;Lj(%&UZfz}D8oBcnTD!c3`gh3oam&CD52c!qEth0`fjdt<@b#_x z`qsXZ_8n1tM^e5c8D934eXAqyJe8{LPy2Q#z8xvwj*mO`Djf&Y9fy^U!%OazzcuY? zQ&~C7*V0AJN>TIb7g9yN_#qDzUh#E4@b$0z`hT`#B<&kje4{D$L+d>5ZKkhU#b`7*%g#)o{z0I1J<$5FylK_>j(2VM2M1E+=kdGmRQ8W? zFREW!hU!yO>yBG!=vq3rbZ(=*ap_#92z_PqPS}<)km;WB)jaTt>pt<_y0wXWyHm{< z@w>lUIrud9rhVgzZ#?B2|G1$GaWlSVR5MfCk@LD53qKLy{DK@Rf9)@QLUq&1%WF-k z!KczyXOyZl=tEzoWjDQT((gT|=(#J?KSuYSOj|qMn;$mqOgHUTnpo`mOl{*^eM;@F z2etdxYxk#X2bJ1Ec(Qri|G3 zPKhEOeISmkiz8|Agd(1x7Y#YLy_nV`I4;3kjF6144($ekd!GPC9O6`GdIxCmE#Z%? zQd3yz^o!PYLO&k4LCT*IY_#hm5J2ab{Gafo$B$Phz;4j4YYxq4UEP7M>M6{rcMD&) zNwzOLE(vcse#Z&2+x(qXFFgag@oUxe9W5*$-Tyk+9G2XuF6`PmwK@N51zKDyE@I77 zvZF3qL}6~MRY=f!sa|b@Jj7~Yl-jGkGvBSPWBr1;OlX2FE-8=wVom=w;imAi<2m6b zT9*E-Oop%9%`G%n+A0hP=CHW)rk$s@3D2SLsWu=loQqGL#16@0+PuvKpkx zw_>+V-)x2O6c=za7@<<%*a^0rcNH2dezri}vz3XYWOzun&`85^4WA}tK}Ey7);jR%y*1F7mQe&%TR{prS2O5>?i^%lQObwjQI znSc7}r@2x~vwT9W^o!4Ks?X7ykBvfK-RcX~LZE!9C{C2}k37RW9RGSKa6DlDiQfkQ zPXa?l!*#B|sB_@qFLo3T4;K8zVH@17VIk0~Ens1M6|U%%vnGX=o_NRyW9o@ zk^e^o7|=uhAwB*Gju{kC;9}4M3OLyKeF6i&ZGZuPQ1Ler20UteG8}LgkJ@s==XC)* zl&TI)!&2niv3+?&DQ^QFpw#v}sNJ<*yDMG0N2%SDD&OK~j&|>Sx^_gV9Z8jM@ymJh zOY;dU-!DFQDL;RGK2JX|usybnWTe z(YIr<{23Z54BU5iVO&7mHX>zREC5V^0-}cMnpXc`|y&lQ9%0r!EauF{rYRMJF%3f?s31(n4MnjL1gx8R$I{Us&O!bs0y^K z=1(xvVU1wEM&)ogZ^<=Yyoc&MB4U_VCsR@LX84V8x?-DBu`T7_^z&?E70G&{FHeO@ zJ|XKRALIFCy`*p+rG}o;K^k(_EBYJsuU=6y;4m)8|C;Lg=WyP0GSou;3kvv4a()UY zPTwV(o|Ek0heV<;&m>U)N=r}b;U7?M_8^g3{gSfZxGxFYel!M$F!WX2H(%D_yNYjb zzN~T7D!*rEJxmN9rs)JVZe)aXQrv0Mg7a#b$ z*ZtjTe~;qtNqKr$*DlsSGsgzHWMRUpupiO@m_(Sx;Vbg&lulqEYg)Qk6Z``_Rt6-5 z!}1VcIc!;~VelepLkNu&c6}E{QIf)U?Qc8GLT5?g1BZ1F#3m3~VooVJ-?HC!AV0gc zAy>^KQu_?{VXWi@A7vmT3iT)g$OsTa&$02RBl8%GG#lZnXovRdC*HQfJzN%ak2PNDIXa<8$LHWK0b7EH0!?@7K+tOZpCCMX% zF|)W4fG`v4C&LRDA^nZrb0&M!rA~prL0RSh1x~gA%XK39aw2aU6okW4bQY7KJZ}=P z&>zqg_){c*Mfhc*;0rGAUTH`dbtpwx8r|NCdroD?G3LwoN|#2LCkQZ<4dAy{&hI}w z`qA!`??T#lLGfLH2Ry3cicEXgJxSSnGF5vDzvY5VpnTc+E%#mbgFx?kpm*&`I z>`iIEPag)c#M_F&_tG4eWZ9W>Ab{4bB9w*|#Bk!oXZ=yfP?PZEroy3K$B%n#aI=L5 z+G1gn(-`eab@YI!GeM%HZR@FaX( zUuWqdGhiZ0^AW|b!LS06i(^@jrqq+QpFe}OKvVHi#dO5!2t*&GE|>g=C<+83z?%m1 zn`te|BNSB3Mb}2f_w%A~$>s7I9ZKnw+Hs zH`Ey|Nc)QLu|G%%@HVA<=Y#SC>*WX1&30NNqLwFQ;CPPT%W)x>rTQFNRJYy(+E!J89 zA!Vh%OQTI5(S{fJ4@7u0KkyH(`v?DgU)n#c_=i)T;s1_Jq3Y$SJe{qZLMC7)Q!j3+ zwU271>GmzwY^t>O>Sw64{J&EU6L2iZxf=njmuW-CI`WNiZvkzB!FT-i_=VOnVSQq= zqnSoX1fr&M*d}LfqA4cmGsF$CdG;Dh@YVSl2zluX3H*hgL&D7H06^!Isf&)qfQ=0F4(X1fj37RG*8=BcK^ZQ?;O6j`v(VB z4yWr5D|Lr?_`|ZgRQ>sM*#)JHaJ-G~KDG@4gF-3x<74BO$ZksS89Y#rGVnn}u62-a zy-1*!?ZC>B#xSMFCc!qE1grs}SY}qz(t3xrc%L>8{t4gHXheO3U8eF`kz<)6=I!We z&Hs+dE_hHk8rQ*zMo z#3+S65C|jJZP%P#a^H4A$jxL52;Eo^If*vaXDW56Y4G#zwQ5yx%`#n4ij)OR>J_Te zAOa0-FkJ_nsk9s6;0i$X{WO#{$k-X%3yENEvRGpL>imsa(nm)K=_*+?8IeveGUXz2 z_+U~B#N1|ED|&uV0|%#xsb`~bo59T%R@@liq1HeGO}$mKVSph|swt$xZGf6zxhWU1 zWl?O|BEG3z`(%R5V?QTg$|ZI{j^Znnor+A77a~XunS7U`(R|H1W}|ap>oR!rD+>L; zDbz`kvxVgH6j=|0cr((=aY7eZ3#lBKQf)4A8GU?ov2oMV!%{Qt2E6|zO}gJhHkfqv zm~`JvzMfne=KP8!C-_rJMTb(c>p{i7^@@G>o#~3hO2y%&!i>L$0M)a$hh-2ocxEjD zhyT)Lmz1(gDc_}yBJ5MUyfqK~Wy`yjV7n3=xYwoxf!OU={QK_@tOL>Y9|Bi+IgzQV zUOKgOYJ+YY{+g9e#owCpwDLuqXdUg+;oAj-SkWW%B-&c&Du2RTCl!NwU)KlT2~y5f zhX*x1=Wwc;a%eZxtRNc`zma7Ll8*0J{f(z6aIY*Q>X$4X3MjDAhaC{sF~LgxwR6CEDM$t|P3S zbmBqP8PU|lb(EPSNj5G@^&=`Z%?5Rp7SSkGQ!Z9-8lUPL*bEcm#28|f!JQ;ny}y1z zPiioaE4hfenv-D}Kqhg(z9*~A_I25qB-tiZuY#&#us_25Gm9;oDzzz2167X}0hRC} zO8nQXA7js=WOtCurjjvolxb>gL5{NUW}|_@ro6M5^3*(G#t~wVkpQgF5CH(*N!_~X zvhr0RPu_nUx)h(aq)Na!H%s6nom2Y&a`KY2c+z2%;ZEV59gOb+@knY2a8+1){5|}< z&%OvBIDkeE#5GnPi%6Iq$qvrVSy7d&mr%H^T2K#fqZYi1^kDR=B2DGhZ;rh&mM(9@ z?iTjCyx0JTvor$1B*oYAz}L0z>ss4)Z#30CnD!l1dWE?)S_hQGO%{9!N;$p?GQZb=1tQ$FoK9? zia}#HF@1m9R_GhU;3A<#fTRy_lgrTCa*$RG`UVyr&iAk24U(tZl{X2tjI*5@umX8u z5^UeaWP4T%(w@!~`?1<~X&64Kx@DcvWsJ*}D1uHC(FmkF*+qrFmg{kJHKwPdU}O|@Jl8RJbCspgw>Vr*9ctNze- zQTSaj!VR7_;?SUH*SsfbOY~?@g7A`H6wgOl}{jl>yrYu2k9 zsN)=~W{M2PG_yE8&KOu(uWpf!^KCw+T#03qb#se!^8ZO8|B*t5ZatAU*z6Q3v){GXCn7k+;T_`hDyEeJTGwo&@nyRr^zc z{rc;By-|LzSER_J;*x_?*7zw5K2skwbzRkt$2B$);u z)DNxK52fpemHOdy)re9xk_wFI*#apZNcjgou5Ns*_+4pjx3c}PviNf{Ne3X&&Ve(2Z`>&$vIpBNKv}Hs(_>p4bia#!5E}12R!_S3Tt2c zwc)IpIjzp@ii8dw0Z$;RXQ)9~XCfezZB@q!P#*oVLKevmJ-cZOp`FL&(h2Fxgh`(Y z+MG0R?KE${E4-bThRAoxAvy9&Ya+a@rCmhne%o}U0q_?`ywM^&6GT(sl(&`&Mmc>4iLoh~!d7K;3J? zs=mtToeEFV@ubnP1T`7S^Qwn57p)`Uw$t)mr?qGBUACsnW#$?rZD87Xx9D}}=h0>Z zbyTRT>DaT*(Mv;TapVEq@l!*LE3jB|S~ZkIhzw(Ca$Igul>cAU6jt|LCrC9U>tVO> z#q*1=jLnNTVF8M3ltGpT=7hKx_=l#^c8Whu zfsFG^A7afQ6Hx>5#Xz-b&CEI}Le@o9jK`_coAhTOV>Izk= zx&qWSs#k0)L+?6PN7hQ;Ir%Sr@A%U7J*ny*CD^+(Lh2k)kg!3f@L^R0Bn8)OKih6B zkwgeVM9wYL?prBWYI>ELz4vaWYEFDu4oCe3pXWnEEB0>m@5;Gw2ZB+t_Y;Sc>H-JC zd!=Q+EP+M$VovTm3Q;-gJD#6Z_uM;bC>27^^tx52v z1G|*Kt|iyQqLQT>uMOTATq%A1=+aSATME{u0;Bwgrpwb`3RHaa*6X)k`|_PHr#!Ws z3iO#x8tc>$#)m*_BSALx$Op4>B5+N8MFGYSzp=s)CJM|{fB%vu0fzZmNER3&@(yz| zu($%T8bUxdu2esUmzgV-Ee=D$lCv2>wB>F8THd`%!;_0jJp|*g=lc#-Jj#FJUj2vV zf7z58xRCN(U^TYX(XG|793Ri)1U{jTGPnn~?a=Z?D(ym>n6L?Jn}GHME`Su5@>0-rEfbaN`Xd^Mzp}|W!)|?tSf#%A>y8Bdu(IVs?F7#P|jc$?xFXuLuu|Dwb#89Z45;DMjGV1iU4ga&c*NY4jn~ z`F!tQPZ#f0ig%L6M9D@)^YWPSN=g@RSBkeoGT&SBOOH@dvr_+{rf0pTCtcI0)bypx z`<3#3ivDp~UC!<(J@`wv(6N2(PbW!rwJ6O()9`kM*42GbD z276)zjF}hz)om~8L2DwrOADM8aE8b~E^3i{2@fjG-(WEz?a7||vE!mdrAPF2&5lDhfsThHz z_x^3)rqb_xQt8dir$oE)^<+`fXPqb3(VAbg-!vcI9uSz_W_%k0v%78=C*6|mI$LVw zZ3*JQs8_PsS`ze(&U(70Gyl+QMaaRuh!J($4dGko?c%Q#FWc_?X|fn%jqK^BO&7<- zu5*_!LfEywYc;A87ZJz{-6WZRm<&^GWMgfd$}IwLw!Lm_8pm7c1w~eK+t(nFJftJ6WebH1m zBH;8~wViP~SOTf^a6;94Ep;5!%=8)-1GctBJqC{0q$ML}(V9-&)AA3UD59R(#=x(d zK`--B1tYg)_H~-f*HZ=>1^lZb?UO)+EYvNnRgAi=hv!Y<3emRS+t`>Qe3xI}vfn9G z>DTvcOl0UiyWD|7$bXCoW<2;;g@*_u;`3G1;jrhX4m7-80y>gT!(o3REk8JsW^1J!3U!)dNwhHxOe4GeZ%a)~D556kmBo zr}nSl=t`+4~c4`0v9@{0`!)0ZN;2zz5YbFtXBptns_5xRF32-Q`_02ynhCuu)FwU#3u| zD}+`P(o7P4M_ zj>-Ed0ow{F8@+h({KfGw(DU=p;-pF(wFe#rVGNnJd==n=__piz!qf!jgym;qH*!vLcf+=T_p1O7kO{LOPzWP z(-JBPD%-zJ2v#kB>2AkTL8hu^$(L!~mhv=aY8sT9!KIRonx;Rf{Z8%b*u9Z-%>kw6 zz*0%32)hIhZ_{eqgO=UvExYf1G2Jqvw7^6H0yA|@59)TU*X_DDmaZFC>V{#Pp}i~R zYsoY;E{%b0P~Wifm2_Qi%2WNYv@%uIkuL32N}*D`%Uk~mIZH#>Jm(6N#XB;UwQtV9 zF`usNP%6P%-{SXiIVgv8dAm~HzE-+k-kmD%&Q!OpKK+(|ZTExi$JVzWOK(4}Y(KtU zeLPit9N({~c~IWFUf#<|hE#cf&fZ;IpQ(b45>ILEM%R(Ga;57Cst@x!-IbZHee4dd zMRz5fw#PfmXQ_5fIlA^?nHZgzgvnlIuc{o$mNFu!0dZAyY>F`Pdh9T}ft29C5yLEN; z-oQKa%C^D#!>RUTsEtVa-ePTL`o)TC+oDf-)Bu<~9HfMmMvs8V-ydE{Yh z_d7>&_9sndK!~nAuzFEj3#%8kP&KE>jsj}Fg2u-?%O_yMr5Ypav9)=3;`^;@(!CSu z?t@DA!F2l}r5&0NdYz7)Fdp*i1d6a;WX!T{X>mXi2hw#rmAaj&a`gulo_dUdVv~~z zHm?q?2isG@_V2f?ed)c94?6Bm{NRhqo=d52`q6M|U5%v6JC?^X<@L*_=V-+)fulvPCBFVqx77#AmeXW#FrPg_3M9+ip8S{{j013knhVMbsvgZx~*?YzK~7 zAUPP0S^z~fr@Z@d0w_uM2YHknt>IhKtdh%$A)7a9p`eCx%?-mO<`CQ3)oIzJJ#VW8 zhW-q}fX7(epg1~xI$wf~B-6%FLZ^i`Zvx*26@S}BYI~-&nv5*6HQHQa(mgj@YeASjbwaw(6cNI88TApmm?SouV41PB7k zj5ExClYGonmLV!2xu4YEXd5eSCEfNWg_mu{rand>sNE@hxLhkEdR3>X)C&Gg!EL9W`$0YTy;=&E`*!pg3}G5GS@JGoyYf1Vgl)!F zBetn$3ZK+7&k1u*jRG}8g?mMb14eFAku{I6*}8nNxk9bZNrYd(mv!UR;?rX%{{v5# zIywOq-Vj@V3Bgys^ZRtYcXY92V&W_)hpRBh4yA&=u7<2dx%nbjH$WsN+b&-u9EkR1 zxGY8^`DW?sM3l?@!kncVwsWFAwP>MOqQ0jjznUXz=a?` z4Tp(h=HYTOA*=a98+i!ae=e`bAv1 z2t{0xl*T=&#*6pc?tkgeI)3_MYVabkqt;502(6XNXOJPjFuKvOf8}|lVL$f38cu(> z4G#UPHvIypKYdu<_OopVQo%vm?E-G0IhjDk!}8X5Uq}VPQufjt-6<4GE0jQs64>z| zuzNkQ``+`)p3x5z>A+bfa5fbnOs=Z#&FgPm|5og7EEQ(v)h)fYBu8~!s zyYGD|U9*2ZxIY!#|FE|Ct==_fy0%xTrP6Hv0fllQ7eb|O+5~Kwva$WkufSiIs@t9} z=}}6^2msS;d;56N@h;&fUB|mlRXcuKHdK3J!0~Seit+Gojx?MU9e*Y6f&Zf_8(iR3 zATHxL`hpIJFJ$85VH_ot$okctmkTosQ5;DZ-C8JA0yrR{&^-I+dD>y5|CJYGlN^j? zpKFu!V3%X@KkKZTVa6Q*w+B=rKbnS4t=+_+(n=17*kw9)%*2#a>n6_7fi!gb3OkOG z7*`8wbz#gGY9=NFzM`q2h%;t1l_}rP!M`$^+nNhIeFo<)Ca&JfKec4B)A$(iyd*&I zDCxmKaV5_XahJK2PmGG~R>mQS0O)FaUu0TNo+R*0m?^+Br?EX+qvWYtX~FvtJAND~ zp!I=GegZ$yxPTF^QZ(0uxt1cmg9TT#vWaE1&WFTqUFPMP;t zX!nHb_lW9`!RvmdAOW9t-F5>r2Hn7w*+>g2S@41Vdk`mkAOHLU$J!A&3lu~jlNZfH z@hpm=DKYS~=OA?W+ClWhh-nHW$Z z%-31)(di(bye}Bpv7;&pq_G2kSbgqv1(tq-Qi3`L7itw$LkrVEKbkP!yY@P5FLpEfvXL2Hs^x_jZL=uOC(lOpR zj>`n}sM$AXfZia;OVc_stLLU>0Neg}PraZ;W6g~NOaZMDG?Y=E9)>m`1}hw-2Qk(3 zj5P4YztSfT<5*;zYtHMW3(trI)d}m$+x(;8L6P+|6|#3gn<41e*e$B;b)4kQPC3K( z5g8}-5Dea&tV{c{5tQyeq9g{GzLuvv^g07EtxKwB^11Y}+b zYLBhIhxPc$U)ia(tYow-`t>I7el{f{F9Eo-GeWoihTc3|H0sN@7Po5Dy{1~?NYXKwCT}}#iN_e0**8CqVX}VO%4V=jQOK?4eN5= z(*xp7rfH4wP9IfAIA37UCoNPfR!Sbta+ z7n*>>X*ym5_ynD2LFd5Hv_mYACuFOO_V(F98T<>TiL6z!k4~c08%sTr5+H7xV3P{0 zuv1Qu23x%(*QPd=x)NbwU`1lJWII^~xMP5U%Bv4#Doq4!CSPY0oWT_Ysl6x80wutj z1dNVV|WRgsR#vo z!CG8A4@eE{;08|DHsfdjwJZg))O!FM{PacIfWx_mB&dP0z>cX^HzlbV*!(w@$bhkW z*T8y)93={b@O*iioGavzj*d+1#4Zo#J2A%ARxz(?(c^^gYa@;mF;1%2VyR`{oPtg} zK)f75bPz8|SpKg}6*WApX;^v+O6g0BP_(39d0nQgDpS#rY3R+=w8KDs0QSt`{DK^^ z!_IYEKvRW~ll&|k@Bqm__MV5CIUJM!lAf5M!!iCwi+utwpyBk#xXI*K(>cb*U>x!U z-rS+UI{gh~F~_>xW3q(WPK=FBbdAX8>E#7-o`#bpn{o3~I7p(1;Q&~jug**IPHG+0 zR*)kU3FZiy6gbQg6743F(4S1ace#rqQVV9CmvMZh+)G{;!-HfZp0cjXw_t=pCRV7)lOu5{z^2G%)B zOTJ=qO35KcxLiR#wt3E2uKEraWh0ICK673`c>K4} zkgw=}Is4N#mnSDMciJwvOLO){SHsG#oPgUJSZcW41G@+}!}-L4h_61+qUMg-0;TR( zPUFCZrdF7)-`ICBv#mSR+L>u-&GhtU`gdfS+BO=SU~oEf=oq+<^lR_RwDe@!cdv%i z?R%B>y&Kg{nWhfxb#HWZW_Ip{Co^_2)7_V8?Z^xs*(k4}ERm?8L(Q8qXw95HmwUz* zvAe)gBzL2vayfn{mUFQn*itQD9$pD9pSm-jD_}u|LbbT+TzydycPUl7b44uBCx~si zV&*Lo8k%!{<_!o9Vy={V%Y=^ZT#$Loh3?*51@l%4wGFu{=Eb=cWy`J0@#W4t=W}%| zs9x|_v9dI<$3~%XTMELj4F_^fEI<^3bt}8>_U4+|V~h6K${yQ<%EpzcyD#S2+2c0t zZ3lbo)ZTWn#~vYAnd@cVJ}Of`^X?GpnsNioyIT<3b9arg^Zen0p7v=TfDH<@Wyg8I1Tqs>J!`FN@wM7}&)nbjq2vDk zAB0m~BZ@exRGrX9&?TEtSb~jVRu?v$_@GkV6RuJhtQuLJZC)1{Hs0h`3htVet9rF6 zHE{ByD=F8dwCj@Mx&+M&7j~UBhi1{UHa*;9bHPZa)p6S>fz?4+@5+JI@wK*lC8_o! zkO80=5SXw!Pzl-j%319ES2o^#5etS=-jgdRa>3{&oDF|j&P5NHBxO9ikw;r*1z?0CHNXmx4{Mgb7D;tY@i*KsmR4OfR7EC@})r)~jzgltIt z%JAL8YJx(cuxzXr*#eK|+13vC4l>~;2#X>Mot4R0w=?$TngXx!QF zcI{k2Q{zUU7q@&TfWfo!ELGJskoY6oVB2b9ZTMdG{nj5eqc03XwYEi$m+OVE_~eTl-OOn*TyNQ-Kj(8`2FG~cF%VTg%R5+Th1Z6fQe{MrV0Wl zc*wMFw#?N4HQ` zyV8EQDObQAJy5>Ld6~BmGHAIX=Jg5q{GPY^bH(hjM5t(3fr-MmLP~jO&d8rAAW?cxjsOu8x@} zY++dW;&&MJqV7FKKyu#HG-OG(TBT7(VT8*Z4E86T2S>V}vxymSDvWI^#;*7bOF`_D zeD{i5#V1nEY(I}PF|Z-;M-Rfj_p}_1@?#6Hq6PWp{g=tdXr`CRHxCC#DjP;u$K*JI zK#j17gtVGA{l82IuJMB9N_35GC=eU+0-^te{XYV(KszdsFVeJCww4plS34tlDrgMY zNyGqVNZgWx`N%vF<cSFDkD*4T6qCY{vV!26~uTML9 z?>(ZwNj8OV9tM^Vt`{|?iW(mVYm{IIcEy9eOrv+B4R(BLR<@-*%^8!oyc)-Ec{BX> zu)KM-4N1y-v8~U->$b5|x;C1a#moAPxPzV>GR-^b-k53G^`K?nI)q2}pZ(}^y5(u5 zk5#4Ow|S zlZ{AyeB&8o(=d{XXV=?a>@>Q^7TwQNj~-quP|sc^5B2Wh#gZPddUX5Ahks>z5ex&P zbJ(y5$n@7N-rT;w?|yeGZE|eB514ymQO^ zj4rr)ItRUKEdowPQ+lzC8X;F9?7Ewl1qjE5$ z*}QRZeNe_^p_T#6V}tp3&@N_Gi>x~wj(!PEQ)X=%3j1qn7!iq~&Gd6>DbFZda~JFM0~t(Nse8ln-yj=i{C|ontzE>PV2zN42hh|c z_Xd+?m&pu=F^c5pNRBga9N~G3;}`5!!>n5zzu>^}3r^(s`Ho-6lZmwna{)+;nqVem zEgf|Df+1dYwCg*>J18bFR8S@zj>P98TB$6`}=WofOM$ya~=G20J)(|KV3ZN~8i4>A-{%n1Cnebe7g+x_a-oDT8NHjc4&&K8b0u zJo2p*cTYShA6PFRxYv;`A5_W*Q|$NY!zx0bOCgk|IV?UVO=%5;eKzRJ%Ptb5234aK zj-8wECmlmo_8(Uj4z;;{+-ieMJSqL6#qaC*fAj_%E)>1>LM++X8QD4z%2$h&V4X%) z7uC;Dfbx&Nd_f4+i5zU3(&a6YWC=~izj~^HYiv_-nV!*Qy|~bn>VBM-(c@&VzlYTC zX^vW4KTW6v1d2noOhrd{+9xtL*s45o^(*kv9`MxrhB zhyFc{uXD&ml~fcQCD6Ktvr*poONUTetpr+EpL)=CV7=`?y6vFSb}$_{qy!+&uSI0B z^Be|LvZY+`$&lBKPi)-!nO>MDyy~WTnOr4%MzFI5&!GB>Z z{R6eqfZj@};3$48!{6_|H~!~c>FyDwdjtW?!~BKWWi5fVj;64D5=G*$!wGe-geK1f zZWT0~pp|KnXOe%Hda`osp4^}UeOoWk!}7YjV^FEr`i_J-VaWr}pHN@Iz!ly&+!b^} zZ&NEyIe|~$j-Py6J4+7O{O|{Pbyj!bo(_&GL6X5NIjfYMU2xo9sj#Lri)VVVf`OG+`qCwC<`Gfc6VeV>iukEH3(c>!iXP9nHSZ z(#t!re3;Y{Bsy~3gzl0OAdr1ij$5m~=MxAJ0JlxqpMx5ABB+%#UqSwBx=Jy2NVr9y zLWZ+u3l`=4(c#RHokd99~-x6zcPThW|&) zXgv;Iyn@_&$K?Eytf^gE$@Dysy7CD{R0Rfn#gc8uJ&d>4AFGKJIJQ(Qf_H zTn7*qnnCJ?v0sa^uM>o1D-1R9CmrT6gH^ysq;X8FITlM<``EgezL8%SW`|RsSNMK8 zn^Ss7(!_pAI;UxdF~uF2IB=3+B6b9A*?_uV3}k0&o`m6mTs5Ma^1mmC5qk&7*FX-V zB~?>VwC-`!tkmyWk7ma;53wRWPB|V04Z#hyF4mf-f%V;gqA5VTahlM+*IV|`U$^p7 z%HNJ(rg{5=<^$`^2XGQq^MQ2p1*Q2ysxJSx?8yWw-z}Z^dmzB=2lv+DEi;^l{)W}cl)nSNOjX0%b4pcjDxm&wR2EF8c*`&~=uEBJ zl}o9jR{ZGP@26gW>f1O8e4FCimhx=_J0C}G!9XG%=}o742X~Qia+ph0g1hdWN(E2i z_o18LQ@)cM{;DNEJCgC$p;~tCm3Z9Y_=(L9mnl+MKs$B#H}U_d1x=@|;;RVQd|3xM zQ3zX4Jq#p=L2)K+zq{#hH}eD`3V{th^dG;#OR<@?%*YZ&QnTWrBZyuC`TCOa811z@ z%OYf6_6@5xY-%=s%0pUcf zo^?p<_l~TEl-`jKrBv^kkDf`Fj4LJMDbE(aoZIQ`&eZe}8Pc;Bx?g@j@@G}4nlt!) z2!myGPX#yqe56lOTuNuyH>~>_R<5OeU5XF-$n^V^j=kUV1(pQjXZ>02&`#mUJL`{^ zIA9x^+u(?2{hC<)Fb}cN?*vP~j{irHr1I6CK7o%J@(H&M;igRd? z_I*9Qb#TLQ5r#8J>T|cj>dqVJ_N3Do!jkFm3^wGQ2Hry$jXB?>Gpw&DclxltkVu7k zVSNeWU=19tVZ?zs6dW-Q#W&YiTz5|JyI~v!6G>kwwl@0%VjXR5tfjz|=uDkF3X7V6 zQCMy8Xt3nPBC9P57323A7{84{rT0{l=wBeM86DyzQU6wRK~oLbf-q{K`9a0t^CQ)E z9KU<5tK;u{f&0xaLwNbLo&cAd=C%A5oNTdq9>@7a*5@tGk&4E_aOc7)#J1$~TRjcq zUr+#B=ZHX%sajkqjXI8Ix~BM`+a}PevsnM6%GOiOb|A~op7|MHay048__I@?) z>9*qvT;FlUcl^UqXodM9Ujzpme%{Y=3L$&}s(}=h3cTDQl{a^BU8Z&K>TacVZ>GF) z)$xu8wi1h=B;JO#5Kg9l=Ld_%Bf=W##n#TUgKWru3Qh8I$fnqfnNk#YVBUbd!;&!J!?Fu_C5If^bh4E@M{Ew@;kK64(u@@e1a{a{T zJznejNv#Wher)V4nzgGwPtZwTp#GD|VUj^R$!CZ#F^MK0^)4-7Tr}yoDGKpHUyW|_EC==v7L(U1!xl8EIr-<>2{s(gb zB=tj1NfDFYX%V({=e)J9XKk>;CbnmK_vQTT37gmmV=j~!bJ(`VBbE%4Yz+${K?5eU zqGbY6lw$U#1l+8ZMWwb|%`qS}Vn>p_;`@cnYx)lVT5iA7Rk#9v6mI#B&xY+&dPnzF zw$*!rZT0547#ahcgdj>>AYS1xAqaXvZ6E|eJ}v~IMPRYGBNkF3t5fZDb*?@|A_kz7 ztWITxt2$HLmUGa(eu@R^!$H5aHQ>>!7#7xzR&261N{*;gavF4nDia}9-F-8 z@?kr*82Od34Prl)Q*xTWE(Nv-D@C2CEFP&0Y5mx?4PuKm!15@^wrmA^@0@mH3)dAY z#TIS>HkU2!f=%LTq$xw%8r*|Y3pR8S3%NS6nd=Ibqh!=27V8|hYef|0o3P{uZf&6zmq^-v&wi&! zwQMCHp>{h8$BaI}pcR?pBnkc_i(Ryd9zVx+%Vm9Y(1bqdQJH+nzw?rcX^@*hzFX((u03tJ@2qk!3ZvRJWYxreEYQC3DA zKG%5KhJxMig_CYLr8JzPEymhR`ykz0^u5T2ZWg|=y`SzinLYdHUY$93nB5}e zci28=6C_P2tRcmId=WA>{eFoLPf;If7YzV5`2HRq+Mkz4!HysPjrQqHn`^6-=cX%v zXCBNR3|s>Vx1y_HS~z4nT16k+Tj!d8LLL}_M5CzJ=EIY5aI$=xI`vsNi=&#&ILO{J zwZ8acY}O9+LCFL1|FpR(?(7q3+m*}u&&vrAmS3eTUm=G81vl2+LB8GO{AW1UQz_IF z3N3>~E6X!9NS2TUoI#)93t-9dmMo938&2+A{_?uNCFO5n_N%wAjijpvl&S%o<`b+^ zf~^mN9qYl4?-$?S4dSu$OuF-o0ylV837$>)&Spq2zW@eiO>x(}>EKQ!xHIM3$;`ys zOIu-xn(V>C!Gd30!p6}F?8?qcSqJ1>vW0S#Y&nDxu=RMNmcV#&K$8xR~1^1|2n=PPc8^X-h@UjO*#^_nrF&K&>`u z+627(?!D)pd*1h)?|kPwzmL9?w4d=kq;vesXsf^%%0_BANzfVA4c_7Gt0taXE8Qy( zdcS|2ltN2|3tLD(hNg?k(squ7a?CK(*pdjXYe{lGTJA_%vETM`NYUQ7O%FdL@*N^1 ztpEx#@H^Npgf#UH$#@lg7@_5ILtDm%5($fOo*MI?A{?nPqxog!p5*QU@Z#+IPrvu{ zyU%PqBe zqn22S9|xeR?zw727nr@xrQ7}6El1)lM}(GPv1M3rjfk!hqyo?(qY=wn$FbIuuY@Xb zaVQ@3N8>r`MoA)JT$radji}zQ`jSC2fzui@Ea)1#MYcj(t+!96UrLv4OW5^pVY4>s zFN_;ey|wNX@vGgm{_XQwG;C{%NNi;WDpq@}$Cxgt90Ag(F7k)Xu(4*y2jmZA^GfZU z5kF1A*snslfL$W~cYnDry{K^|YpGIw9bJx=_g@}PRN=q10C1H$q#)(LG~Jour!vT3 z9-$0^X8MQ`r=o_56v=9HuzLcIOm$yyhRv`cvq$PE6vnfuxnn$A)+8JI7+6uDNaAzZ zz8H;BV2VL?cuktTGWPX*)FH6Jjd}&fA|-QZqtNtxkoS=jb%-Qkp`n2>&5GRgalD#z zkX|F;DX=Az^$f{;j2^Ou_G`w$FhK7RYDt-6mI*V}~3VX<;})se`Dx^-UeQ{0ZDMs$#E3P*3u(ff<` z-iSkVwvaHRc3;9-bR&D6+sOV_4rC#<7z{z6$%`IByI(znd22z@+mqjzT<;+}4~t^^ z$lWuswkg5>q-cLKW`7cq5xh_P=2vfD6Knco`E=kdQZCuI*?GHP1iH|SSlPFF67e>* zubvd`SXDq4JnN5dd`Yx7ZQI-9_V&%!RAYWD&a~%m2=*hQ{YcDyWT$O#bxeD{$qDv- z3_;QxJsEdg(v{_coHbk>msru9&4-yzk%U~k&-`qTJGhS78hb!=GkquBxL`{W^C zr*lF zLRs$hu?^=sbHk)1JS!nsw|jju%R5c`Y_alzj}{uq&=m9q@}*v3i#~Z15%$T`Tqwyl z;K`bW02Y~hRa!6qN95}OkpV=_CdJB(No_Y+W8vp7V>2!@>djl=J9X+rIA+VWh7Vog ziX~ga)D?V_zH{oaz*1nL%_-&sONq;E!WSdSPPKJ7O96OYM;(^W3;K3y>&4oRI~K8) zKDOFE;DAQ#0A>Z+<#yF*ylNCy7rs>=4T_D}Fd#M#3cexHHw1C3hwRIEiX%3}1`}|w z8Dqh+;O0vrfJL1LC005*CYA&?>%@}Qn7#G$d(O(6$77@>X2~TMS|+e!yldvL2VkA- zvg0gK?5~453+Z+#E|UBGtSsWfLBKSTy)=Xai78tryg6Ju;xv6cR1Erwvu$K3i>FT8 zu;@ac3i~uCaq*k5p|r}KhXywA>UAG!X6D5Bfu<^PK}@pO#D5>6B6Cd)(%NC1`oAT^ z5`MQJ%mLooDGLE$o{5qU-5jQ0^&N!39Aw>`>yi}pD7B3Kj4dNH{lc|rowBP=IH1B@ z|B%`Y=@Wg9Mq{$j=3IsBI7=mL-RPmXqdn$m-?gGY-(i=ylOzUaY3RF&5TN43Rs$)~ zlGx&TDT)6P50@JrDT#kX$r+N9V^&h4OB0zIY~FTv#N8c&yHj*`?popNJ|!CSGM0Q< zS=O*LO#Q^y@c-cF=$C)9L|M?e04M49DAmnDaI*sKffX~%c)%tajAj596e~~!nyU8D znWy8a4JVTI+_NhLqneX>iiVXq6r;9ErC%}2JPAsj(uW-SJ|2cd4B-J`Y_FJ8dQpAM zD>fLqw=7hot6)0xXm7ckh%wJQoRrLx$(RHT$NIJgvJBEcM)iyH~sf;Nrk4d&{u zb?%{dLuk6PH|9|dw>+GqkY<#ny( zk=cy5O2TpI{CNJ&onSjNDAG0*{MrW;F zqw3}>B~Nq?7aCK-nN~|M%-H{dO`nfo!LQP;jJ?Q;BkVw1`|TBH*r_i8v=^toCH#M@ z`=W4BhPrRmN-1OA7d=wx7NwSMxCkw#$k<}m-d_8+#?TDqR2(kW{OenrEIpWpT2SV? z)x8JK6RlMX2ltL}9_)gp^rPTm)z+Lomkv5FV(7yN-(cvqi-N_`QmwqStJJx8COc#> zATtv&uf2#q+p2GKOT>)GKVvDPHRY-8osDkL6y(R0i;QR@;WA3|4e6!pv>t0A$fIy-lL_GN+#Q6ZGVQv7^`X(ZfZMaab zn5|R;|3s2Jnt?rN1(CVfqEz*GV;;cC7HgdB7~Ye0;FDPZK+>;k@r;LUF))b0a$1_7 zxir5#mx*ir_rxZ85hRwhYR07F&e@yc%~7FtzgW9pb!1Fx(qzaBeP=8$6oAT;V>#|E z%qz8Kg7mA)acALE=EIZR1%}F;feZgta_|M^fNJt{WTAOdI_^BaS-LrM+od|N<)&)6B++1Tph1y6q#vV0AdWAZ_Lwr>g)6$=6`RXqpzLrmtX8if7AD z6ZB3U5hlcA^LQFvnZzz>xv)6Dz_-vnQ;{LwK$`Gt(mtBiNK4>s8MKs5ev*!*%W_>z zv!YJsk^?J~WC5udQ?(F)ZYb$8lmQfj<iZNW9U9{D1+Zy7w2Eo=O+L~gvrbN#HNFhOT6Yfgjll$OUn{Zd- z5_?v26CN)txo>-VmY#k74M#LJj z<&tu2yN<=>O96H%s02vmHIdwe(;cx%e~?*xzMG5ZIRBN$R8$%{ zEfC7MFFF%vp(NZ5(HYElH;Y6!?Bt4W;C7gbn#qWbMRe~IN?QQvz4_I6>Hb*h{+&Rt z7#N5Ytj~x}Z?uSZOAQOo#vM0M8V(fr?h}bv?p4&Rf0d*;-wfOe2oKDOMW7q6Ks@Ba#f>+l^{B4j8Hfxds+xe; z0c$U=%JsobZsUmHY7t#6@KIg2UELY4?!4pQvIx~fV)f8Fc@aw_xKq=%UDFw_>HI<4 zUCZ5|&~;MmIw{ng60r?1KjHF0xKmVq&)3F4;J(1*09hvBvc$0D-Q3P z{6#1i5Mi&q4d}2r+?IN zm-}h=-KCHFf6^}uoE8U8!%=9S6q_g43wB!j0eMjY?I)1+Q;GVHJKU`!>totQplv%a z6b}q-1@Ddtf#YJ}_`4_8$D;n7uHo&j@p#ubfYV{WW=!z*i{5@T%5Jia)m;W#4-vus7Bj+CP3dno`LR}TYmg=12EdPvq0N(G>tLMW_a{7o zZO{I=XMdu;<TOS<~YCFZ+&O5{L+TK`g z@4d!D5Ct}z;SxQ4KRo`u<6D=7o>OAaDM$g~h(-zu`CpR{^1mi(B6Yt1et(oh9qvvN z?$YY%du5gXs;XNk>k-RP@L2^|&j5*ViIURw<1o#GBjFE3PA5t$BIC$&DeX#dVqp}9 z0NBpe``Cd^AG{N2N0!`bz;cstvhQBgzRmt`zJBX<5=i#Z=YnEV1(8h0Gbalu{IC&= zz@SS&W)2RqD|9L)%>Y*_!Y2Ll$hCJ4-#Cn#DWVdF6Hsu}8|IRtWdMa3PXp6vN!aXf z7k;BKvP81h+PhP$g@WybXgd+Jo!HSH1vY!cmP4Of=;>+Eb~|-;?A~H+IjPu}Bxr)&=khFz5RWM5oZ8!cO zyr3rdZ+!_}2(qc%@`6@>CMv?B&NhDd`8Km1J>sB|(j(z*g z2WJF-ujua;oCiebfk)UPi$#e)M6lZK&}0r47^t2Zx24E-6Uc#qb^ifgS}w_u_@k6k zS~-UDo8M#&m zYI@mYsMr)n`Z(2aCqk0d zvBZ4pM00zv@FQ*41lZS9^pa50jm=##dpGHuOsy^hlth}={4rkT7wD5%B*GNdIo81h z%2V~$dGZ0#y{w9!O;?OFrwWyjIH`IiBu-MLkd)Wi@;zhO*^(WtqVbGxCq9*@w#!pK zQ#I2`)0L^a9w3f2fDY-p`nPM&ll9S0aFg6_zS9acIFKDz)%s~D%@E{OC;D4pHs;Wk z4QAw`S<$mm+s5JDTykL`j}O87V?o*psH%XxQ{XznP%LGHxMC|-z(7=dIC6lpxC{?R zcN#hz-RZ#L=$78qk^Lr59VHRf2(nX91kA{lSg~I$XrNqGBj`fHkyPA}ziLEKRw2EF zzzeB7q}N#(67l;9Da=SPSoaR>W|dF^KoX@cb^{C)cHY7MZL9K-`H;vyt2OV=DEa_v z9$3_BaqtYgP9=rIW{NV6PFQkCS05w_oHU%au;8dT>8^@x*2*ZN!D%zZPIs<-4sG`QAl97D8+KShyW9epFrN$&Rv&cWz7W100Qe%9Fek2ya9xD!Vt|5` z%$3fS88pxdB+PfzS|STIBL3O52Tjiz4ZkJi%Y*bCN}rNtkIEAc%2>h7Ble;PQ`+pBkSU2Q2^d<4+$yJ9U<>rp`P$ z`WRh2IeF^%pI(GvWqc5_}5q!XDyj zN-{|x`;gNhjq`ZX`><3@@z;i5oSA=E=%*oU3qB zu(M4Zh-OlXi56w~^Yb#x!jc~_CkvJB#M2OG&0YlhwiF~UqQ8{DybY5J5=k@0&4&xp z#)n8;?O7Rq9Qp+5r|I{a`9G(T{ojBn%qsnp;k#(ru`FDPAM~hL$LxHs`7a zh?#xoU_UXjRWWu*9HtsIJW@ixhW`f(An7^=IuNQ_tQo+M^ds%q^q+B#qhE#Rm==i! z?H5*+nk`bMUqEOQrZ{Dv|0CS$kj&T<6@Ea?wkC1EP8laAS!Uhy9czPPKK6QXxvh!f z@*Az&#esNnKqzhzi(6v$3`e4dar;$Z`Bw8EQceSiL@B2zuG4>emx8Rw&ELgKX<7Uj zj_FyPo}NL=odbs3*O5j36MA!s$d8Hqgvd`p466HTozh~GlvdW{a3}rLCI@r$thoOK z?nb>${!=(DSEM(znYmZzm!_xRq5?04AGyHg(tB7lW8VYmFVRFMigWtUSagq~;Gz`i zKSN+?Mf%U-m@yADd`?fVQHlPXUZfH=EVxh+vh-3GrNtxd`&An+|L-!iRRZ0Yt1MI8 z@}sw@{2T}zUut^Gv*3a9duUSBnv{}~UXMv&07^BsoT1l{p8P{f3n?>bY1ykDsZ3b8 z(0XhNc%Mn@ER4%)avh;hW1Dg_ec+T#vO@qoz6{Bfp8PH)lUBh9m9KeZW0IyZIQRhw&*X$CH3yCWy?lk&pPw;VaBw z*Nm5+c|~D)NDM&JbcNy6S#Oa?T-X)Uu^JRk*!zSo0D7)QA-{7Gwjt;()tz2z^XjaE zhX%X@B;Xl%e)7!N`1Hi7;bUiE`jOX-;&P>s6hLEQC?GHSJB3mIS#8MIdw!0dk72Xo zv%?Fp;kJjTl(aoDM+=M0JdamOK3hg)R%2k~Oe!U5%~D>W)LUACQax*8)a~)_Q;Xw3 z6e)+=N{mvDC*WndHnr`g0F=;@Rp=Cgg`mTOUHRYuwr#$+&3DgUb#pXofwcy~(<6F% zV)hA`wY5)3$JWcz8Dj5T0wz!}2_RW6l}E*?WFbE@4^*JVg=xmi0Wj;*rNvjU7^pIN zA%j{uwd=3p|3NmoGG*x0T4)HWiD$88Subt{t3ll!`)ONSjI9-lAOC_Wj%z;EZj&cw zMRm`t5@sB0z^rhuWdR){>+4WvhLWQx^G-2+xO#?&#B10Ei4^?4nhJfGvrtAc4#KG_ zE2wBN&Wyrj*9O&3&EnN$T$eU3=Y z=1m}f2BB2?x@GN8q_Ymz#QG*zpOR-qwK8Ct$wT$1AJh1&bF){O^}CFH%5l|nCFU}c zd{Bm}VP=S~%+1c9pNF&(<__iVVOG+Nms%*ACf=Jy$1w*}M`o%nGHMUze!=;d=Yv=AHD05MAeqjhu1WV@sxecly-IRa*GI5y ziw;`Z4M-;WNSZ6_Sp;FLmq~7=no$F#h@hqc<5AGkfVBAvl8kBUXDIzd-VQ2GaSOO~dvtM@it zYf+pbPqdkd|Cb=4Y&@luDyT3ya@gsEy!_z1)WLoouga?$e)N!{1FL%k=vYF4j+Tnt z1}yBY_iPM`RbxWgxL7t$Mz67i211K_t{a153HCU0MLpQuw9&d<*%`0w6e_#L%I;Wc zhGW;_D5`m(#4J`LUx4b3M)SGC5F%6Ti?m_Yg!B%|O(mYyGoSDH z{BnBzF@Wo^BXkfI_*=u-qX$hNmo|@Nn?D{js92l}+r~C~N?AP)DyR)VMTyF<=LC>Jr|H6>9d`VJpU^zgWqE`ZiJ| z{W5cJfZa_|-d(YUZF~z34zY3D(Ind_#`ej?U(9vC3m3<&{v!Wc7@a-H_{IX z<+e2VU#P~1+y(_li~b!bFj{Y>pu4@v>7ggWxyI2tn0=9ri@eJaDwUI(l61vOC`IP# z6$?qxQv=HiXJa3^J)HNV={)QS=%0}4wb4Zz-hw(y7EyIPRZ4@-;T&VyIn&yI(kr8C z8(#srf_S2es9Yb2$vE1kwie@p?@GQwK|S9Xe}v;_!WMpkwXKUQIR@4AoC`E(V811= ze1X%FPj~ItuFq!~7pwUZ28+gBpotax>1zb@1YJ8$gF(yD>=>+_#s-UKB@B}Z+)NQ| z0toB;FbFjJ>vqBhU%^@971k~RU*I~+-wOM7)I6;e7;;;nk0T`~)4{xGnU(_WO0Vp@ z)ULVfb7~CBSpF-8!F>2tRda*cG(*ETU=J697K957Z8)2h+|P4**I;(g^cy-zPkKLG zph38V3*O|`UPnvPnyHpde7Vs|-K~0QY+>4Wk&=3-+W-16)a!Na9(`0F+7We{@(=k_ z%iQ=r_)1lo_kya(3$By;AKj)1C8SiyUe3f6viq^ngIQLoqeR2PBk{ z^>!PKyU+Ma!(@Tey4od``A*##@!fj1Q>{_a@6F~E$%TOVFRM($Jl6$cQWW;A46rzVu@q9n8Z|<@n|EIF9x`lS=FTF z5o$rvH~HUG3FnYYnKR3*Zvu?GW8410xPNeK>Tcaf=LG+_=pPrH6QXnC5p+-Z7*#@^ zjF0K9_kLmaHZOYu#BeJ@5wN{iL*RDVWMIH+s16#pStF-UOK#-3#zqch?mVTja#Cac zztBYY;qwYnZvq`|N2_!Ioddvr>Md(|fm;4c@Fk&(bW`>86Y&yZf(fR<%+al;h|KDe z;k4hxyU8pxPw4|=pBfFyJasud^}&)dH2d=Y6rm)uFgM`o+ezB4EQX*-zqlYl@BAfu zjUv*x`w83v?|||2B0c|%o~ztFa84G3i+mqB{u6q9ny%Ql^c{*Jn^j3j;{RFNis1oC z2))QuikS5UnhY3zlDhC;!e<5#Jsau%Fl`A=VH!tiIUnVcjL(F7*<-=u0^dfKs2;LebE7!!U*1& z7o1)IG)Me5fMg5U1k6pg?TvAJV>Be#TSR5`<`=G-8?S46Sv#J(_fNfd>fOnW$#hLD zHz{Ei?@d;-f!1$#tiJr#p|wNzP4&4oY^!;0LCX%zd75&HFiiuAjNWtAMeA?v`*7t) z7yhg{)_zuSO^L24Y)UU{0RUu0OQK_Z^JS>|ChGjR+$iq-HHo(Ux1V8GDD(ZKK)G*k zvOc!-aw6!w0@$}hqH~Kd zlLLuJO)4@$X>a^6Ah>$SQmZMatRdlR_;&LL%^!Au`07^4M{c2IL~I!me507^4o zxavcjCAU3WoDhIkFzy)HI;UMH+PZH)3++<*5p=yPJZRRp;Z2#ZcUNzyH1d=u_JbgYkwz0aiEZ7!|6fb?ZaZrshEq7gu7(AUd6MpN@{8n5`FzE!j zWLV#&ISb7UA6y4{6j^;Ld`#vc)yUC-OLMMdrGOT5kl|;M4F9*mSFIJPYf+FTlawUs zng%fY66-&wFV0<)Hq>MHjkW_tfpVcfkEfgg`iZb#$hUD3Fj+OtbQ09XZ%H>n+8eT* zJ}B?)xs`^UCs0=4jIvD-c6hcchT;`aA{Qz~#fs7GiWBjQ6GFu)vEme3SMC8uR*xs_ zUYhHBVfNMDyV(z-KY*YnOQn-JBwE6HzM+<=hG?XHKzx(2mNZsp1^DI!68(rZauzaL z3RnICQB22jDz4z}u@&*rm?KDTvocGl!`2s5Bm{fNq*LU?XctomQ6IkekOV{2gjVt#p+`O(_owK(a}A470B;%`F6V zEl)Nq2m4bn`HpvBqYy1GgeD8IY0^R`wq+-2WiII;Wrao+8r3j|suEy)-b2lfxCGYh zAaH9HiyK#ScFNtW`LN&nk5B*3>37cDfI^-*7e+}zR>$ta)bX+RC*Pag?773;J}7v) zMNhX-f>pd83|V&9w%r%E`>;`?Sg^N>_SS8Ccii5M?GE;S(T)a6$4;4dyR0c*)+Ce# z#4_s0bD<9jvO2Cd=<=9-|7HV-{?HmU4M^ogv3xBl0+rEA*Hr zLL9HoGW*AL`zaA>1`;?jEr;{}fjs{O5w;lnpXn+<rmCiDV1cy)OCVH!qLiDRf|~Gx|>BVeTUeY8J{&8!)CUz zn@z_!py_3`lYS@&gs$u+ab%R8$=2`eTE(ta@xXjZ|0K&T(H$@eR(4Cv zda+U%pK099VGcG^MfEN){ZKG@*nT0uMT)&F2Eh4Ik)_dR%-P5WnIon%Vxu$54$k0> z48&PLerwiW+02X8c8RX;-7L5;-#G7@_8?NrVvUOCUi=wqi`4FBai{*2UhF{^ob*bo zbFg*`pkW5W45d|ofEo!PG0V(lW;Y@EoZHcnem z!^Y_@U|w-bCFrt_$~fysX?Gaz_M%dor-%bDNP?1Ir-F~8{2C@B5R)3d0Cf_HGQn!huVpE1o~2lr?$H-g_@w=% zxl32bM-llbCPH$IWU1tBCUk9Kc7Cy4){ZQtNA8qIsuHOL=wD7@xQLK|m2kN!B}zar zi+hnLc}23s_<*hH@&r;q8-(eV7oeEAc>X+3A{E*tOm1>INNg#YMyl1lATJX0UV2(b zggz9$o`|1F1Cd4|O+=bOl#-GqZ6Ti8A-|8F;L(EI{CK!_*k ziKJ6(y)$-LYy*a*#r za~jx_`BKbRm*$a{qx8-&kr5)JM8=4)Z(*FS9wWlIiwU~=HWAhh7gOWQp^euwvvWx+ zbU@~Kz(~qlu-G?aWC^~o4PIUhUcEGTm~TLbh}TV_CbU(|A2}{zD!k7A5~kvqawJRz z*V&)$!f~Db?V1ZXGe(QQ6Qst(^~FpF(+~6xl)ztwLGrg}X71L%8qh)4#pSgdge>!G; z*1};!bY^;=xqqgA8n#`|;=o5{rjg6BhW^;0sr&5tXL?`H=a`&e49G;UA4?RL zy}kI2#r4@}w@}z57B+1cw#5tEgu)K7umg{C3S-5-c#bcY<4f3_JC^+G$5zj*pNlmP m;@CPTG>(gng2!ihyNQw_oeCYk4o)jMvWr>nSO15chAcz-~D3PFY0a_MA zI*Q{qbXJqlUTwvACu#fj^77!^bI<#pbN^E;D55L9<+oXNO zZlF9&6OPIJk$mPiPdF!CBQEB*OcYGIN8FR15zl1dNa3V+#5-9uQZ(rs@l6(w6i=3n zluVY6lunk7luee8l(RI}iHga}k;=)ck*dk+k?P5sks1RRwqB`~8^h;awUA$+TG%GI zN&iTlfs0VxY!h|T6a4mx`pJfo29~E|V$)>fNF(#-Pc%(7k2FuVjI^+4=R{z#b)=Q~ zT@#xp+eX?Z+eg~jbHPN%Wamid3Fy_Tpm6g z?hYRsGnLE1oazfd#aHY{czCa13LhFd5iy1jkDOp7RidP-aC1ifC)vAdysOE2H;A%M zh6l%tYW^dqSo~VV_kYibn&Mx&MozOgb$C-BKAlm@)9hUX-fap$o$>Ard)J6}O&K{3 zu{X_l(~_0rFdrB>%eRJo;d5&3#*F;tSIr~O7`d=3{A~C+{5^xeXYuz8-*(sbJp*ct z|8$KzUvL6*}VbW0T?7EOA(GeZNX1`*xcBZT>IBsLzJK*ATt`LK|xKN}4Tk_L!jzEOqz`;Xn2KB)oSwWG7EX;zt2}RLVdFs&}-G?Fn!r7^@;bRy<(HG8yC&To$!qL%iWHkIj$BW^} zi!YoQzxYCQJQi-hhDf1H;phvjS2{z~MdMSQqsr&(xOPL>iQJiU1fD3ZGB=gKq`P?j z#n)cC_0r8_^v7z#;-*}^;js{Agw%<-yQu_usolg|coWtP6K_V>SW~6xK}FN`BI>Ek z1BY6@l(##*0H`ByRQ?LcoTG0?bMBE9&K-d5A?{tnps){5?;2C)Xn0~wIE)AOVf}uA z);RhMqbM{Oobhi^hYmT$)08$3&P^_9%bz!~4j6pb$TAhW@#0;xunRxJZgTdJ(@zf7 zKrt;sH}DJ?bVkfc3_bQ|30rt8pT}FmR^G-!?U=)P`Z+Ac4cqYR;PdYm^Ukn6 z>ADuve2uNjRS` z4ZHZVjIzozo+~n*D>I&}@LZ(Hw;Inr&2tUPwP~Jf@xEB|?8kGy`aIUk*S%^TDdFp1 zeQi)q$wTv|KTTx;YzYT6Pza4H1 zzatz7x2mm9$KHwbo9!Hb4DapXR*VZ>EG^Q??@pIt<@cbBHhyoo9jH$`%gM^`Lrxw1 zew5W|=aAz7zY7cHfxAZjAkrN|pKHg{VT5%ftU#^Nn2kU3YTn2eRPoUL&)TTX@|1V{X%Q* zyBr+793H(I9FG8Xd=Us@VI=%gEU0~#DwqgGV?iLL<1dDTA)u9jyi4{R|Q6bK{^_J3xXj*YeNNm+q4A$**`H!8$HQyhpr^53G0Ylfxu6nb)`cep zQJF2k6XnXTSvQ`Ld-}FL86$S&Q)OtaZsLhiiXh73!0|g$CrdL7FNx%@w!of8x}B zIR(dEamoJd)M!_s{C2hwU&V@66h`Y~jdCc*#hO*We$nTRdMXsT`Q*5f^4MnCk2)wl zHe0B#g*MGBcST9RRH~*{eX~}5YH)Mvp0KW_jq5t=L@mnXQh56I%1UnJW{YO?W^J=} zJynf3%2%EB;;B+e&*4e=dOST<%kO6M@l>NcaZ3uXN)DsnSx06oFHtUjISx@5v~wkq&IT^lug2KK2@V4nBb+dO&6PaIMXF-Q(eN1pI3C9NQ2tSFyjK z#g9RvU;KZ##;;*o%v8!y&_6jHWsL|$`~+Mt0jLl_VtkUBnyhGHG%qapxA~_8|MozO zP)~6gM96?AY#C?Zj37$}OiS5@`UZyw2K!E=tY8;~BfLP%1t26tB?Owesk}5<%mAQ3 zlS`mE#o$HCJUVp^JS9FHzQ%l|)7SV=EF6qZU%NIX#KL?UI!a*Yc}jPl90q4DkS|2e z7@U+N3hYG!nZhWA@)T-9cSyV+#wQVIKBgS!LKD*x8%3b$!ysayRG{heUkos&4A-L6 zL;l>CLQIcG#({*)RA$raAp4}3bI2z8G63RDZhaf)DqiQT_JTzl`-wO0jW_kJc`MhA zrozpim@GvFzvSSoa~4;@x|1s^o;TmhOI9|`n?+k$vdoW1m-5)Ki-P@faQbac8--RT z^XuaIfn?+MxU)Xlw4cHnlKw69Tb;}=f9u(Jek1N=b?y9MGQV=2GuihfofWIjx)o>L zJ8cPPr|9gAJ3G~|rnfs1&aI+zYuve24Q&?dcO{&=Md$9gb9YiH+_TQv?VSsQ>?c`N zw$7Pd+t#Y<-`V?n``+Gn-;k)@CRT4-FyD48IR4hk)zsfTzq~V1y;ZE?v*!Ui`rG6Y-y$6nq=vw zg}J3?m%kD}d^%D3v{?Ey`pucF-$8F{le_n^$MjF#Rw<3m`7QT1+>6eHtx>c!#%+zs z!P8RwntJ-hH?rFs*E~fF$6j~ccFlLscYnI(M#BvDM%7vKY@#>w-D~c03hg#%-8FAr zy#7$adsy@yjyn&pn<&DkpMJV-B)KgeY$RW!q{==CgqOOlJk>*yMHhDlRbuGPVOgr3y(IMe(Es7|5Il<`5R5} zf8^YBY>P?343SF34CnCxo`_+ILbER3_$naa5-o;VmmVkS%^;WcaAywqFP-^jTnZHsI3zJW|li&@B;FhGt3!TTHu+#!@XrX$K5d) zxLa*|56wP(KX@VOh?YyE`+ZM!C=RJ zkSw8z=)n#pejM3Ex4@D3KJn^fxZfRKe)_&)sc`Yi;+3VR$(6#jE@Sn4X4wCk;UIYN z<||X&Z_X~2 zh7>Ec2_6tQ+!g#v7tc)_rfdjN1}}vSajaJ8*9(XyfwR})(^M_x9FNMBY?z;^%~3~f zgjGsSNGK}lF1j_lv?K0rj=Ou8d+(ii&m3>-joW&qiYwzEk*U(G;xEB-htpDHYK3Pr z=rW9VP*mzXdeIIJ4P>Se$i5t&&(!>IoY0uGr8%O^u6c{DE;3l``@`}f3REJeBi<5 z#O9;o=A#McG0}M}F5du{3@R29P?Q`bo$sCRB~VxhNEjvB{FSyX+Ovf*y^9 zAWkBJLCfNihz<#N_7e-LOUWRMJH^Nt5G>=DB2oW%jCh4adq~-V1QFO{dhA2ir{vUy zD4|JRxn2HYBo)G6nkMm{oCo7NDair`#{Pkflp))~MRbZh5QsUX9SFjg5inDo<9n+Z z`u|30h~~xDb#i5!7H01ci#wl+m!3$Jo)Ak<5cV{Wzw8y(ibP+-|D$1ip|7Vw@N1ec zBNz$b+Bt+NUt~$U)FH8S&2wW0AQU$CYkJkDXAFD|NXVB7h@1XCrb*;AOdcvbeO)oj zK9I;p1NRCSbI2iJb0{%&X%uGDm@!RQD-0blz0CS4`-&mvQFBE6<~c*GNDX<7Thf%M zhChBGc*VdQ<_s?zt{b$>E9720XVm7Nxk%3%UqQdl8DBPDR|tOA#|on>T8SDdEGD%+ zTm~YR(XRtBrB~2z1#&ukJtb#-zX(*0@=lIVzprunnA(yez9&tEZymt5R+uwvp{z0> z_a)8uP|N)uyx&(IwPn(%kQY|o@+yr;g~^tQp1!7G!0F?i-#KT(>XRV@pED!OoY~?z z3)qiUT1MCvWyH){^t~h4W-a>K-rB`bRqM>o9tmhh<#pu@iT%^U2mkn(pI9cL3F4LC zfY5?zFNFEQQKc8)p&3VIKWc;XKN#*%|G}4i>HAN{hYY|a(>V(YK6F#UlWqGaLX#Ky z(7~Cu9E(gkl?F>r$NnYCj?#qt^d`4x{*LQS*SFnw-8Ut1rw(__uDf9=yW$ARS@(CL zi-GP+*8^$_7RKV2Fiy(aFSSGXefWQcCeRo{6Yj_Ub2kQ-!9eCT^y3KwLYZa*#y{*D181hv4kQM3|SDKQB^z;<-qCs=QM}Qg|JUEb*Fx zli_F-(zukp@1@Z&W6?>H6bHmx>H4RN=<^CtJc8~CNx(>VN1)0J)Oiy2lm|F}jdV@& z$D^U^q45~0<^-$~?rI39OyQSCg?A}BVNxk`EEK&OwZeOWp$!uMCof&%OvT0{{r^Oo z=y?pRPbKQ_VZK|;uOjrPDCzXh_pclC?OTX=YF+iVt$5p#p60l62ad(%`xBFqctdd3 zIU{&OpYMDMwu+}zbTj6Jmr9hJq_c3%Q*yiDojlPG>SHIpIixyk-kNyrfrR&<=p~lR zn!AMFb*T<`7)zU0>vyiy@4O#M)bA1N_awY~Mep9Yb1x7$nJ2P^Qb-P^Xh?XQL~qk_ z4_HbRi}1ZI^lNq6y~(0dv8Z*O%X95~SWW!&HNwZj@=?SGvm^Hr?r~XKV>4ORv{2w%Xj_fvlu-gLv zhg|pO-Zt*XZB2b%J%@*ov9IBOW6c+3olleG-$m@)jD+;8D5W(cAFw5@Mu`XgnEEt4(+~ypM+=0%W|>}z1=P|rDF@!2{zh)CXrK4!zvC;0$nR^vGR;Tf&HuJ%UH@4|L7{GiEzcYU#9?4u zhKiX31CVS(8xfq&3~ptcKcw!a2s2(Mbj?9a`9pr_2ZSy{|AJVNt!Qh?uuTx?H;D9OwPCdBLyjhmf=rC3VDpA&OKG z6n#jU8&5qoQza*oH-wP(guE#vW$igJ0Bwj=-caB0VE4(snQ}&3g7%JqO1$KkG&KE8 zFO%X74ECRzv7Hz=(#~S%kq;YDQr4lq6Ma3yI!unB{C505BBqp#$(^@Bh-vso=2=5p z&}b(y3S;2wh;*pwLj{GhNXr=o60y!~$$?s`6t0GQBFiMN0n>~&BWYU3Sa>pCcye*a zM`rviY=V<${2!ZyJP@-e;BnC~nsLC3}TBRfxi=#Xm zf^5eFqw(brLVb~wVXl6V2I~ED7|05#bIZAEt6j0xE}2zzg2Lk4RrA(|zOs2c;{r55 z%fr5B*?iB%JP&+-TFpEUJwDOX0-CRI*sxZ#^FIH>$@hkTd_GY$Bo+;=TR2z6x{WJu zS}ohTQnoWuwp%RQJwE^q0%!3jT#J3%qVI0?^5uB>u0;7Rh+7sn-EI5Jmc0pgm*@r+ zZ+3MgJ-$2cH{5^e- zexjllTm=&Rdly5^DFLcard^hl0dxmSfXS=EE$M<1|a?PY{!5q z@ZLJV)Dm~K;{FW|8?d%ky$vh!z({!aiQav2XO8;`hQoRR2SKi+tkh#rvp%*w{=g^h z9Y}bOi{9gLXO4T#T}fQ49V_)a67{>FvlOq&yc6!-qI>s)9V_lbarYsnf76{PIU<%E ziF=OF{PNs7KuoRSjFKzZ?DP(a-l4cN$DJgWANW27`?-vi1y~7FbS zG&u9!5Z$_p!B$!=X;~?0NtCpTC9QE!?i=IRkBX4`n(SbmSTKW+=PG7=JnA3R)oAbf z)%to*qGYdFvN!J8yKX@yET<&<6j4H5f6`fT)WQAK(QP|cZ2HJ&fcx{Zic{N-Ki}>+ z%~^ha$N)EGjZ6_YSI6QZ7RA@_|ELLYRszt_#>J8?UqHN+Cp}8EgZmnoDypCnF&R-$ zDRb*j=t*(Lpix*ZQ6DzBAU|l(BNugF_17T0Q_GM9q$r6HBX&IrlZ99u(OO+9g`ptl zL%;g^=@Isb2PmpWj0V9YLs3=2lLw)oYTUCYrIwMR2DEPD_cEIMq<`2gq6S1dvBs3|3>~lxO&8wqiczj36a?ye6)90v z+U7$te66f)aHfGII=mmE24Ij=z=42CD*H?Qp)shq_yf+Ai)q=)+i!$(s4qjaQZAqn zsxV5Dn1t{aTfLDTwg}N!hKd*byzm1`c7YrcpD-bb%%A*U5uigN=_}{NS=7>I&=t`- zj6(@$SvMEi%hpOaEe(r}hZCjUVrlm}SKtB~^0`hLUua$Nv?e@lqNgqHX-k$?ilq#P zsZ9DR*7J0kd_sBt^7Av!EZgQNYyr#v_K8(r(~7St;cF3nEpcB9R=lcutV_jvlh7lb zSgqN$QnM>jvq!Ai6EDkgLq<_rgZPD{i;{Mb?*b{I6qZYi*`}6--rFaV4bAkka02oQ zP8SsSHEZwn>fcBUzi^*WWgna9)4#1@QXn9kCOec>Wd~xOq-W?pFYbCe?is?Z3YZ=i zm0|^Um93i)83ja%E&FOkPYd_E^*zO=_qjrN-}iMLaT`A#Ffy#{LnkZ)SC6jhWO`AmNpjTn){!J}T+;kb$=-Y&Ok0o4x;nZ6(Z` z@nbJM?>{{-c(lzAB~qf6PoEk*3Uwps_KXVMx( zk^B-3>}LdVz%0a(L?Vw8{;$@k4B7eJ>zy1D;EBOcF`3IOb z^wEU(nCK-HF-$S2c;_FG)QYrUhx}|59E9ibqu_Dyjj=Y2GyeXxP?)6eB%1bLhj9q@ zar|SU@rmf5@D9q67uP?4U%R-%XaRL&kfLs&@u`h)2mSeoh+?HbzcuxZsYF4oSWp|c zZFozafV9e`OobH$$(^7|OoZpP!&^mD^d0gfNDIKEg0fs?KA}^GSXh-hX*`IbOa%B9 zRmKcd2S8h$kn}<1|A293dk<|uW$dQ(5Kr&g(EwGp_b0?YRwqr8!GK-be?mYpKY{X0MWwpcqwgyB(aq6*W~;gax&%#<0s`*;?;7Weut*W%SfIEomS3O zC_0jM+#U>%uSaS~tgh=>-Wo!C>5^n>f>) zgDsXT;_uT3I)*%@50tby6@E-!!qy_%TH>~rBq-jA)dK%Yfj?1DFBa6tZ5!UKtB2X> z7}Wp~jz&4_=MNB?-OtfVfEn!^Ms(@Y&q{zPO}|B|AmyrfVgRK{39?3+gV!)z=JKjrtrFc`0IISyqV{0b4UJL3>fV4hTE75~VA4xg4}Drvx`s zJ5rmMzBGN05pNZ7734p+24ZIJY<#O}o=iJZ)7w<4o?ucXx*$Jbat!UvDX--X_cDkN zeS2ccR#cEJrVPY`d&L;@%RR~D2s4nx|EeW5s5#A=t|(IXj55t>S+)n8S~anFt0H9K z<}7pONX3S4&AK;cZ947NWk^!Z*x&>0N4WO4GPELRP0(}Y=1eb}pds6$)*QVJqjJA$ zAE){5gCnGx59`9++~G!6-#nF0J6kmRqU(A5wfP^l5^TDfT-Vy~Om~ zBo?@&=T;=)j{3E@DaTrzBi70xdx>?~{Lc1-yIFKM6R&D>vZC%g9dC9dDq6*g)`dJN z!p?*{Ai4t-VNukCZM|1 zkqMxLdMhxLdwpO{!jC{7FymVoBW7i~GSY=@+h+ z`t%X?NjycS!3dd%m2~nH$H5hqK0#|qGtY%YM8MWzl)rE6-q+K`eQ;1>(;dzKQLIxiKdq zSM@OM@x&`5BrP+WPh%RUg|46|L(D7Q_@*I-zz$+7h~9mdVklS zbp27+gUCmGV*8M|eF*fPyZIB&=yqT_xg9j1pV-MJkLV*YRO~;&BcWnXvR_M&?f?uc z)^a_V*djLj>5N?h#Sv?*?;9bHn0c<%g*CB4VX{ND7^9Smoiv0Akb3Fpva^7)<&f5lLc5 z(BzUw8Us2GRg+Uc;0)-&oS1&Dvi>CvJmQR|!Hd~KLYDICyH%^@T`T2XiSqqo`TlrO z*6rL+t0{q@b684M_sLd3l(1SJSSb%A$~TMUo9B-+R>tsyEAjea+#hxStY7jevK?B^ zNK^P6ZTF6nxt&*`5c2zu?)|18bUV6to8I4Tfgc+Zic}sg8Es;^u9&vdQPQ6O(lq)R z=7^xR4uy5}x?~nn(whgfo)fSgic@G5z+Fz67;j<#rfC%8SD}*`A-yO>kS^>_c_Lbc z>AzUMI)Sv5JG-Dg2EBUiZmQ@DF$LQPC6a;1AK&`n6lcX;Wt+E;jAyxs{10)>iRs9(&zVbr0z*_d3<{#KLXXH z(W6v(MZn{CVW~8J6((zlFEneSEz3)qktB~eERL3Y8OCn3y$aD!p(bwLtTkKUgFSp2 z(Gki%FlYOajXJKkXFw!LfvHKUj*Vt~evUidZIu2MAkT1rm~J7OAY zRAa6R)&9Ox_1xORdN8HUbp|Qt?6Y0f)b+=l0@3C$_f9HVlX&qXIA*=Wt4a(Y1JhBFxre& zZpNR37GrtJ{rIntXY>WE|7kGkp1lv)o$4mtCD2^M=C6g=LhK~(8MQhfQBGm_b@#w>(lQy_nEl&9Sz-wOz*dQ$$!Xk#Gdzo-30#!P6PQ} zmE>=!@2N6<=%6?sRylf_@;+>$I3ETKMXG;xh7d-^v37+^Q=j09zomFnRYq9 zaDQfyG3ZZYZgdd_5ipNbUI-!e8^p}$Js|EHq!1GDZ1Jo`Tbr>Af@99KV7O)9 zuw^;=fUK6y;5-Im;nBwbaoC-Kj2j$B$rdH_L3DgP*)}8-GO(Q#gO6x|@&^hf(Sc=b zVk#699w97ciP2de!Y`RWdTnAHwiSn-I~nXdd3yLc;lHC`8$AyVcb^fMpnyI0oH@~- zHpe&_y2ea6rW`n0VM@61;&}La%0X#*Pn|e{RLsJYq-LLHmjYwGHXTcu$#8SZr8nPf zLc3B9I6-LqUy5DM)~zRAT~6krmP=WUDH#3V(QMevDlD3}{;iYq)hzN$Tkl?aXF5^T zE*7=NZRvXrAc|kydi&B_(L{cOn9tOncCHnbE&3KicT2xh^JYz=JRp__R?9nA$~zO~ zTgCFNiK1;{(YE`;59%J&Lks)aM9~2;xbN8Nmx8`2WYT)2X;9w$f zSPUHg^OktcQwjG8(G5E~56h~s&3oRpR#dVOyFDwGwqnb7(N?htTfWQf-cQJx?*Xb^ zQN1|y?XtUN^T$7i0m9zb?YHfVCs#ayxF?V-s$O!fpbv`L*NUnaN8jm66m^J29YC9W zgr%3&-Ff+qmx15E)%8wvx$F17^7dC&n-8osA4oJG5}ObGd0E_d9PIZpLeI*)(CD>t zg{5~~Z@3ougr`CDG{ij(Nlyt28BKWVMNfU)Q@>VPyI@{0e_ZOP+|iD;vih~M%EjYk zwqv!dW2LMkQMLt$#abB*R93=WcjXnAd;*m+6a;6%{JMGF$JyQAa(%x)}Q_7ZT~FU@iNYIu*Gx| zr?HG<@sk+?FuV1bg*0Ge>zzQW4_gS?S}GJ_Jh2r{aFdS~Oeh!iQKSkAD29`=rcE!( zOP#c`31sXbWg4C2>6E7F$kmjM{orks&{KtKmjtRV?eZ4QNxti1JVh%Yjyt0ju*N@c zO){sfeBPBzFCY(#u)(0v4y+swtV@))F8ajsR+!r;hYb#o3oqa-Sk@|Q7N@`6b+>E5 z_Rv?ibaKVFHSXJ*EUjH?Un%X3mv*j|)-5&uph7Z=fhDAD3)X`&(v~egm@KOy!#wYd z|3T!tk^AQoP5VXcr71fgmK}(f9Y}6!TsR4HvJ3sF%;Mxq(dKy3<{!*FX#DevMCS>y z^8_BD3w-C~8z+|<72RE^?>@{5OrmPfCVcG+Cl^kx*HP^^aZV7825i%DdcSq@8zEBvG+Ntk|NOrBxP>ca6gDqT_LrR{y((;efG!Ft9V@v>Kd65ag#uaSRdcXhtWd zVo?~#jM3*lKo02_2yNt$N<0Ix(w;Pu&D%}wPmY3_=fyVlK>h1Qz`>xT_otv^}clx*!tZrhctYf5h2n=GqM z);5zruq)|rOg6WG36!jFOE&IU3MLwNiH*A`MO|ZZ?}21vM+aA4w^V%By`Ik=om^dDx%h4Ox{Ey)aFw;| zZszrH<%B;BEKZ4K9qWZG%*z#(tQRq_572hKn0ZSmQ7QA5VYAj^7t{jQ%h_`US6Q=O z$-GsZzj3{qd26_mn#IxE=hti5qhGFJ9eb>o-!`zvP4e4D_SnRE$`&oRzOvrT9$UET z#(3jSv1-?PfCaR2WmStuZ_ll7W{+)L4fe9_5v%vEx3ho_IlJu6lRA<&8ZCQ4^UIEn zv-;=+ChR|i^N9(Mul|-4VCAd@7Yx{b`IkA2o) z!Cs>*H)1TdKwTcrQjGmPFteXbr^9R+Kp$ybr_loS7R9kyEu^-oaXm&$!~K>AJAa5i zg!et3{bV{0?rFnW!@8;2f`t!Gvb1XP>{8Ei+5N_QwejjbV(DJ?GC6RP{XVq2)-7^m zmO^sQ7|a&OvWcqbxF2Od56~h!WjfA03&}z?ZV6Z4j4crBdHc~94i59SxozD=51i~g ztf*PH&;xdzRV+5%u9YL#)UW4LxRWcbU5wq1WTcaFm^HLnN|s>x2|xFJ_rpKLSb#Uv zdBISHXqT5?df*T{d&DLTCj@-t`zZV~B!G8AM_R^c@fyXya>+80NB;ytUk4T`pJ&Ij z^Rn2vSnQmvyB6LSHuLtdC2S5`b>~(&!g+jt*oHHZtaxjs6PZ+gg4VBw;v6mOn1flg zbiG?0@d4%=~>lLsdcx%fha6d=Tm5HCX9I2+5up3S@u&xP~cONJ3IaG&Co zBMn|)-)v@wd`!`B&uNAQJ;_l;DLXS(O_KQWzX8PRm$cb%T%Vc3Qf9LAuN-c36$b%e zU;c~XRGFky5L7~f(s2n537EOkbHMb|7*BVkBMcgcv36tofQ@96TM(Su=DRhl0i$xtPN3$y9k&)!2E; z!}>N%%1Bm_-!-O^##+o5q=vnqXe@3(v`MB zNEyr&sb5(+Q(%%1!sqbzQ+np>Hs$k- z884ZbZm{x+AlWr6QJz^B9qpo8ts2YFlm#mZl3^Hs*9@;gV|NHfx)IXpc8{Js5s($B%bEI2A8E z0i0af<$EBFqb?p;-Xykm#VhtDocl%R{OBZjr z%P1c@iBTO?duVQDY-UIm%O(-AK#&~-iN~az{D{zwoH1UdRudNvtuCv&YhT`RZ!Zi5 z(rw$BJurwM{~G=u{m)1zDVXT^nVQP$iP%gv5G_Hj4glUvGdcHA(Q~S4rfQV{WV`>r z8PyQBE-5QW#%WbXb=6p+d7O1Y*${2i&i7;ZR%gZo2%f~sjvx>03^ z@1XD^@?>mT$*4<-q&0AkLP=pD<(|U9JDNEr?4@~nf!>Gcy&We!!w@M!*#g?Sgwykc z5YCMmn_?&CP>F!7te8~(!0FRxP7R+5qAsa?IKjbFy?rOTpJUJ!Y}!*NfC^hmR0HAf zQ?#$c$;*ls1Dd+E<_jh1XcP%Q6$v?ZK+an z8yG6=1e(%n_Tw%V-LE4m`g>OVJqdrG={R8X0f(M2NTNTC*cstNs zEJRdt%yJ^q&MvNc>$!Ll^z6+p;NXhGILOX7oUa$$E?6i?dWx}m%~e9(QG^z;W<_f- zp5AKjt}?w}<>+q8dp}@+`=P0OTkl@($9tRm{CXiTK}Pz2v4Kh> ziFkuJ9;Qpk1sE9PK&6s|O zH&n$X{AOSJRfkTcQL7%cqA8^FYosP<;h{E`9+D`ACVlC&kN~SWY7I{!U+Y^IY`M&P zObi<<|M7W{x|V%##wTrhkrza1kIYO(hkUd&5DePB9LC{iH~iPaz=&z*%xA_9za-E4 z4|ozjfivR<$s!%IE@c8uVaDiU%2gz)dRIDDM4(P*8d7?lVd90&l=mnrbBEpz>v!p! z{zJq8wrt~I@I)>t!00bmErpX~S}Byy$fLcAj2yc^1lV*Cbqi(dA$2UU4 z;(V8Ude&jel|DR(Y;XsI*!IMT5Sm4YCBENg%9k8MV0#eS?T#NHb` zldP;-ce^d%wkG=+VZxeG5H{I6dpu)ViHQ9K>A9C!dpR*u1>^{`Lo!2cz%p zd~k(&bNhg}`M6mB)Vhme6mTWwnR%q02F6&X1cAk>=`>PBc$R;Y*ZG71?l!!$G7dywXQaT`LJXD{knVC=yDYJnuw=-yeGOEIY$+Zbj@S*n!IqlI z&{gbuU^(K5N)puLl;aMmqIA%)zvXf)b}ib~*$FX1wBy>1*kzDZQ^KXr?VUK>SqKR? zIw{5F*yKcmK52mEI+(%{#nQ^gdro8Ndo#RX#95QG)s@29J+JtdiBJdEmMMtRt_JEH9Yt2PPv&S9`#!YzlFL9J5Wc7?UEMUfu9URhU5&BbC#TQ}iE`TINfM zR6+y>I~ci~KGX5fXhj@CYOIKV>*Lz@Cw;Za;<{u>1G(^5wnNJW5%Er(zQgWRo10XL3(BT5r?r~jDy&<8l8ak z5!U4l$gnT4f*A5XAGLcad%r*3u@rfxA){ku_^;(utWYoSL{jwfT4BlSrMF903p-W{ zI}(Lk#KJA$xsdd;WwoqrrK~Mc)&XhGymfy1HJ8d}(Q#O)TNn;W=$#&iR1qfmj1!|Y zqMoC1lEGLJC~&4&--7hGUPYZB5iJc-Eo~^R#WvKqt(n1uU%N6Rxhg|}Ga2Jlo?CyF zT^lle@SCa4^SNq6fitE0u2JUqzoHMS@0@^)PygDT^FprbP+(T)q}P~#joJudN=35H zU%UMCxyq-&%#o5_+5RmRPo@55ivO)##Z%x+RmRuQL5IJ|{v;i7TL-ICz&bc6JdG>{ z2m1rwoTw;6I~hL8u+W?6NP%IYY()rAo!AUwBbN;r_L*2;u^OMGD1&gK_?I!y(-cU~ z1FGGZ;K2$Y|G{dZ#RggwP65}{3X_=0>Sl5wo@!`WcYA>@a&R6NLm3K^SPKQf@MrB} z^!DU>9zB5ouUxm24<3)v2WmO z>BVL;`bxjNi#KPWqo0q`>e1P3^cLtW?|9V$R2E`4)tCrG4NeHg96Yhb3j{(_uswC7 zQ3u3g3TJSG&ql*b(A5xG3DAGH;dS+ z@KRfI;D}t1<~h57FLFUz38W`%D^-ux;7JN6lRoS;OTq(9DRTs;vZrkFG3#uZnb|Dc zqsEHm?*Se-J~lpz!x>?AkzvW~ymo*8MCcN>Z53!fT?jp&viJ0z83t2yuuots&0nB8 zl4h)ny*b6qP5?-#XmN5gwCU2@m+%;lg@;lLcUgY%Rx*(H|MT8TgDJNaH9?mLM)(|`pI z-)>&IfpfR1Ao(ouQi(w+ALqSwC)G_k^D!GcRp!P)X>Mo~F{2Aw8Llc4)MJ-=;oz(x zNHdLHVC^Y03E>LmfpDuFM`*#5GX8NefFZXOMw>>P0@Mz^g{tQdnE|J+FznzQWwf*0 zmC-KOfPS@U;8#+>*iUBe`n5yTTUf&|Ka2tcm^AXR#nCz%Vq_qGiO35$1sa|L8}ucx zY>pX%o#103C_$2}L0R3{G)U#cg8ul}jo{=I4s=zrO}U{s4$E3ZdW~L&DK0^o0jXm4 zDxHip1c>&DqEdZmBr98MtBV_rv z%^wBO7901>AI0t>Xo0=mLB3jwJO@zZI%in&y-kOu!3P`Pl1=jaz8_Y9Wd4~G$D}1Z zXGPE1xaX{r;yK8a-*!@p=cE+vE1vfI!#_O#(T<<(hZXaL=ULJ7Y~1rKjJ{yJpJ4TZ z*0F-`3=*!BpNZ>`?xnPn$2iEQM1luT*MqEBU zIY}jl(z)oVfGe+7vt;>7PM5<{wJ>!1x3H>M(AgU}5<);t(IEu#q6Htf=#V!k9p-#X*yXcqJ zBw7(39fOmt!vcPZvYKV_OE4s)i)ot}Rep)E9a)2vrqVQw4YM>0S*S{2(+cTVDD0bf znrYa$2NVd@LNl}-v4LMhc!WjXo_s>xkjKD)Ysm2P6-00h7Kv??_A`YLO+O)%^p&Yf zqL+W96++B|Qcn#ck)#V^&IpinyJ27;hyF*?V>(Nt57I{c)q@hyU8+8ac^MYjm%b7& z-2H{sK$KxbO(k&lHT*xSLLI-bB8A2>ot8bPMLktOnt4Jt)FzblirNIi_zWw5FvzXM z!&$tAX^R?4ShkVw$Er24rxFdP#D-Jx>dadfXJ=;m2`lE8Ph8lOSL^XHnUp)TGE$OI3^5j!?XnbTb?nneS^SHUL5d`n0 zFH1O_guUE|+sY&uxUt~(C+XTO;Wzuzk7{gErV*FEAdpoSLjCf_8?Lf9f)8XGiH2ck zQ;o}OEGgohg^72qkBNbk>az0CY>#Gnka*WN$b_{sb-84`G{4g7FkOD(De7seqo4|O zs}!M)B+%8Rz}#c9ND}Ny_A^c(3;hKAL%f>_JZ4qaOL+Iw$67!dkW$tx3GZ5d!TgO| zFDLSA#Qd72x|RHfcz(k}&$;`s#(NI;dx0N!#GgJR9)Tfrdd3aq5}dN@Fcj|6iE&Am zShx#Y?nq{veyD4GyXL+@tlOrBu~^VJk>$9aOoUREM>Z!BKm}uim!q{p-d`(Gw4|$JNcUB9%CV(8af@yG?i1( zuYPK4%`Rd8Jyc^+hDOgX^B7k~^9ggPML!f+Rknp?`Wn=TQ!ds(Y}-8pXqlbIk#w8^1hkBm=A(yKDL%uxX}1k zQ6jHe%!7SJgQa+>@eekCck}PHzuo?$1M&L9xRY+*{PbGBd%^PBzFYg^<`RiSvIz{q zI*Xj8gDjY8_p^9RxhF$fs2i0G;*g-N1L*jf6Tzp?_MLey*nQ^c*^@YoEqJ>7%uwH% zp;4q&F4US`k1paz`H|kAC&25<(HA2}DKp(;$kWiW4c*v@oHAuSC_+ zr+Dkt>Vsi} zBDKvD%au31m0={{6@zTV5lmG%@7Dm&6=sr9s%xv}jlQKgk(NyYq*a(zS!tCwS!vm{ zL0YA^cxxID2_Td}6}z%>RNiFe$R?fEv;}HtqrQv$OjnK_OXeRU#GNjJ%PK>8lU0U; z@K-K~fK9()FM_{iPgQWoV_hi+KX^fxD zHT5$?Cxe5+?;!F_6^jG)nl`8rQf%g>9O0SSd4|HMK>y@)H0F=uR2A?!{g5k=stzgq zjKK)%)OE648if`KEU5WgJ~IShg_|}v2-Kx13oL31H-sLPCv63%juBp`#})E173r7B zr$Pp+l$+En!bMUxS=mO~4m3+S=Yel95gHAr3c6!4Vf^BBEX;6eCR791xI+o0vnqL} zi2|7j)OAu0*1tivsrZ{zkAFeAx!94Y!E`&aMGYxCJM}V%m0Td3+Yv0a(X&8SpgK`e zzqI|^?RVR6_9v@qZuWm%wQ1?x+b<-lwux2SR;%``RP9Mrb%|BbO?1$vTQ~_DctP`5 zlKI7C8@lnWhQ%x2?!4Q%+`UrK9fO=@y2jW3M|ueVFHZ^(%zN>{_d)rUet# zJH_gq&;^-E*ea5beT#f-1+UI6T37OF;(0a6{K8xNkd=L#l-2Xn*_2Qq-}TzyTH~R4 zYusIzUiZl5Z zcPzaKz>b@p&9_!t|IY5^UHA4S8g`2fyH^_yt$;mXdhbl4;h5NPEKxfk)(%LWu;Bc3 z%~$`<@puu5b02$5pZC^*#bYb^o8tMK)&jfc`{PB831`!%56gDJ5J^E<(mDLz$+&Y^ zx*;vn*=MH8-aN^)w?8l!94Rt>P}F#2kL4%EJ^lN*pX@6<>NfqfzyLR83Syr^K^nUP z5_KA=DWMz}r=}zPD8{sMDLmvjf>flB_F@8oGwRVi-h_RZv=`ILTV6HmafcD?#^kX} zlZSp}*rDP8(3Q*&JJshg?C69b*#&Vj?Y7K^>qefQv?#fdcOk^fc4romKIDjx_t5@M z=sTK6uzoT>?anOWD|jDESB(5h`AWV7p=Ep(Uyk2$-U<}6T6h=pG4y>n4)B-!%AOL< zs(B54)8W5xVPFhOhdLzs0v6aPom1RKD_R83c$8%`b@2+FB85{_qFC3uuHEQjNNU%G zm)Tm`p>{l5buLJU9MP&sg*8i=OpH&C$EW}Zk+4GY9S)ZFksJQBJgJTCd{Ju}g{>l3 z*tLHUf?Kqz=ZBhx9lx$Q3a!rk~jC0joQXz#gkBKN- zqa~73OZF-3{t-4_b>w4)0W)SI3tv9_%EU4agkOR%h0-Jw0$}7ALvBnBR#6%_XV^hu z{*V^j(zm4NvGGgO`0naKg_p2TH^QK?^hqg$el$G%QfLx}Qo6d-V0y*I44~@s&qLEy zAUJfs>v`%v>ech-4=ekGyLN5gy|;6VQYj@d0q0*SbsC;41s^`&Nm7>1*i@&qoKlOI|N_vO*6k zdC1kEuG7|ov>&buArSxkf1x@>b(Ol1{v;PJbZL6$EKNd5qUM)GYMOzVo|QBjhOxxR zgQ(3ff2TITj3QB3>@riZrnA=={)Kr-SenGrQ2K{HAEl=$d|8;9zI53S^ah&M9Sqm$ zn2vmDdJ5Vhz(6rdan>d#dK&3M_BWJ#z(g5^)!=sNgcUwrjGrAPh6Qn4Ktlw{R4!8o zhdf*ejpFc5d9g`1i-rJ=s4zt1SaYt2ZZLgx8SxA;llpXwx<4{Kc`+<>u)Y`@7l56z zrYSWVBN&JZp#2wFZ)r#8)((F+)>Qr?)_!g8NV+mOKd|ExcF+*=i*ch&Og2H($*`@% z4`4FQ&LpKpUyhHSlKhldo+u2qq(4h~0adC>ZO4_ysL}r$RRD{El4!f837Jc?v>XF8 z$Qt*Wv4bj;UQoI;(z(CJbPuF{mqCeC-86*q)51U?3}a4)UsU1ljIpK7X*7f{B0&Xw zd`vW9>Y6Z4ibkiI4!=JJ^9A_$ln-4;u*!yUNP-GoMx`SY6zC=mCfzXh*AENR;rh<{ z{?J4;T(4w?4^aPHIEoj8Q}rGGbBv9L0WKZH0G<&I393<8fVpc{)zJ_d=MO1aT)4ne zNr3$VwFF5RCIB#dDl$sbMnHE+9i<&ZN(+>{Xrn{sCz7DNJoTi5MJ`tXN1*if|2Miv9Q4{0PqQ^8>D$%AL-)fCi7(T(~7$`XP zTSyxKjEu-hS*Nc-BPI+r^m_oZ61e_5z}i$k2C8h7B1$|WswETcrEGMH1<^?}rTP|i z$S?kwXr~=W1m%8g7AW;EnO=|Fj?CvLZ3WC)-BnNkA|nElZtr|_er|ql;T*YfTNPul z4GKi<3JY*Xk(qK)O_-v918=~LHeQ2LeTKPO<6{`mR#5TAt1LUgt(Ed-o)Y$ofyrH! zvYB}dDxFx&*u1f|1$*mp^l1Vb<42v2s7h8iV`eGTDQst6lBf|zs~DRNX|2((cVthlr$hVrF_ zKSFW(!N&HYWR0_6dKbxGqs`H;BR>eOoLpsVykgt(*?BjeP}TVZ9AVWdx`~*xpETS* z^xo4e+xz3&``5fx@#?1%-V>siHX1(kZ=szf)ycYT^jnjx?V#VPhliQPkA}7VhyH2b zpY~ChKUrNTR&QUe-n~-2`+@r}N)y#ji`7rltBN?g+0Y$DBa}{oc;Ep`(ef9A|fS1E}(>0mtFdf68lB+6HKKax$2cnolY% zLin79nSE)(guopgFr*_;(tr|&9K+b{i&_eW(Y*NftSf$wN=aQoYi8!RPkE6|kPIZK z6LqF8qjR#Oknke9ne`OdJak4YG-nO2Uc(v=Fxw#(ZBDq`M0eYA3`V6^+&$|S<;yGI z42fx-qp|nsZPZNC%CXbvMv!zZAw2uij{}^I_%t}Wlvnz~c_Y1$3CO$;glgB+td3V! z>#NKsc(ewL_zbF(H{wi+Eray>*X5L?`(zyMlv>%8vNCZIH2i%|O7g8TE1tcd{3ghODyl2KR$mP2Ma(bZ?eNmsO;!x$9=Q7rFX^M8+Z4v zl{Cg-@U!HASaRUK9dXZ5b_`bgN_l&tyi+Xir2OWO(@F-wtF}!mwoOYT z3ELLYwk2-cvTiopz08(J%Zj&Uxgz1+A$oVjow;x6c-~SNx^(_6{GRItso$!w#DU!s2n zKar?Bp= zcO_a!fbBA%^)U}=Q<21HK2$Mm#8fOkDY}`orx@HyW0E1Ve4X3~*5XN~PY&e*| z7{#%$yhJB~vXqIKjj^3S!{mkiAq90MlB*+Q$?;Q%)kq!Y-ZUQ*-J9a>gSeMsV)FsX z8@C-~xBy#JbmmHsSkgAViJ~O9hCzwI>`M>Ju#PL|uCevskb5$0oC?s3K{2VMOw(9& zA`}^S(!)!wQVo-UUL?ieC2B?1wQT-0P~j!cW{-)`9ZA(CjaG-bhM)uc?44hk^-1^x&ipZ zYzZ6C9-$5`(j3;^ zSBrP76z@nB?-Gl5#od`VA!|ns4C?Gllol zfvTJIR;_xQSG>&$Z$R`0;?5j5i?eCPyD8yq61`1vXO8=cs(DPRrWQC-HK|4#H;-xu zh!iE!^Y6BHJ8)7?cju7b{d*| zSmIjFNH~jRJR?2uAZ`Kt!1)zvp$ef>gTUe$8FLqzOZfaW`LYJo`!t|5c9+qtUkqdt5)hm z2W!+!R*h;^>OQAS4KO zU*V>fp9k3!K_(>;e)a^k{d^Gwg7|Em*G?V@lWaB&_2LS z`R-N{sbuSJT*f27bl$6aQtP%dEKdlrhFZs_(Es9gG8OG$moV|<@oXy@iZ%9z^#b7 z{bt?%i!GNIuC#pg!b<0u)j0-_r4fLFOX>m&43U5{`N&)(`WM3|!D@mCZIDJ3oxPXw z2aN1Yl{=rMGC?wbjE|5&!M00O>w6W86}0Hrm}@@gOj@w326@^Lgg_n{vSH}Hrsu;W zR^I^#Q9KG|g8+-;i{scBH8xv`U5n$NZEm{oqAg8(wF>RKQoY}*-VeF)`zmiie|8A} z*p>+(`Wh$=7K2|vxmKO37FgP@g9(}aR^9%OPprhot=RZtz^;O9wGLf^@y$3I9Dqx1 zrRIDchMievM(=Q0hG+4|KT!NQp|gPWjh&vuxF#;cnZ`SR2pa$#8c!=s$k-|({e&l{ zn99QDf?=h+pG5;0e?#u1EXEvNTL66XJtqPFZXX2jZ{;9u8leil^JOpP=lgdny)%C4 z817(jXnFExc0BBh4&XJCl}wQ3^Bru+L_pYsvZHz9jfE`*MaqX9Ww#ndDj@OIZ?Woy z3f#;#Ylc~(t=n;O6&q~{>J{I@AhxlJuj-`@88cd$yP#V~BG@p|ohTGw=Gg>{4~jg$ zG7XhhCzSB=hfL!(i*|*s9)c0xl3=5V?rFM6D>JS#^nQY06a1FocLdzm2x4gv8BnGx z{zTWO1O;Nz6r2(1nagOt)FSTE`7d-|QVj?}LJQYs%X&lGVESq2g;{Ek-?ls@e^+tB z0e3E--iz9|za!DJ$8_!CeY)MkZM)RN|6slZ?!g~A_f>=!`!89DuUd||a5HAZspezq6VxcE=a}X)fQ357I zq21X0@+G?qL9Ct%N&v33%U>br&6_L03mxkPIQxMvv<^^H2UDkcQMFiuK4zva9s7UESRZQG0S8nludvM!llY@)SgM z@|^S}_I{jg9oD$Kuvjw8$+Jg7jH?>t%qSQ{$rU-Y(5tYk$@yMM24Z47OFfStMP-;( zvUQE=vto(fQ)Ld4<`DiJSaf~rz&!?7Dt%>*_oMXV31Ql@lRJC&s&pvhpxU`7Np=n&1 z1SN&SlBT9nA<%+&7FhUcNy|qZKaOBZN9P%${i?Ga#p-?RSOFjQmqTiYiG?&*Fs!7tP80&;$fq zoI)k>QK=rH_$G4cm99`7=~!}d1|mqw8M3)^MJwd4IkKQ`dL;CCT9E<#Y&@5{lxE7$ z2QiC(E@JY+kZZuL$TVcCAWm`?3=X0PQ`}(WK4CaGQQs!(ok|d(_5dq(?&HT7-Q6`$ z!ceu~rLyxOrToB48+3Wd{^!Ac1&*XXerX1gClD1XLR^*H3zs?UDp63%*&`UcCm=>J zcP3LwhK+I?EGiU82@>ZoyYUy|BSQ5i!`frcGObRHr{TNMTzUr2>s)vX8BaZjn0LVT z_bG%F0=2!Z&u;3;hCr*9dvGo{C863UcS|Dn7f_wsY9)GB5`9*p4_X^G*-BwgUPF%$ z|0PX=SlR8rBmeK~Y9ojsA5j)vC&ZayVj)02X(7t>G zhh7>6t%gBtrK`UQ9D1YBZfw3pT)dVKZ4}yx?U#0Zk{G<17`*b3we#RgV%$oMoAo6w zyJh#~%|C7Ud4tum`)br|dG6zR0CoNToa1bK&h%g4Z!5hLWM{767N!OVtSs zCBPq+5=w^NqYlfyWF9jun{eb^N5AyK z&*Cj+>zLcqi;TAjv!2%0DhlgA*7N?q@lU zing24c1lus-hl}w(t-KK>$ia%eEBG94!Fx}gpu~%h(6L0xYhwyTKTm>9k9E!zKtGK zorC&4H9Ir+ED>2nxDpap{)m1iq=M3HDp|eQI;Hh){FxyH&$Dqp#S=j5a^GxOGig)= zkLg;n)oy9CckQ)%2Cbew*{T@nD*(5)Hf2M+5fh5k*H+FuQi&ZxRD}1HP-}9r^HQI+ zxyyZ45-0@8iV!E3bzprk)FE^t{FA=3VW3EfENl01sYc^<6gLx`#y->d73=CXf=NVx z5bYZ&@y{gnp&SGbuGCCQvi=dlf6)(v_03)T0 z5{v9|A4ADYi$)sb`*aC0n3_q{h@)_tI%X{-A!5P&GcWk)@zo!Y;C~wU$%C{EOlkeDp-O43lP`z_M-egVQTAM*|Uz*vwDi@L>NDR?0Qt#0}jD0R!l!1?RVR@Jt21y+li z`lSPAqQ~qTHuoJi6Njz(Bi5#)rp9YUJ8B2&fu8I4+x4APA9Jg|BmHzXT&6=kYB9L@ zGFEjxid8)qUYU2fesnEAQWR6G-wHeP=HP_6b;7E9#?)%E;e!=ASPrG(s`#&YL%&@! zuIu1ZmWF0++o}Yuc_Tbuwo3JVbM(-ySgoCCwqaAbsf}0TcDtqB z-rkX|jfBEbv=9of2CByNvNes+)DjmT7lY4jS6;i)V|5Rk?ZZ|R5WXt*M}SpvHI*~N z#bD{l<)h*cBP7grK1Th39$(s-)$n(5Nd5}J%eqz`OP^evHXD1)aPLaE*9!Nh1KIF= inGT$#G+Y(`HE-yd&^}!Ueo-1;d~sDm*47CZeB<982gC~i literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/asyncio/__pycache__/lock.cpython-311.pyc b/.venv/Lib/site-packages/redis/asyncio/__pycache__/lock.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..09b348f2de154d040052922db2208de600b2c9d5 GIT binary patch literal 14742 zcmc&*du$xXdEa}HcjS>r9iKYBRunCY5=A{MS+QOgMNzUOmX`T&V@CFIdAk%(I^Hq6 zccREp4ig(K8wiMED3zKD2+^jF1RI6^DWLpOv@Y5rKwIFBSU`sb1PCpPCV%w|C8&|V z`uk>f_x6sYV+R4UI?m3{&V2LDH{W|!Kdq^$5^()#+utew&@Tx8MGw~HH7hSxP`M|_ zg6v8Nll<wqoUEMlPx|KqlL6N5O;pWQPgc(b zCxb3QsZjms>r2$k)lSyVg(gET!7ZE@2(>Q zvH0A4LK%_f6m4FLDZO5!X8i5TL(#$4hXyZQ7&&hQ1{S1vTAEHMhX0NEbUc-m5{7Rg ziAt~A2n?rU*N0R!r5f9)I+9Aiv5-_`*7V42_(l~ut{Fjg8%$)hw4%mLWY{faKD_wI zMTAiVA_fTIn)Jx-NiY6<_^XgTla;b}(l7fa0|CMMCwI$!rAiKLw;{?^N|jQr1eKZ@ zkE69(sZ~Ob=b#djYm_> zS~-*kyk}UN(4I6vOO~Ak_H-F%rY+`k{+=6KL&3+mft2jm&I z96@_TZdHPElkCR$Haxcm1bLU-ft7Y*r5NMH890c*q0NN51O3}K^l{5wXzwul>_oj& zc7uI-3@`2V(*IV8xCTURR#FwYPsC2A)%bKKt;iyE=ocrnc=D>qHeZ}csbT`H)FLGk zsRd0;&nm1VgOg5)(~1d8lwxX1)5Li-6;m`#(L^aJ?+1W6DK;BVDq4RP8*?GuqlpP+ zCM{w#LCa{0N_ADyQi&UiC@YdolZtUo%WyD&aUJtyRE2?<%Ouiqh=3SN#Fb&_WvC9&Cz=J*?_j%?|Fv4Qrz=CkpnDpTgl!p z{i_Y~554hDw%ueICMmaA$N&83FX;N&YvYEG0aD4}8r~$Vmr7yuMXfHu^sEZS5M|Ve`EBbV2p-hw??oFkN6W5dA!@%~cH;@{{95+l$+oP^ zUOdrAb}jqxWZ8USxdKl<>s`9WstLk!C7HdCi!g;~rS*1MxMtVY`t&xdT@bDXtolc& zd~7`k$(nSd{UDUS0|xde8LKM7h*n!;mW8#TRd?P?A;AM7AHpsDEvRoZ)*uL)Rz!(7 zk?C|Xp48G(GNy>MJ+e48Mfa&GsA#ePq^w6tYnpo32Bc-?=b?#Zae5JB*fvj1nd+Xj z;?$J6ivSf*%JCScg?WHhzZsv)%!!HkjKXXU%|I-GUZSSNQb`$BgCNj#W)Y@gMuP6| z6XR)dA)ZJ;-_A+sOJgv7CYg>?TSAdEWp^(Oh)DWfk&8f_sKlfsGhg#cEIvc%ON7)+ zA|<6s+sBh><*K6giPNd{ETGQAK*8F85;jVNZ!$AC4Fi^%u`q_25Xt{4Apm3WlI7D_ zX)XnvX)F zGtk6_6w9b876h9)n@Y&m4im5v)Gd%D*kf)E74)T%Q&Upxo0+&u+@j5+Fg^$Fi-SoLi+$KZ&V7y5hBl+gHk?J3A~ zPb-9+HAlaAmNO9Cn3OoKW|SghzzfC(%z|ZZNQn$w3(g#=8;YvNWf_=)x#uN~NrHs+ z7Rh3xBdJ$2bD$_ecc8l|H7&(fLRG@u5{fe3C`tsN+cRqOFgRjbU1YnLvQ}zyML%3U zz8>({)YM2SNgHI#pbZD22FAv+O;B+B6s)}8u}%lVn+lE%>q`g_!|%%pj#KSBQ5P)^ zwD+5PXV^e^gE2^Ryy%*7Ap5|1Z~(P*N|mlE{Ur*8plk#HJjv(~%Ss7*fhGV^BmWh; zLbAH0l8_}$fo_Y#DP`bb=D~*O!F)(f0ZT60fGpAEv-FFDsiYQ{$r}bXGbwVo*}g(I zK**G1+=1rWP-H6On0TPioPFOxYxgyAYHpDhdwr@8Y7)u|^K(l}s^*BLsEW*Qfn;}+ zSO?LKR$&tcOx-0-$GU9vsW-trCLXkrIK;&s<2LZ5ja1Q`lz_6480Hp$o1#)A`E*C@ z=?;pdNQlIXAZ;u~fiXgvey9bqQ{3s|iy(SzKHqg^@r!3UWKk9-(V{FST>x>g{c#Ft zq#ICN6mgeAve#r1_0VQSy}7uw8Bt$xta2uvjBB$dV=biA>rAzianp+Su3v;3i~ZVs zl{R8OCGR%91zJQi zj74x4qp)!%lYk7FCY-}%BDn7mMUADV=>nXD6wD?9NT_RyIN4St6#^uw6be#&%V%&1 zvbD&5@mxx^iKX0>hXWsXpF2VG>xi=P@NX3OnXA!0-?lKNv1(5+E&IH z?4|8f0UHT4Q?D}tXL0ENchI*NXb0(?jTe9vl@`o*vL|h=igX;hGdD*A=Clo^ z6D*{tJGRIMSKKPDjMyMPC90&&xE+U80W?N&@r{fM-$={Mv0Rc33iGlN=xFZ%vI;aK zBykQQBJ)2q+S^&nccV>V2Hgf@PF}Lkq7;qv)~I#xY*lim)i4$HR5VaQuCw8tPNfoR z6IBBo7L=ypWAIcDHTxLv8+EF373mH|jcPG9KA+Zl{f1Xl5;I>s0Ryd3#9@iRZ{9q6 z>|)6+4dn-cO7O&yTVk{ zeo0$Q#^R~{jKcGahCdpGjHjc~rJ7-4bL(*g^J*WUSP=?0T|!gqs`qwPzM%!TK)$&H zw_v_8!Wvsd+-maTfmN^WZ-3S%uC?Xb`t`PcdfuMj)35J2o^2fc;oEnkxyD_3^OWq%R>Th57x99wwy1z4P{ayeMA!dg@cp&=H--{}=-V+d{ z;DKMaC}gqw-f}OyuGyj2O6RhBjmB-b(8~_O$^tEyBXo0JvxBoQgjHcpumP4m9y8iO z+sckFz{?IgH^8#T%fc9vz+=KA*GO-`2t=c?1Oz7B|-`03HvRaX^ zuD$(Qwz@0d(fzdJ@OsDL$7A}DOSz6=y<>QF@b(+@{#3SlN4|aM)ApCw+h2Y>s2{$N zYrm+sU&Q+nyw|JSven&rao1Dvm38rz$C`fhjhuK{7cZ|4>cRFb`xQJw@FjFpMIf<( z^WI0}iz_HD2`6Do+|OpBNy8RjpTuo-KdI2B?JplN71E_Df3pt zkI_v#f#MhV2ik9Iyw~<&+YdVKc4VtN%YFsH6==!VH?LlLR@Axji}Q*Rpc?ZBpqEv+~%6hQBjq$&NZ7+)|~JGo?oTCZ+VjM21q5^s^*%lj@E3IVU4AG z*?3>Fcc+jh>t|lw5LQ+j78YE~zRhu8_LMUIEzh!RrP7&oflO}uZdEM1zq32tY_%cRWoM*H*R$rxq7{3W_E~l>;nl4QqT5<+u~)HHjwi&~ zWs7qyW%#aH2UJ4TrX3xEEW0$f?18xdzHs$2Tq~C=zT;m;d7bfux^WI0`DJe@jh(o= zgxgEKUP%Ls+OE+A{3@PtgV#h!8d2KxatwgCrT2sjX8 zf=oE;x`BWl=V+{xJ?R_{O{t@VXrEG@sp)GiVr$yE5-W+DadBH|2q+!P_O z5jG@qB#Yt+XEOsTvLS%O(6G`AJUFnh2Ue0eF>&Fn4UDBsf!0+eNjXGkUUX#qT<>it!4c$6ObEFmgjjS06rG3XZB*m*ENb>JY6sHhc_KSbcDU)4 zrpIg4QGYd)OagtR^HcMNmu#m|C8wg6$&5f`m>%!-GqX~J!&*6_mG-2_$jnFiCP$^T zQJsX#M9+9AaooATgM)ryDag!?Ip0swqJ0atnH!tJ9syoX)v7OFUAKDjSwqX+i$55? zJFGW!KW*5%-mo{q>sRPcIhUd~549_-O0ho44HuSZVjB4_l-nLCwtDnEZ# zzoQ_yYhErE&#CLv$bt39fn4N}9yvt)?o<|h==J&MpBE~G#g`9Lwx3vU zKap!crMI8T4!oIbe{*%D;0^?O@{QZ?ML&$LP2?K)>WzD|q4FOg+LqtB`;PZ+m0l-e z);sBZeJebSn)ZBi+nvm_$POT#iyUUleRVzZYA$kIj~suZ6y_pR&y-dj5G+Wc57rkuiiaMY>)} zB4y7%M{rskX3UEAaRdY>Kf&-oG4V9Rempu|^$HGishTMb{_vmF=LiZ@XZVGt$lb|% z?|%61+S#96$Tjxsjs4kB`R}ou4IRt+k8LC%F%e_x8z9y1mw<5GT&k9KxSY$bv>nYt zARt`D4~{hMv;rM|72Vf061)vpsRIXbBB#~iy4g;vJ@U)JDREleYYu#EKyc|w*@opD z>_gLQwxdcclnT+&aPbhe`1U&1FCeDrbuW#5MHXX>M-1_W3|7q;Or=~7V=$vCj&mfQ z;5K~B;;R(xsVAwR;7mPEMbQkJL41(T9uzss+zoXQeM*#r;Y-n%TuW7qPg(sJ)aTz& z*lgO-^mu}{z|sF{I?o}DGIg}go?n|{-)~TiN9~miLdG6YpkK* z{(T$0ww*sd^`lb{`*N*E_12@S!}(DC?Ik_bxt3-&>hj~@KYIVUNCG4Kp(ssEIg(NkjFnK@j?V;q%U8-!-*vH*cfjD6 z<68n@3oB8^l3**(Qr9Ryl;)1Bl%NbR^pllpB?cN<>Kv4kbd+JGgmD6yNpfYwlo~>8 zn;}?Ifw@d(??-MPf7jy71Kyd%BNR@+c5u^i2zAr(F-Lul7LAy0MR>lw{XsIhv}L^EGWsl3pAR=Z4R@`FyYet9@jKsmSexxRN-}_aSpCk=1b2Py zuc#o0ZR_GQkGHPsR|1NH;0uhqeqANhcW1jtbKx;PJeCcP6{@M3zhs+u&In1e9Os{m zvcSuz#+MItpc=)OQ!$(DK$Z*^J-@hvVk-&zZPMl3+Ooc7`H1g=4YtT!ATLpB!mzPk zX%ErwJ^N1LAclP`LSHeMpOEnHMr;I} z-;b~We6y%k#C#?5J7|x&;pp)19CkZG!Cr)UG7cuoQAIRqPi{rKU|wX~H2Q``#CEda zk;miaM0RQbJ?Tq1iaTv68>VphP)i-A$naz}QMW{QEp?Z@=Mu%@TF4V^3O)pbD3xkB z?j#4`=yJG^xE)mA0n4fHq9`?g6}*?}r|}0r3D*U5#Q{o02-e*`rn4xD>9-TP@JT&< zG8;UZCzlzSRn~ka7ar8ZgW2F9EYbJh``&x^QxCtD3mw-($Fu(9+;?+|0{JHIZv13=!FN0s>M%u|e?~*-NDFJ5tX`gt%g0{5N zX3&C57t7d5AZ zwajQ1aX1$_qDPLbhPW=hxBtWarY5D^HN9!q z!_bq~?5o2+ug|_Zmc2ZdZ5*c5Jb5pKLA-%YHI z=bCzR;XQhI&uXRRb#Y8pL4w;eGxz@{b-a<3h_B-CPDRJH2TeqlrY~^Mx$~n zhV$iaqE-(TjBdNAwwsDQRM3_i9%P=?QL0tpLxq&Ocq6VXsAMV(ANyvHtL07_&_=}p zDqf+2GN$SoD&C-iQama#m`V|aN<3IjsCqp{g?C&w85*9rfFBZ!8?DY{R_;ro4N1zBz&v zXuj`2zI{hw+mOpA76dAvhZ?eteR^nL!N(dagiyns!TXJCRoR9;dhOmqC2RHz;mG}$ z?sgUe?6FFyYb;c=Y7kfyYFM>aXx+JX`|iiqj@-Yd zxAf|vJ;h;cEH9>AeqZC7@^J8R$yK( z5a_;1DOULQ-`~D=_(3P_-v08UuEIC&dYGZ+ao3Xue&3`F3&&5p3Z88~~D+%L{c`>z5a*SJ=P2up?Xg%L^y6zwP&2cs0A(@42TA{OdZD_a4k{_A68*ye^P) P^YSy+{;MtCvgQ6i0x?%7 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/asyncio/__pycache__/retry.cpython-311.pyc b/.venv/Lib/site-packages/redis/asyncio/__pycache__/retry.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1b391e983609307bce26a56f30cbb303087b2435 GIT binary patch literal 3485 zcmb6cU2NON`6!YSB}Z(7}(4DrY;>&^l9IbG$q^1 z!%pOPci;EjclZ4s^~X#mg`oZJ)L-yp0il1=$$sO)!Smn4U=wLbV+>?662s7O%!rw+ z#G0JMnY_fCaVc&lq=YF*f|-<(J`Zc8%pR%7OiO7qBV`zbSrUh}oY8A$r7VMD2q!iE z69%Ej@CHrF#n26;#UCIo@ktCQ@P?E=O?VF#l3&tkf$@09z_?OKc$w1OccTo>LQ$9Oa@k`_YIs7wONNu@+c4Nf7)gwVq?pD? ztQM0v%;R`DR%SF-<1`*8v^W-U5~of^GPFcF)|r*#n(%;^dbA`?mt$J$0Vid&9^AWt za2Dsf_`23;Y21rb3k>e-mZW8H4y5&hgnlgxmdttl40cIv^|IfIis)3Zs+V3E5di}Zqi zUSgj!cbKuL?#COo1NAuz@AJz5Hc_3aBN;|PtH)p##Y>%qSrj801A4`j^FU6CVY_MR zuC5sRDh37Sd{yT}d;T6cTwK=OMT!l5xsQ+5x{Hb{hKB||Q(4i?s!8oK7h>lE3l*a! z9fGP@;ye~Dyr8)HeJr}RFRCV%ZG!J((phuYu8Nd9uzyW-7l9kX)1f;>rV<02ipz_- zx+sFl7Zxyy_EkdRzDiWUT(mHB#++DDh+<-JWoPSY(hp`Wa31GiqfB0c2{}%|2>=dt z3N_=mGd~)eRc%eT7G~eK%cXa~_s;ALHZhG8?5NmM@oe!vw(if~*5_v(-NlzGz@#i- zXO_@x8daQ{rRw%5HC(M&sX++II`~GGS9^W06!+)!M2-kx9koStQhdlg%Ct_L@w=D5 z`;co2ryKtB9C(nI3&S>wIyH(1AVXaXVu`?D6S-03Amq{*3tJuCi&k~>)R}|zX%+Yn zVh+xZM&s&FA|Jh9(G(ZFO5GEACvq!|MV}I6A=Uy)5DAftX((8{>lZTC0aFgbfeJB_ zhmM>E;7~P0kqklS9k2R39?8qq;lScAAfKahz7Jp>{YO9}=f6m2H@If*+@A&;qd(j& zTyGYx@8+)WrpKG<@vqp}Na||@pvy62nC>3aY>%TQ!;6E{tHe^f4321QeE{$CJK&OA zh@pv&?g1ibJ6(?2$ARf#_&A!vHN&j2NtA?&0ggIA`v7U|FWEb2ll?9C9y&{9M-F}k z5p#{JLkV8ZAhgE9>R6pS=*aH%3|$?aU1OGbdIXZ8#ixT`q8cFrl70gPt4k9fPift) z&K}%vjj!_{Igl~v_H=mbhpxzjC%X%Ju5rKOEFtKZnPs%X-bKsIqelf^IoDkZr&h39 zb)gPgqFuoR%93qC$U%)W^@T;(FYiFqXej}AIil`5Fm|ejdr`DIwT39V0~HFQ7_X?f z(h;+)(BLNavL$M`f-PDwM1K#cM~8}Rrv}Yw_S~2+uIp4bR7Arlic>3)4sZ<178SBk zHL>M(t)$Tvt_|-daS;?SFu4e43s%x|8j9oYrxVq;bI>TU2n~JEvjQe0G#Y@*PrI`)Ca+Mk5FWzuc)wWt_0)+2iB{45tjto)WLl{GtFyK` z7-ZuibP<+0{|4|c_(3V`N6E~i%;&<;Ght{~7;Xx~4Pm%7aO|Pbj-`@?b}X4Gw1&@Y z&3s(iE^VxKevRDA-?RpfHwOxBl*n{}R_?^s_=lMdq4iRJL)&`e!=;awfcfYHt3P^s zXZ+c~tBrwIKfUmz^yi;Hdu^ie+C(dVX5&^Xe|r1U=lRiR`OzoBZvJXBe|00#8pv<` z><`yAu6>a|vy=F^xLs@>7!T*s90wgzK|+;=tw|A;tsbXHO0$M&Njq1 zn)x?7{QjZg?xkgrt6rO{>kui z{#QUTDi}`S4&U^?Pci{R_XlHOdEdrY=nnK&@$LSt@K)gWACRknqbckB9YC997^a0z zHV!^5^lsz-fA-Li8!vwL*jyViOtHmXY8-sPn|ylx#>2^9-+pj=ooUD4WWc&d!B-Ub K_5UFFdj1zRJCU6L literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/asyncio/__pycache__/sentinel.cpython-311.pyc b/.venv/Lib/site-packages/redis/asyncio/__pycache__/sentinel.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aebcfc5b63cd52df53a1f77433858529f7ba478b GIT binary patch literal 20387 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 j9I(+#``U-Yqv}Y{QENnI; + - `rediss://` creates a SSL wrapped TCP socket connection. See more at: + + - ``unix://``: creates a Unix Domain Socket connection. + + The username, password, hostname, path and all querystring values + are passed through urllib.parse.unquote in order to replace any + percent-encoded values with their corresponding characters. + + There are several ways to specify a database number. The first value + found will be used: + + 1. A ``db`` querystring option, e.g. redis://localhost?db=0 + + 2. If using the redis:// or rediss:// schemes, the path argument + of the url, e.g. redis://localhost/0 + + 3. A ``db`` keyword argument to this function. + + If none of these options are specified, the default db=0 is used. + + All querystring options are cast to their appropriate Python types. + Boolean arguments can be specified with string values "True"/"False" + or "Yes"/"No". Values that cannot be properly cast cause a + ``ValueError`` to be raised. Once parsed, the querystring arguments + and keyword arguments are passed to the ``ConnectionPool``'s + class initializer. In the case of conflicting arguments, querystring + arguments always win. + + """ + connection_pool = ConnectionPool.from_url(url, **kwargs) + client = cls( + connection_pool=connection_pool, + single_connection_client=single_connection_client, + ) + if auto_close_connection_pool is not None: + warnings.warn( + DeprecationWarning( + '"auto_close_connection_pool" is deprecated ' + "since version 5.0.0. " + "Please create a ConnectionPool explicitly and " + "provide to the Redis() constructor instead." + ) + ) + else: + auto_close_connection_pool = True + client.auto_close_connection_pool = auto_close_connection_pool + return client + + @classmethod + def from_pool( + cls: Type["Redis"], + connection_pool: ConnectionPool, + ) -> "Redis": + """ + Return a Redis client from the given connection pool. + The Redis client will take ownership of the connection pool and + close it when the Redis client is closed. + """ + client = cls( + connection_pool=connection_pool, + ) + client.auto_close_connection_pool = True + return client + + def __init__( + self, + *, + host: str = "localhost", + port: int = 6379, + db: Union[str, int] = 0, + password: Optional[str] = None, + socket_timeout: Optional[float] = None, + socket_connect_timeout: Optional[float] = None, + socket_keepalive: Optional[bool] = None, + socket_keepalive_options: Optional[Mapping[int, Union[int, bytes]]] = None, + connection_pool: Optional[ConnectionPool] = None, + unix_socket_path: Optional[str] = None, + encoding: str = "utf-8", + encoding_errors: str = "strict", + decode_responses: bool = False, + retry_on_timeout: bool = False, + retry_on_error: Optional[list] = None, + ssl: bool = False, + ssl_keyfile: Optional[str] = None, + ssl_certfile: Optional[str] = None, + ssl_cert_reqs: str = "required", + ssl_ca_certs: Optional[str] = None, + ssl_ca_data: Optional[str] = None, + ssl_check_hostname: bool = False, + max_connections: Optional[int] = None, + single_connection_client: bool = False, + health_check_interval: int = 0, + client_name: Optional[str] = None, + lib_name: Optional[str] = "redis-py", + lib_version: Optional[str] = get_lib_version(), + username: Optional[str] = None, + retry: Optional[Retry] = None, + auto_close_connection_pool: Optional[bool] = None, + redis_connect_func=None, + credential_provider: Optional[CredentialProvider] = None, + protocol: Optional[int] = 2, + ): + """ + Initialize a new Redis client. + To specify a retry policy for specific errors, first set + `retry_on_error` to a list of the error/s to retry on, then set + `retry` to a valid `Retry` object. + To retry on TimeoutError, `retry_on_timeout` can also be set to `True`. + """ + kwargs: Dict[str, Any] + # auto_close_connection_pool only has an effect if connection_pool is + # None. It is assumed that if connection_pool is not None, the user + # wants to manage the connection pool themselves. + if auto_close_connection_pool is not None: + warnings.warn( + DeprecationWarning( + '"auto_close_connection_pool" is deprecated ' + "since version 5.0.0. " + "Please create a ConnectionPool explicitly and " + "provide to the Redis() constructor instead." + ) + ) + else: + auto_close_connection_pool = True + + if not connection_pool: + # Create internal connection pool, expected to be closed by Redis instance + if not retry_on_error: + retry_on_error = [] + if retry_on_timeout is True: + retry_on_error.append(TimeoutError) + kwargs = { + "db": db, + "username": username, + "password": password, + "credential_provider": credential_provider, + "socket_timeout": socket_timeout, + "encoding": encoding, + "encoding_errors": encoding_errors, + "decode_responses": decode_responses, + "retry_on_timeout": retry_on_timeout, + "retry_on_error": retry_on_error, + "retry": copy.deepcopy(retry), + "max_connections": max_connections, + "health_check_interval": health_check_interval, + "client_name": client_name, + "lib_name": lib_name, + "lib_version": lib_version, + "redis_connect_func": redis_connect_func, + "protocol": protocol, + } + # based on input, setup appropriate connection args + if unix_socket_path is not None: + kwargs.update( + { + "path": unix_socket_path, + "connection_class": UnixDomainSocketConnection, + } + ) + else: + # TCP specific options + kwargs.update( + { + "host": host, + "port": port, + "socket_connect_timeout": socket_connect_timeout, + "socket_keepalive": socket_keepalive, + "socket_keepalive_options": socket_keepalive_options, + } + ) + + if ssl: + kwargs.update( + { + "connection_class": SSLConnection, + "ssl_keyfile": ssl_keyfile, + "ssl_certfile": ssl_certfile, + "ssl_cert_reqs": ssl_cert_reqs, + "ssl_ca_certs": ssl_ca_certs, + "ssl_ca_data": ssl_ca_data, + "ssl_check_hostname": ssl_check_hostname, + } + ) + # This arg only used if no pool is passed in + self.auto_close_connection_pool = auto_close_connection_pool + connection_pool = ConnectionPool(**kwargs) + else: + # If a pool is passed in, do not close it + self.auto_close_connection_pool = False + + self.connection_pool = connection_pool + self.single_connection_client = single_connection_client + self.connection: Optional[Connection] = None + + self.response_callbacks = CaseInsensitiveDict(_RedisCallbacks) + + if self.connection_pool.connection_kwargs.get("protocol") in ["3", 3]: + self.response_callbacks.update(_RedisCallbacksRESP3) + else: + self.response_callbacks.update(_RedisCallbacksRESP2) + + # If using a single connection client, we need to lock creation-of and use-of + # the client in order to avoid race conditions such as using asyncio.gather + # on a set of redis commands + self._single_conn_lock = asyncio.Lock() + + def __repr__(self): + return f"{self.__class__.__name__}<{self.connection_pool!r}>" + + def __await__(self): + return self.initialize().__await__() + + async def initialize(self: _RedisT) -> _RedisT: + if self.single_connection_client: + async with self._single_conn_lock: + if self.connection is None: + self.connection = await self.connection_pool.get_connection("_") + return self + + def set_response_callback(self, command: str, callback: ResponseCallbackT): + """Set a custom Response Callback""" + self.response_callbacks[command] = callback + + def get_encoder(self): + """Get the connection pool's encoder""" + return self.connection_pool.get_encoder() + + def get_connection_kwargs(self): + """Get the connection's key-word arguments""" + return self.connection_pool.connection_kwargs + + def get_retry(self) -> Optional["Retry"]: + return self.get_connection_kwargs().get("retry") + + def set_retry(self, retry: "Retry") -> None: + self.get_connection_kwargs().update({"retry": retry}) + self.connection_pool.set_retry(retry) + + def load_external_module(self, funcname, func): + """ + This function can be used to add externally defined redis modules, + and their namespaces to the redis client. + + funcname - A string containing the name of the function to create + func - The function, being added to this class. + + ex: Assume that one has a custom redis module named foomod that + creates command named 'foo.dothing' and 'foo.anotherthing' in redis. + To load function functions into this namespace: + + from redis import Redis + from foomodule import F + r = Redis() + r.load_external_module("foo", F) + r.foo().dothing('your', 'arguments') + + For a concrete example see the reimport of the redisjson module in + tests/test_connection.py::test_loading_external_modules + """ + setattr(self, funcname, func) + + def pipeline( + self, transaction: bool = True, shard_hint: Optional[str] = None + ) -> "Pipeline": + """ + Return a new pipeline object that can queue multiple commands for + later execution. ``transaction`` indicates whether all commands + should be executed atomically. Apart from making a group of operations + atomic, pipelines are useful for reducing the back-and-forth overhead + between the client and server. + """ + return Pipeline( + self.connection_pool, self.response_callbacks, transaction, shard_hint + ) + + async def transaction( + self, + func: Callable[["Pipeline"], Union[Any, Awaitable[Any]]], + *watches: KeyT, + shard_hint: Optional[str] = None, + value_from_callable: bool = False, + watch_delay: Optional[float] = None, + ): + """ + Convenience method for executing the callable `func` as a transaction + while watching all keys specified in `watches`. The 'func' callable + should expect a single argument which is a Pipeline object. + """ + pipe: Pipeline + async with self.pipeline(True, shard_hint) as pipe: + while True: + try: + if watches: + await pipe.watch(*watches) + func_value = func(pipe) + if inspect.isawaitable(func_value): + func_value = await func_value + exec_value = await pipe.execute() + return func_value if value_from_callable else exec_value + except WatchError: + if watch_delay is not None and watch_delay > 0: + await asyncio.sleep(watch_delay) + continue + + def lock( + self, + name: KeyT, + timeout: Optional[float] = None, + sleep: float = 0.1, + blocking: bool = True, + blocking_timeout: Optional[float] = None, + lock_class: Optional[Type[Lock]] = None, + thread_local: bool = True, + ) -> Lock: + """ + Return a new Lock object using key ``name`` that mimics + the behavior of threading.Lock. + + If specified, ``timeout`` indicates a maximum life for the lock. + By default, it will remain locked until release() is called. + + ``sleep`` indicates the amount of time to sleep per loop iteration + when the lock is in blocking mode and another client is currently + holding the lock. + + ``blocking`` indicates whether calling ``acquire`` should block until + the lock has been acquired or to fail immediately, causing ``acquire`` + to return False and the lock not being acquired. Defaults to True. + Note this value can be overridden by passing a ``blocking`` + argument to ``acquire``. + + ``blocking_timeout`` indicates the maximum amount of time in seconds to + spend trying to acquire the lock. A value of ``None`` indicates + continue trying forever. ``blocking_timeout`` can be specified as a + float or integer, both representing the number of seconds to wait. + + ``lock_class`` forces the specified lock implementation. Note that as + of redis-py 3.0, the only lock class we implement is ``Lock`` (which is + a Lua-based lock). So, it's unlikely you'll need this parameter, unless + you have created your own custom lock class. + + ``thread_local`` indicates whether the lock token is placed in + thread-local storage. By default, the token is placed in thread local + storage so that a thread only sees its token, not a token set by + another thread. Consider the following timeline: + + time: 0, thread-1 acquires `my-lock`, with a timeout of 5 seconds. + thread-1 sets the token to "abc" + time: 1, thread-2 blocks trying to acquire `my-lock` using the + Lock instance. + time: 5, thread-1 has not yet completed. redis expires the lock + key. + time: 5, thread-2 acquired `my-lock` now that it's available. + thread-2 sets the token to "xyz" + time: 6, thread-1 finishes its work and calls release(). if the + token is *not* stored in thread local storage, then + thread-1 would see the token value as "xyz" and would be + able to successfully release the thread-2's lock. + + In some use cases it's necessary to disable thread local storage. For + example, if you have code where one thread acquires a lock and passes + that lock instance to a worker thread to release later. If thread + local storage isn't disabled in this case, the worker thread won't see + the token set by the thread that acquired the lock. Our assumption + is that these cases aren't common and as such default to using + thread local storage.""" + if lock_class is None: + lock_class = Lock + return lock_class( + self, + name, + timeout=timeout, + sleep=sleep, + blocking=blocking, + blocking_timeout=blocking_timeout, + thread_local=thread_local, + ) + + def pubsub(self, **kwargs) -> "PubSub": + """ + Return a Publish/Subscribe object. With this object, you can + subscribe to channels and listen for messages that get published to + them. + """ + return PubSub(self.connection_pool, **kwargs) + + def monitor(self) -> "Monitor": + return Monitor(self.connection_pool) + + def client(self) -> "Redis": + return self.__class__( + connection_pool=self.connection_pool, single_connection_client=True + ) + + async def __aenter__(self: _RedisT) -> _RedisT: + return await self.initialize() + + async def __aexit__(self, exc_type, exc_value, traceback): + await self.aclose() + + _DEL_MESSAGE = "Unclosed Redis client" + + # passing _warnings and _grl as argument default since they may be gone + # by the time __del__ is called at shutdown + def __del__( + self, + _warn: Any = warnings.warn, + _grl: Any = asyncio.get_running_loop, + ) -> None: + if hasattr(self, "connection") and (self.connection is not None): + _warn(f"Unclosed client session {self!r}", ResourceWarning, source=self) + try: + context = {"client": self, "message": self._DEL_MESSAGE} + _grl().call_exception_handler(context) + except RuntimeError: + pass + + async def aclose(self, close_connection_pool: Optional[bool] = None) -> None: + """ + Closes Redis client connection + + :param close_connection_pool: decides whether to close the connection pool used + by this Redis client, overriding Redis.auto_close_connection_pool. By default, + let Redis.auto_close_connection_pool decide whether to close the connection + pool. + """ + conn = self.connection + if conn: + self.connection = None + await self.connection_pool.release(conn) + if close_connection_pool or ( + close_connection_pool is None and self.auto_close_connection_pool + ): + await self.connection_pool.disconnect() + + @deprecated_function(version="5.0.0", reason="Use aclose() instead", name="close") + async def close(self, close_connection_pool: Optional[bool] = None) -> None: + """ + Alias for aclose(), for backwards compatibility + """ + await self.aclose(close_connection_pool) + + async def _send_command_parse_response(self, conn, command_name, *args, **options): + """ + Send a command and parse the response + """ + await conn.send_command(*args) + return await self.parse_response(conn, command_name, **options) + + async def _disconnect_raise(self, conn: Connection, error: Exception): + """ + Close the connection and raise an exception + if retry_on_error is not set or the error + is not one of the specified error types + """ + await conn.disconnect() + if ( + conn.retry_on_error is None + or isinstance(error, tuple(conn.retry_on_error)) is False + ): + raise error + + # COMMAND EXECUTION AND PROTOCOL PARSING + async def execute_command(self, *args, **options): + """Execute a command and return a parsed response""" + await self.initialize() + pool = self.connection_pool + command_name = args[0] + conn = self.connection or await pool.get_connection(command_name, **options) + + if self.single_connection_client: + await self._single_conn_lock.acquire() + try: + return await conn.retry.call_with_retry( + lambda: self._send_command_parse_response( + conn, command_name, *args, **options + ), + lambda error: self._disconnect_raise(conn, error), + ) + finally: + if self.single_connection_client: + self._single_conn_lock.release() + if not self.connection: + await pool.release(conn) + + async def parse_response( + self, connection: Connection, command_name: Union[str, bytes], **options + ): + """Parses a response from the Redis server""" + try: + if NEVER_DECODE in options: + response = await connection.read_response(disable_decoding=True) + options.pop(NEVER_DECODE) + else: + response = await connection.read_response() + except ResponseError: + if EMPTY_RESPONSE in options: + return options[EMPTY_RESPONSE] + raise + + if EMPTY_RESPONSE in options: + options.pop(EMPTY_RESPONSE) + + if command_name in self.response_callbacks: + # Mypy bug: https://github.com/python/mypy/issues/10977 + command_name = cast(str, command_name) + retval = self.response_callbacks[command_name](response, **options) + return await retval if inspect.isawaitable(retval) else retval + return response + + +StrictRedis = Redis + + +class MonitorCommandInfo(TypedDict): + time: float + db: int + client_address: str + client_port: str + client_type: str + command: str + + +class Monitor: + """ + Monitor is useful for handling the MONITOR command to the redis server. + next_command() method returns one command from monitor + listen() method yields commands from monitor. + """ + + monitor_re = re.compile(r"\[(\d+) (.*?)\] (.*)") + command_re = re.compile(r'"(.*?)(? MonitorCommandInfo: + """Parse the response from a monitor command""" + await self.connect() + response = await self.connection.read_response() + if isinstance(response, bytes): + response = self.connection.encoder.decode(response, force=True) + command_time, command_data = response.split(" ", 1) + m = self.monitor_re.match(command_data) + db_id, client_info, command = m.groups() + command = " ".join(self.command_re.findall(command)) + # Redis escapes double quotes because each piece of the command + # string is surrounded by double quotes. We don't have that + # requirement so remove the escaping and leave the quote. + command = command.replace('\\"', '"') + + if client_info == "lua": + client_address = "lua" + client_port = "" + client_type = "lua" + elif client_info.startswith("unix"): + client_address = "unix" + client_port = client_info[5:] + client_type = "unix" + else: + # use rsplit as ipv6 addresses contain colons + client_address, client_port = client_info.rsplit(":", 1) + client_type = "tcp" + return { + "time": float(command_time), + "db": int(db_id), + "client_address": client_address, + "client_port": client_port, + "client_type": client_type, + "command": command, + } + + async def listen(self) -> AsyncIterator[MonitorCommandInfo]: + """Listen for commands coming to the server.""" + while True: + yield await self.next_command() + + +class PubSub: + """ + PubSub provides publish, subscribe and listen support to Redis channels. + + After subscribing to one or more channels, the listen() method will block + until a message arrives on one of the subscribed channels. That message + will be returned and it's safe to start listening again. + """ + + PUBLISH_MESSAGE_TYPES = ("message", "pmessage") + UNSUBSCRIBE_MESSAGE_TYPES = ("unsubscribe", "punsubscribe") + HEALTH_CHECK_MESSAGE = "redis-py-health-check" + + def __init__( + self, + connection_pool: ConnectionPool, + shard_hint: Optional[str] = None, + ignore_subscribe_messages: bool = False, + encoder=None, + push_handler_func: Optional[Callable] = None, + ): + self.connection_pool = connection_pool + self.shard_hint = shard_hint + self.ignore_subscribe_messages = ignore_subscribe_messages + self.connection = None + # we need to know the encoding options for this connection in order + # to lookup channel and pattern names for callback handlers. + self.encoder = encoder + self.push_handler_func = push_handler_func + if self.encoder is None: + self.encoder = self.connection_pool.get_encoder() + if self.encoder.decode_responses: + self.health_check_response = [ + ["pong", self.HEALTH_CHECK_MESSAGE], + self.HEALTH_CHECK_MESSAGE, + ] + else: + self.health_check_response = [ + [b"pong", self.encoder.encode(self.HEALTH_CHECK_MESSAGE)], + self.encoder.encode(self.HEALTH_CHECK_MESSAGE), + ] + if self.push_handler_func is None: + _set_info_logger() + self.channels = {} + self.pending_unsubscribe_channels = set() + self.patterns = {} + self.pending_unsubscribe_patterns = set() + self._lock = asyncio.Lock() + + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc_value, traceback): + await self.aclose() + + def __del__(self): + if self.connection: + self.connection._deregister_connect_callback(self.on_connect) + + async def aclose(self): + # In case a connection property does not yet exist + # (due to a crash earlier in the Redis() constructor), return + # immediately as there is nothing to clean-up. + if not hasattr(self, "connection"): + return + async with self._lock: + if self.connection: + await self.connection.disconnect() + self.connection._deregister_connect_callback(self.on_connect) + await self.connection_pool.release(self.connection) + self.connection = None + self.channels = {} + self.pending_unsubscribe_channels = set() + self.patterns = {} + self.pending_unsubscribe_patterns = set() + + @deprecated_function(version="5.0.0", reason="Use aclose() instead", name="close") + async def close(self) -> None: + """Alias for aclose(), for backwards compatibility""" + await self.aclose() + + @deprecated_function(version="5.0.0", reason="Use aclose() instead", name="reset") + async def reset(self) -> None: + """Alias for aclose(), for backwards compatibility""" + await self.aclose() + + async def on_connect(self, connection: Connection): + """Re-subscribe to any channels and patterns previously subscribed to""" + # NOTE: for python3, we can't pass bytestrings as keyword arguments + # so we need to decode channel/pattern names back to unicode strings + # before passing them to [p]subscribe. + self.pending_unsubscribe_channels.clear() + self.pending_unsubscribe_patterns.clear() + if self.channels: + channels = {} + for k, v in self.channels.items(): + channels[self.encoder.decode(k, force=True)] = v + await self.subscribe(**channels) + if self.patterns: + patterns = {} + for k, v in self.patterns.items(): + patterns[self.encoder.decode(k, force=True)] = v + await self.psubscribe(**patterns) + + @property + def subscribed(self): + """Indicates if there are subscriptions to any channels or patterns""" + return bool(self.channels or self.patterns) + + async def execute_command(self, *args: EncodableT): + """Execute a publish/subscribe command""" + + # NOTE: don't parse the response in this function -- it could pull a + # legitimate message off the stack if the connection is already + # subscribed to one or more channels + + await self.connect() + connection = self.connection + kwargs = {"check_health": not self.subscribed} + await self._execute(connection, connection.send_command, *args, **kwargs) + + async def connect(self): + """ + Ensure that the PubSub is connected + """ + if self.connection is None: + self.connection = await self.connection_pool.get_connection( + "pubsub", self.shard_hint + ) + # register a callback that re-subscribes to any channels we + # were listening to when we were disconnected + self.connection._register_connect_callback(self.on_connect) + else: + await self.connection.connect() + if self.push_handler_func is not None and not HIREDIS_AVAILABLE: + self.connection._parser.set_push_handler(self.push_handler_func) + + async def _disconnect_raise_connect(self, conn, error): + """ + Close the connection and raise an exception + if retry_on_timeout is not set or the error + is not a TimeoutError. Otherwise, try to reconnect + """ + await conn.disconnect() + if not (conn.retry_on_timeout and isinstance(error, TimeoutError)): + raise error + await conn.connect() + + async def _execute(self, conn, command, *args, **kwargs): + """ + Connect manually upon disconnection. If the Redis server is down, + this will fail and raise a ConnectionError as desired. + After reconnection, the ``on_connect`` callback should have been + called by the # connection to resubscribe us to any channels and + patterns we were previously listening to + """ + return await conn.retry.call_with_retry( + lambda: command(*args, **kwargs), + lambda error: self._disconnect_raise_connect(conn, error), + ) + + async def parse_response(self, block: bool = True, timeout: float = 0): + """Parse the response from a publish/subscribe command""" + conn = self.connection + if conn is None: + raise RuntimeError( + "pubsub connection not set: " + "did you forget to call subscribe() or psubscribe()?" + ) + + await self.check_health() + + if not conn.is_connected: + await conn.connect() + + read_timeout = None if block else timeout + response = await self._execute( + conn, + conn.read_response, + timeout=read_timeout, + disconnect_on_error=False, + push_request=True, + ) + + if conn.health_check_interval and response in self.health_check_response: + # ignore the health check message as user might not expect it + return None + return response + + async def check_health(self): + conn = self.connection + if conn is None: + raise RuntimeError( + "pubsub connection not set: " + "did you forget to call subscribe() or psubscribe()?" + ) + + if ( + conn.health_check_interval + and asyncio.get_running_loop().time() > conn.next_health_check + ): + await conn.send_command( + "PING", self.HEALTH_CHECK_MESSAGE, check_health=False + ) + + def _normalize_keys(self, data: _NormalizeKeysT) -> _NormalizeKeysT: + """ + normalize channel/pattern names to be either bytes or strings + based on whether responses are automatically decoded. this saves us + from coercing the value for each message coming in. + """ + encode = self.encoder.encode + decode = self.encoder.decode + return {decode(encode(k)): v for k, v in data.items()} # type: ignore[return-value] # noqa: E501 + + async def psubscribe(self, *args: ChannelT, **kwargs: PubSubHandler): + """ + Subscribe to channel patterns. Patterns supplied as keyword arguments + expect a pattern name as the key and a callable as the value. A + pattern's callable will be invoked automatically when a message is + received on that pattern rather than producing a message via + ``listen()``. + """ + parsed_args = list_or_args((args[0],), args[1:]) if args else args + new_patterns: Dict[ChannelT, PubSubHandler] = dict.fromkeys(parsed_args) + # Mypy bug: https://github.com/python/mypy/issues/10970 + new_patterns.update(kwargs) # type: ignore[arg-type] + ret_val = await self.execute_command("PSUBSCRIBE", *new_patterns.keys()) + # update the patterns dict AFTER we send the command. we don't want to + # subscribe twice to these patterns, once for the command and again + # for the reconnection. + new_patterns = self._normalize_keys(new_patterns) + self.patterns.update(new_patterns) + self.pending_unsubscribe_patterns.difference_update(new_patterns) + return ret_val + + def punsubscribe(self, *args: ChannelT) -> Awaitable: + """ + Unsubscribe from the supplied patterns. If empty, unsubscribe from + all patterns. + """ + patterns: Iterable[ChannelT] + if args: + parsed_args = list_or_args((args[0],), args[1:]) + patterns = self._normalize_keys(dict.fromkeys(parsed_args)).keys() + else: + parsed_args = [] + patterns = self.patterns + self.pending_unsubscribe_patterns.update(patterns) + return self.execute_command("PUNSUBSCRIBE", *parsed_args) + + async def subscribe(self, *args: ChannelT, **kwargs: Callable): + """ + Subscribe to channels. Channels supplied as keyword arguments expect + a channel name as the key and a callable as the value. A channel's + callable will be invoked automatically when a message is received on + that channel rather than producing a message via ``listen()`` or + ``get_message()``. + """ + parsed_args = list_or_args((args[0],), args[1:]) if args else () + new_channels = dict.fromkeys(parsed_args) + # Mypy bug: https://github.com/python/mypy/issues/10970 + new_channels.update(kwargs) # type: ignore[arg-type] + ret_val = await self.execute_command("SUBSCRIBE", *new_channels.keys()) + # update the channels dict AFTER we send the command. we don't want to + # subscribe twice to these channels, once for the command and again + # for the reconnection. + new_channels = self._normalize_keys(new_channels) + self.channels.update(new_channels) + self.pending_unsubscribe_channels.difference_update(new_channels) + return ret_val + + def unsubscribe(self, *args) -> Awaitable: + """ + Unsubscribe from the supplied channels. If empty, unsubscribe from + all channels + """ + if args: + parsed_args = list_or_args(args[0], args[1:]) + channels = self._normalize_keys(dict.fromkeys(parsed_args)) + else: + parsed_args = [] + channels = self.channels + self.pending_unsubscribe_channels.update(channels) + return self.execute_command("UNSUBSCRIBE", *parsed_args) + + async def listen(self) -> AsyncIterator: + """Listen for messages on channels this client has been subscribed to""" + while self.subscribed: + response = await self.handle_message(await self.parse_response(block=True)) + if response is not None: + yield response + + async def get_message( + self, ignore_subscribe_messages: bool = False, timeout: Optional[float] = 0.0 + ): + """ + Get the next message if one is available, otherwise None. + + If timeout is specified, the system will wait for `timeout` seconds + before returning. Timeout should be specified as a floating point + number or None to wait indefinitely. + """ + response = await self.parse_response(block=(timeout is None), timeout=timeout) + if response: + return await self.handle_message(response, ignore_subscribe_messages) + return None + + def ping(self, message=None) -> Awaitable: + """ + Ping the Redis server + """ + args = ["PING", message] if message is not None else ["PING"] + return self.execute_command(*args) + + async def handle_message(self, response, ignore_subscribe_messages=False): + """ + Parses a pub/sub message. If the channel or pattern was subscribed to + with a message handler, the handler is invoked instead of a parsed + message being returned. + """ + if response is None: + return None + if isinstance(response, bytes): + response = [b"pong", response] if response != b"PONG" else [b"pong", b""] + message_type = str_if_bytes(response[0]) + if message_type == "pmessage": + message = { + "type": message_type, + "pattern": response[1], + "channel": response[2], + "data": response[3], + } + elif message_type == "pong": + message = { + "type": message_type, + "pattern": None, + "channel": None, + "data": response[1], + } + else: + message = { + "type": message_type, + "pattern": None, + "channel": response[1], + "data": response[2], + } + + # if this is an unsubscribe message, remove it from memory + if message_type in self.UNSUBSCRIBE_MESSAGE_TYPES: + if message_type == "punsubscribe": + pattern = response[1] + if pattern in self.pending_unsubscribe_patterns: + self.pending_unsubscribe_patterns.remove(pattern) + self.patterns.pop(pattern, None) + else: + channel = response[1] + if channel in self.pending_unsubscribe_channels: + self.pending_unsubscribe_channels.remove(channel) + self.channels.pop(channel, None) + + if message_type in self.PUBLISH_MESSAGE_TYPES: + # if there's a message handler, invoke it + if message_type == "pmessage": + handler = self.patterns.get(message["pattern"], None) + else: + handler = self.channels.get(message["channel"], None) + if handler: + if inspect.iscoroutinefunction(handler): + await handler(message) + else: + handler(message) + return None + elif message_type != "pong": + # this is a subscribe/unsubscribe message. ignore if we don't + # want them + if ignore_subscribe_messages or self.ignore_subscribe_messages: + return None + + return message + + async def run( + self, + *, + exception_handler: Optional["PSWorkerThreadExcHandlerT"] = None, + poll_timeout: float = 1.0, + ) -> None: + """Process pub/sub messages using registered callbacks. + + This is the equivalent of :py:meth:`redis.PubSub.run_in_thread` in + redis-py, but it is a coroutine. To launch it as a separate task, use + ``asyncio.create_task``: + + >>> task = asyncio.create_task(pubsub.run()) + + To shut it down, use asyncio cancellation: + + >>> task.cancel() + >>> await task + """ + for channel, handler in self.channels.items(): + if handler is None: + raise PubSubError(f"Channel: '{channel}' has no handler registered") + for pattern, handler in self.patterns.items(): + if handler is None: + raise PubSubError(f"Pattern: '{pattern}' has no handler registered") + + await self.connect() + while True: + try: + await self.get_message( + ignore_subscribe_messages=True, timeout=poll_timeout + ) + except asyncio.CancelledError: + raise + except BaseException as e: + if exception_handler is None: + raise + res = exception_handler(e, self) + if inspect.isawaitable(res): + await res + # Ensure that other tasks on the event loop get a chance to run + # if we didn't have to block for I/O anywhere. + await asyncio.sleep(0) + + +class PubsubWorkerExceptionHandler(Protocol): + def __call__(self, e: BaseException, pubsub: PubSub): + ... + + +class AsyncPubsubWorkerExceptionHandler(Protocol): + async def __call__(self, e: BaseException, pubsub: PubSub): + ... + + +PSWorkerThreadExcHandlerT = Union[ + PubsubWorkerExceptionHandler, AsyncPubsubWorkerExceptionHandler +] + + +CommandT = Tuple[Tuple[Union[str, bytes], ...], Mapping[str, Any]] +CommandStackT = List[CommandT] + + +class Pipeline(Redis): # lgtm [py/init-calls-subclass] + """ + Pipelines provide a way to transmit multiple commands to the Redis server + in one transmission. This is convenient for batch processing, such as + saving all the values in a list to Redis. + + All commands executed within a pipeline are wrapped with MULTI and EXEC + calls. This guarantees all commands executed in the pipeline will be + executed atomically. + + Any command raising an exception does *not* halt the execution of + subsequent commands in the pipeline. Instead, the exception is caught + and its instance is placed into the response list returned by execute(). + Code iterating over the response list should be able to deal with an + instance of an exception as a potential value. In general, these will be + ResponseError exceptions, such as those raised when issuing a command + on a key of a different datatype. + """ + + UNWATCH_COMMANDS = {"DISCARD", "EXEC", "UNWATCH"} + + def __init__( + self, + connection_pool: ConnectionPool, + response_callbacks: MutableMapping[Union[str, bytes], ResponseCallbackT], + transaction: bool, + shard_hint: Optional[str], + ): + self.connection_pool = connection_pool + self.connection = None + self.response_callbacks = response_callbacks + self.is_transaction = transaction + self.shard_hint = shard_hint + self.watching = False + self.command_stack: CommandStackT = [] + self.scripts: Set["Script"] = set() + self.explicit_transaction = False + + async def __aenter__(self: _RedisT) -> _RedisT: + return self + + async def __aexit__(self, exc_type, exc_value, traceback): + await self.reset() + + def __await__(self): + return self._async_self().__await__() + + _DEL_MESSAGE = "Unclosed Pipeline client" + + def __len__(self): + return len(self.command_stack) + + def __bool__(self): + """Pipeline instances should always evaluate to True""" + return True + + async def _async_self(self): + return self + + async def reset(self): + self.command_stack = [] + self.scripts = set() + # make sure to reset the connection state in the event that we were + # watching something + if self.watching and self.connection: + try: + # call this manually since our unwatch or + # immediate_execute_command methods can call reset() + await self.connection.send_command("UNWATCH") + await self.connection.read_response() + except ConnectionError: + # disconnect will also remove any previous WATCHes + if self.connection: + await self.connection.disconnect() + # clean up the other instance attributes + self.watching = False + self.explicit_transaction = False + # we can safely return the connection to the pool here since we're + # sure we're no longer WATCHing anything + if self.connection: + await self.connection_pool.release(self.connection) + self.connection = None + + async def aclose(self) -> None: + """Alias for reset(), a standard method name for cleanup""" + await self.reset() + + def multi(self): + """ + Start a transactional block of the pipeline after WATCH commands + are issued. End the transactional block with `execute`. + """ + if self.explicit_transaction: + raise RedisError("Cannot issue nested calls to MULTI") + if self.command_stack: + raise RedisError( + "Commands without an initial WATCH have already been issued" + ) + self.explicit_transaction = True + + def execute_command( + self, *args, **kwargs + ) -> Union["Pipeline", Awaitable["Pipeline"]]: + if (self.watching or args[0] == "WATCH") and not self.explicit_transaction: + return self.immediate_execute_command(*args, **kwargs) + return self.pipeline_execute_command(*args, **kwargs) + + async def _disconnect_reset_raise(self, conn, error): + """ + Close the connection, reset watching state and + raise an exception if we were watching, + retry_on_timeout is not set, + or the error is not a TimeoutError + """ + await conn.disconnect() + # if we were already watching a variable, the watch is no longer + # valid since this connection has died. raise a WatchError, which + # indicates the user should retry this transaction. + if self.watching: + await self.aclose() + raise WatchError( + "A ConnectionError occurred on while watching one or more keys" + ) + # if retry_on_timeout is not set, or the error is not + # a TimeoutError, raise it + if not (conn.retry_on_timeout and isinstance(error, TimeoutError)): + await self.aclose() + raise + + async def immediate_execute_command(self, *args, **options): + """ + Execute a command immediately, but don't auto-retry on a + ConnectionError if we're already WATCHing a variable. Used when + issuing WATCH or subsequent commands retrieving their values but before + MULTI is called. + """ + command_name = args[0] + conn = self.connection + # if this is the first call, we need a connection + if not conn: + conn = await self.connection_pool.get_connection( + command_name, self.shard_hint + ) + self.connection = conn + + return await conn.retry.call_with_retry( + lambda: self._send_command_parse_response( + conn, command_name, *args, **options + ), + lambda error: self._disconnect_reset_raise(conn, error), + ) + + def pipeline_execute_command(self, *args, **options): + """ + Stage a command to be executed when execute() is next called + + Returns the current Pipeline object back so commands can be + chained together, such as: + + pipe = pipe.set('foo', 'bar').incr('baz').decr('bang') + + At some other point, you can then run: pipe.execute(), + which will execute all commands queued in the pipe. + """ + self.command_stack.append((args, options)) + return self + + async def _execute_transaction( # noqa: C901 + self, connection: Connection, commands: CommandStackT, raise_on_error + ): + pre: CommandT = (("MULTI",), {}) + post: CommandT = (("EXEC",), {}) + cmds = (pre, *commands, post) + all_cmds = connection.pack_commands( + args for args, options in cmds if EMPTY_RESPONSE not in options + ) + await connection.send_packed_command(all_cmds) + errors = [] + + # parse off the response for MULTI + # NOTE: we need to handle ResponseErrors here and continue + # so that we read all the additional command messages from + # the socket + try: + await self.parse_response(connection, "_") + except ResponseError as err: + errors.append((0, err)) + + # and all the other commands + for i, command in enumerate(commands): + if EMPTY_RESPONSE in command[1]: + errors.append((i, command[1][EMPTY_RESPONSE])) + else: + try: + await self.parse_response(connection, "_") + except ResponseError as err: + self.annotate_exception(err, i + 1, command[0]) + errors.append((i, err)) + + # parse the EXEC. + try: + response = await self.parse_response(connection, "_") + except ExecAbortError as err: + if errors: + raise errors[0][1] from err + raise + + # EXEC clears any watched keys + self.watching = False + + if response is None: + raise WatchError("Watched variable changed.") from None + + # put any parse errors into the response + for i, e in errors: + response.insert(i, e) + + if len(response) != len(commands): + if self.connection: + await self.connection.disconnect() + raise ResponseError( + "Wrong number of response items from pipeline execution" + ) from None + + # find any errors in the response and raise if necessary + if raise_on_error: + self.raise_first_error(commands, response) + + # We have to run response callbacks manually + data = [] + for r, cmd in zip(response, commands): + if not isinstance(r, Exception): + args, options = cmd + command_name = args[0] + if command_name in self.response_callbacks: + r = self.response_callbacks[command_name](r, **options) + if inspect.isawaitable(r): + r = await r + data.append(r) + return data + + async def _execute_pipeline( + self, connection: Connection, commands: CommandStackT, raise_on_error: bool + ): + # build up all commands into a single request to increase network perf + all_cmds = connection.pack_commands([args for args, _ in commands]) + await connection.send_packed_command(all_cmds) + + response = [] + for args, options in commands: + try: + response.append( + await self.parse_response(connection, args[0], **options) + ) + except ResponseError as e: + response.append(e) + + if raise_on_error: + self.raise_first_error(commands, response) + return response + + def raise_first_error(self, commands: CommandStackT, response: Iterable[Any]): + for i, r in enumerate(response): + if isinstance(r, ResponseError): + self.annotate_exception(r, i + 1, commands[i][0]) + raise r + + def annotate_exception( + self, exception: Exception, number: int, command: Iterable[object] + ) -> None: + cmd = " ".join(map(safe_str, command)) + msg = f"Command # {number} ({cmd}) of pipeline caused error: {exception.args}" + exception.args = (msg,) + exception.args[1:] + + async def parse_response( + self, connection: Connection, command_name: Union[str, bytes], **options + ): + result = await super().parse_response(connection, command_name, **options) + if command_name in self.UNWATCH_COMMANDS: + self.watching = False + elif command_name == "WATCH": + self.watching = True + return result + + async def load_scripts(self): + # make sure all scripts that are about to be run on this pipeline exist + scripts = list(self.scripts) + immediate = self.immediate_execute_command + shas = [s.sha for s in scripts] + # we can't use the normal script_* methods because they would just + # get buffered in the pipeline. + exists = await immediate("SCRIPT EXISTS", *shas) + if not all(exists): + for s, exist in zip(scripts, exists): + if not exist: + s.sha = await immediate("SCRIPT LOAD", s.script) + + async def _disconnect_raise_reset(self, conn: Connection, error: Exception): + """ + Close the connection, raise an exception if we were watching, + and raise an exception if retry_on_timeout is not set, + or the error is not a TimeoutError + """ + await conn.disconnect() + # if we were watching a variable, the watch is no longer valid + # since this connection has died. raise a WatchError, which + # indicates the user should retry this transaction. + if self.watching: + raise WatchError( + "A ConnectionError occurred on while watching one or more keys" + ) + # if retry_on_timeout is not set, or the error is not + # a TimeoutError, raise it + if not (conn.retry_on_timeout and isinstance(error, TimeoutError)): + await self.reset() + raise + + async def execute(self, raise_on_error: bool = True): + """Execute all the commands in the current pipeline""" + stack = self.command_stack + if not stack and not self.watching: + return [] + if self.scripts: + await self.load_scripts() + if self.is_transaction or self.explicit_transaction: + execute = self._execute_transaction + else: + execute = self._execute_pipeline + + conn = self.connection + if not conn: + conn = await self.connection_pool.get_connection("MULTI", self.shard_hint) + # assign to self.connection so reset() releases the connection + # back to the pool after we're done + self.connection = conn + conn = cast(Connection, conn) + + try: + return await conn.retry.call_with_retry( + lambda: execute(conn, stack, raise_on_error), + lambda error: self._disconnect_raise_reset(conn, error), + ) + finally: + await self.reset() + + async def discard(self): + """Flushes all previously queued commands + See: https://redis.io/commands/DISCARD + """ + await self.execute_command("DISCARD") + + async def watch(self, *names: KeyT): + """Watches the values at keys ``names``""" + if self.explicit_transaction: + raise RedisError("Cannot issue a WATCH after a MULTI") + return await self.execute_command("WATCH", *names) + + async def unwatch(self): + """Unwatches all previously specified keys""" + return self.watching and await self.execute_command("UNWATCH") or True diff --git a/.venv/Lib/site-packages/redis/asyncio/cluster.py b/.venv/Lib/site-packages/redis/asyncio/cluster.py new file mode 100644 index 00000000..636144a9 --- /dev/null +++ b/.venv/Lib/site-packages/redis/asyncio/cluster.py @@ -0,0 +1,1620 @@ +import asyncio +import collections +import random +import socket +import warnings +from typing import ( + Any, + Callable, + Deque, + Dict, + Generator, + List, + Mapping, + Optional, + Tuple, + Type, + TypeVar, + Union, +) + +from redis._parsers import AsyncCommandsParser, Encoder +from redis._parsers.helpers import ( + _RedisCallbacks, + _RedisCallbacksRESP2, + _RedisCallbacksRESP3, +) +from redis.asyncio.client import ResponseCallbackT +from redis.asyncio.connection import Connection, DefaultParser, SSLConnection, parse_url +from redis.asyncio.lock import Lock +from redis.asyncio.retry import Retry +from redis.backoff import default_backoff +from redis.client import EMPTY_RESPONSE, NEVER_DECODE, AbstractRedis +from redis.cluster import ( + PIPELINE_BLOCKED_COMMANDS, + PRIMARY, + REPLICA, + SLOT_ID, + AbstractRedisCluster, + LoadBalancer, + block_pipeline_command, + get_node_name, + parse_cluster_slots, +) +from redis.commands import READ_COMMANDS, AsyncRedisClusterCommands +from redis.crc import REDIS_CLUSTER_HASH_SLOTS, key_slot +from redis.credentials import CredentialProvider +from redis.exceptions import ( + AskError, + BusyLoadingError, + ClusterCrossSlotError, + ClusterDownError, + ClusterError, + ConnectionError, + DataError, + MasterDownError, + MaxConnectionsError, + MovedError, + RedisClusterException, + ResponseError, + SlotNotCoveredError, + TimeoutError, + TryAgainError, +) +from redis.typing import AnyKeyT, EncodableT, KeyT +from redis.utils import ( + deprecated_function, + dict_merge, + get_lib_version, + safe_str, + str_if_bytes, +) + +TargetNodesT = TypeVar( + "TargetNodesT", str, "ClusterNode", List["ClusterNode"], Dict[Any, "ClusterNode"] +) + + +class ClusterParser(DefaultParser): + EXCEPTION_CLASSES = dict_merge( + DefaultParser.EXCEPTION_CLASSES, + { + "ASK": AskError, + "CLUSTERDOWN": ClusterDownError, + "CROSSSLOT": ClusterCrossSlotError, + "MASTERDOWN": MasterDownError, + "MOVED": MovedError, + "TRYAGAIN": TryAgainError, + }, + ) + + +class RedisCluster(AbstractRedis, AbstractRedisCluster, AsyncRedisClusterCommands): + """ + Create a new RedisCluster client. + + Pass one of parameters: + + - `host` & `port` + - `startup_nodes` + + | Use ``await`` :meth:`initialize` to find cluster nodes & create connections. + | Use ``await`` :meth:`close` to disconnect connections & close client. + + Many commands support the target_nodes kwarg. It can be one of the + :attr:`NODE_FLAGS`: + + - :attr:`PRIMARIES` + - :attr:`REPLICAS` + - :attr:`ALL_NODES` + - :attr:`RANDOM` + - :attr:`DEFAULT_NODE` + + Note: This client is not thread/process/fork safe. + + :param host: + | Can be used to point to a startup node + :param port: + | Port used if **host** is provided + :param startup_nodes: + | :class:`~.ClusterNode` to used as a startup node + :param require_full_coverage: + | When set to ``False``: the client will not require a full coverage of + the slots. However, if not all slots are covered, and at least one node + has ``cluster-require-full-coverage`` set to ``yes``, the server will throw + a :class:`~.ClusterDownError` for some key-based commands. + | When set to ``True``: all slots must be covered to construct the cluster + client. If not all slots are covered, :class:`~.RedisClusterException` will be + thrown. + | See: + https://redis.io/docs/manual/scaling/#redis-cluster-configuration-parameters + :param read_from_replicas: + | Enable read from replicas in READONLY mode. You can read possibly stale data. + When set to true, read commands will be assigned between the primary and + its replications in a Round-Robin manner. + :param reinitialize_steps: + | Specifies the number of MOVED errors that need to occur before reinitializing + the whole cluster topology. If a MOVED error occurs and the cluster does not + need to be reinitialized on this current error handling, only the MOVED slot + will be patched with the redirected node. + To reinitialize the cluster on every MOVED error, set reinitialize_steps to 1. + To avoid reinitializing the cluster on moved errors, set reinitialize_steps to + 0. + :param cluster_error_retry_attempts: + | Number of times to retry before raising an error when :class:`~.TimeoutError` + or :class:`~.ConnectionError` or :class:`~.ClusterDownError` are encountered + :param connection_error_retry_attempts: + | Number of times to retry before reinitializing when :class:`~.TimeoutError` + or :class:`~.ConnectionError` are encountered. + The default backoff strategy will be set if Retry object is not passed (see + default_backoff in backoff.py). To change it, pass a custom Retry object + using the "retry" keyword. + :param max_connections: + | Maximum number of connections per node. If there are no free connections & the + maximum number of connections are already created, a + :class:`~.MaxConnectionsError` is raised. This error may be retried as defined + by :attr:`connection_error_retry_attempts` + :param address_remap: + | An optional callable which, when provided with an internal network + address of a node, e.g. a `(host, port)` tuple, will return the address + where the node is reachable. This can be used to map the addresses at + which the nodes _think_ they are, to addresses at which a client may + reach them, such as when they sit behind a proxy. + + | Rest of the arguments will be passed to the + :class:`~redis.asyncio.connection.Connection` instances when created + + :raises RedisClusterException: + if any arguments are invalid or unknown. Eg: + + - `db` != 0 or None + - `path` argument for unix socket connection + - none of the `host`/`port` & `startup_nodes` were provided + + """ + + @classmethod + def from_url(cls, url: str, **kwargs: Any) -> "RedisCluster": + """ + Return a Redis client object configured from the given URL. + + For example:: + + redis://[[username]:[password]]@localhost:6379/0 + rediss://[[username]:[password]]@localhost:6379/0 + + Three URL schemes are supported: + + - `redis://` creates a TCP socket connection. See more at: + + - `rediss://` creates a SSL wrapped TCP socket connection. See more at: + + + The username, password, hostname, path and all querystring values are passed + through ``urllib.parse.unquote`` in order to replace any percent-encoded values + with their corresponding characters. + + All querystring options are cast to their appropriate Python types. Boolean + arguments can be specified with string values "True"/"False" or "Yes"/"No". + Values that cannot be properly cast cause a ``ValueError`` to be raised. Once + parsed, the querystring arguments and keyword arguments are passed to + :class:`~redis.asyncio.connection.Connection` when created. + In the case of conflicting arguments, querystring arguments are used. + """ + kwargs.update(parse_url(url)) + if kwargs.pop("connection_class", None) is SSLConnection: + kwargs["ssl"] = True + return cls(**kwargs) + + __slots__ = ( + "_initialize", + "_lock", + "cluster_error_retry_attempts", + "command_flags", + "commands_parser", + "connection_error_retry_attempts", + "connection_kwargs", + "encoder", + "node_flags", + "nodes_manager", + "read_from_replicas", + "reinitialize_counter", + "reinitialize_steps", + "response_callbacks", + "result_callbacks", + ) + + def __init__( + self, + host: Optional[str] = None, + port: Union[str, int] = 6379, + # Cluster related kwargs + startup_nodes: Optional[List["ClusterNode"]] = None, + require_full_coverage: bool = True, + read_from_replicas: bool = False, + reinitialize_steps: int = 5, + cluster_error_retry_attempts: int = 3, + connection_error_retry_attempts: int = 3, + max_connections: int = 2**31, + # Client related kwargs + db: Union[str, int] = 0, + path: Optional[str] = None, + credential_provider: Optional[CredentialProvider] = None, + username: Optional[str] = None, + password: Optional[str] = None, + client_name: Optional[str] = None, + lib_name: Optional[str] = "redis-py", + lib_version: Optional[str] = get_lib_version(), + # Encoding related kwargs + encoding: str = "utf-8", + encoding_errors: str = "strict", + decode_responses: bool = False, + # Connection related kwargs + health_check_interval: float = 0, + socket_connect_timeout: Optional[float] = None, + socket_keepalive: bool = False, + socket_keepalive_options: Optional[Mapping[int, Union[int, bytes]]] = None, + socket_timeout: Optional[float] = None, + retry: Optional["Retry"] = None, + retry_on_error: Optional[List[Type[Exception]]] = None, + # SSL related kwargs + ssl: bool = False, + ssl_ca_certs: Optional[str] = None, + ssl_ca_data: Optional[str] = None, + ssl_cert_reqs: str = "required", + ssl_certfile: Optional[str] = None, + ssl_check_hostname: bool = False, + ssl_keyfile: Optional[str] = None, + protocol: Optional[int] = 2, + address_remap: Optional[Callable[[str, int], Tuple[str, int]]] = None, + ) -> None: + if db: + raise RedisClusterException( + "Argument 'db' must be 0 or None in cluster mode" + ) + + if path: + raise RedisClusterException( + "Unix domain socket is not supported in cluster mode" + ) + + if (not host or not port) and not startup_nodes: + raise RedisClusterException( + "RedisCluster requires at least one node to discover the cluster.\n" + "Please provide one of the following or use RedisCluster.from_url:\n" + ' - host and port: RedisCluster(host="localhost", port=6379)\n' + " - startup_nodes: RedisCluster(startup_nodes=[" + 'ClusterNode("localhost", 6379), ClusterNode("localhost", 6380)])' + ) + + kwargs: Dict[str, Any] = { + "max_connections": max_connections, + "connection_class": Connection, + "parser_class": ClusterParser, + # Client related kwargs + "credential_provider": credential_provider, + "username": username, + "password": password, + "client_name": client_name, + "lib_name": lib_name, + "lib_version": lib_version, + # Encoding related kwargs + "encoding": encoding, + "encoding_errors": encoding_errors, + "decode_responses": decode_responses, + # Connection related kwargs + "health_check_interval": health_check_interval, + "socket_connect_timeout": socket_connect_timeout, + "socket_keepalive": socket_keepalive, + "socket_keepalive_options": socket_keepalive_options, + "socket_timeout": socket_timeout, + "retry": retry, + "protocol": protocol, + } + + if ssl: + # SSL related kwargs + kwargs.update( + { + "connection_class": SSLConnection, + "ssl_ca_certs": ssl_ca_certs, + "ssl_ca_data": ssl_ca_data, + "ssl_cert_reqs": ssl_cert_reqs, + "ssl_certfile": ssl_certfile, + "ssl_check_hostname": ssl_check_hostname, + "ssl_keyfile": ssl_keyfile, + } + ) + + if read_from_replicas: + # Call our on_connect function to configure READONLY mode + kwargs["redis_connect_func"] = self.on_connect + + self.retry = retry + if retry or retry_on_error or connection_error_retry_attempts > 0: + # Set a retry object for all cluster nodes + self.retry = retry or Retry( + default_backoff(), connection_error_retry_attempts + ) + if not retry_on_error: + # Default errors for retrying + retry_on_error = [ConnectionError, TimeoutError] + self.retry.update_supported_errors(retry_on_error) + kwargs.update({"retry": self.retry}) + + kwargs["response_callbacks"] = _RedisCallbacks.copy() + if kwargs.get("protocol") in ["3", 3]: + kwargs["response_callbacks"].update(_RedisCallbacksRESP3) + else: + kwargs["response_callbacks"].update(_RedisCallbacksRESP2) + self.connection_kwargs = kwargs + + if startup_nodes: + passed_nodes = [] + for node in startup_nodes: + passed_nodes.append( + ClusterNode(node.host, node.port, **self.connection_kwargs) + ) + startup_nodes = passed_nodes + else: + startup_nodes = [] + if host and port: + startup_nodes.append(ClusterNode(host, port, **self.connection_kwargs)) + + self.nodes_manager = NodesManager( + startup_nodes, + require_full_coverage, + kwargs, + address_remap=address_remap, + ) + self.encoder = Encoder(encoding, encoding_errors, decode_responses) + self.read_from_replicas = read_from_replicas + self.reinitialize_steps = reinitialize_steps + self.cluster_error_retry_attempts = cluster_error_retry_attempts + self.connection_error_retry_attempts = connection_error_retry_attempts + self.reinitialize_counter = 0 + self.commands_parser = AsyncCommandsParser() + self.node_flags = self.__class__.NODE_FLAGS.copy() + self.command_flags = self.__class__.COMMAND_FLAGS.copy() + self.response_callbacks = kwargs["response_callbacks"] + self.result_callbacks = self.__class__.RESULT_CALLBACKS.copy() + self.result_callbacks[ + "CLUSTER SLOTS" + ] = lambda cmd, res, **kwargs: parse_cluster_slots( + list(res.values())[0], **kwargs + ) + + self._initialize = True + self._lock: Optional[asyncio.Lock] = None + + async def initialize(self) -> "RedisCluster": + """Get all nodes from startup nodes & creates connections if not initialized.""" + if self._initialize: + if not self._lock: + self._lock = asyncio.Lock() + async with self._lock: + if self._initialize: + try: + await self.nodes_manager.initialize() + await self.commands_parser.initialize( + self.nodes_manager.default_node + ) + self._initialize = False + except BaseException: + await self.nodes_manager.aclose() + await self.nodes_manager.aclose("startup_nodes") + raise + return self + + async def aclose(self) -> None: + """Close all connections & client if initialized.""" + if not self._initialize: + if not self._lock: + self._lock = asyncio.Lock() + async with self._lock: + if not self._initialize: + self._initialize = True + await self.nodes_manager.aclose() + await self.nodes_manager.aclose("startup_nodes") + + @deprecated_function(version="5.0.0", reason="Use aclose() instead", name="close") + async def close(self) -> None: + """alias for aclose() for backwards compatibility""" + await self.aclose() + + async def __aenter__(self) -> "RedisCluster": + return await self.initialize() + + async def __aexit__(self, exc_type: None, exc_value: None, traceback: None) -> None: + await self.aclose() + + def __await__(self) -> Generator[Any, None, "RedisCluster"]: + return self.initialize().__await__() + + _DEL_MESSAGE = "Unclosed RedisCluster client" + + def __del__( + self, + _warn: Any = warnings.warn, + _grl: Any = asyncio.get_running_loop, + ) -> None: + if hasattr(self, "_initialize") and not self._initialize: + _warn(f"{self._DEL_MESSAGE} {self!r}", ResourceWarning, source=self) + try: + context = {"client": self, "message": self._DEL_MESSAGE} + _grl().call_exception_handler(context) + except RuntimeError: + pass + + async def on_connect(self, connection: Connection) -> None: + await connection.on_connect() + + # Sending READONLY command to server to configure connection as + # readonly. Since each cluster node may change its server type due + # to a failover, we should establish a READONLY connection + # regardless of the server type. If this is a primary connection, + # READONLY would not affect executing write commands. + await connection.send_command("READONLY") + if str_if_bytes(await connection.read_response()) != "OK": + raise ConnectionError("READONLY command failed") + + def get_nodes(self) -> List["ClusterNode"]: + """Get all nodes of the cluster.""" + return list(self.nodes_manager.nodes_cache.values()) + + def get_primaries(self) -> List["ClusterNode"]: + """Get the primary nodes of the cluster.""" + return self.nodes_manager.get_nodes_by_server_type(PRIMARY) + + def get_replicas(self) -> List["ClusterNode"]: + """Get the replica nodes of the cluster.""" + return self.nodes_manager.get_nodes_by_server_type(REPLICA) + + def get_random_node(self) -> "ClusterNode": + """Get a random node of the cluster.""" + return random.choice(list(self.nodes_manager.nodes_cache.values())) + + def get_default_node(self) -> "ClusterNode": + """Get the default node of the client.""" + return self.nodes_manager.default_node + + def set_default_node(self, node: "ClusterNode") -> None: + """ + Set the default node of the client. + + :raises DataError: if None is passed or node does not exist in cluster. + """ + if not node or not self.get_node(node_name=node.name): + raise DataError("The requested node does not exist in the cluster.") + + self.nodes_manager.default_node = node + + def get_node( + self, + host: Optional[str] = None, + port: Optional[int] = None, + node_name: Optional[str] = None, + ) -> Optional["ClusterNode"]: + """Get node by (host, port) or node_name.""" + return self.nodes_manager.get_node(host, port, node_name) + + def get_node_from_key( + self, key: str, replica: bool = False + ) -> Optional["ClusterNode"]: + """ + Get the cluster node corresponding to the provided key. + + :param key: + :param replica: + | Indicates if a replica should be returned + | + None will returned if no replica holds this key + + :raises SlotNotCoveredError: if the key is not covered by any slot. + """ + slot = self.keyslot(key) + slot_cache = self.nodes_manager.slots_cache.get(slot) + if not slot_cache: + raise SlotNotCoveredError(f'Slot "{slot}" is not covered by the cluster.') + + if replica: + if len(self.nodes_manager.slots_cache[slot]) < 2: + return None + node_idx = 1 + else: + node_idx = 0 + + return slot_cache[node_idx] + + def keyslot(self, key: EncodableT) -> int: + """ + Find the keyslot for a given key. + + See: https://redis.io/docs/manual/scaling/#redis-cluster-data-sharding + """ + return key_slot(self.encoder.encode(key)) + + def get_encoder(self) -> Encoder: + """Get the encoder object of the client.""" + return self.encoder + + def get_connection_kwargs(self) -> Dict[str, Optional[Any]]: + """Get the kwargs passed to :class:`~redis.asyncio.connection.Connection`.""" + return self.connection_kwargs + + def get_retry(self) -> Optional["Retry"]: + return self.retry + + def set_retry(self, retry: "Retry") -> None: + self.retry = retry + for node in self.get_nodes(): + node.connection_kwargs.update({"retry": retry}) + for conn in node._connections: + conn.retry = retry + + def set_response_callback(self, command: str, callback: ResponseCallbackT) -> None: + """Set a custom response callback.""" + self.response_callbacks[command] = callback + + async def _determine_nodes( + self, command: str, *args: Any, node_flag: Optional[str] = None + ) -> List["ClusterNode"]: + # Determine which nodes should be executed the command on. + # Returns a list of target nodes. + if not node_flag: + # get the nodes group for this command if it was predefined + node_flag = self.command_flags.get(command) + + if node_flag in self.node_flags: + if node_flag == self.__class__.DEFAULT_NODE: + # return the cluster's default node + return [self.nodes_manager.default_node] + if node_flag == self.__class__.PRIMARIES: + # return all primaries + return self.nodes_manager.get_nodes_by_server_type(PRIMARY) + if node_flag == self.__class__.REPLICAS: + # return all replicas + return self.nodes_manager.get_nodes_by_server_type(REPLICA) + if node_flag == self.__class__.ALL_NODES: + # return all nodes + return list(self.nodes_manager.nodes_cache.values()) + if node_flag == self.__class__.RANDOM: + # return a random node + return [random.choice(list(self.nodes_manager.nodes_cache.values()))] + + # get the node that holds the key's slot + return [ + self.nodes_manager.get_node_from_slot( + await self._determine_slot(command, *args), + self.read_from_replicas and command in READ_COMMANDS, + ) + ] + + async def _determine_slot(self, command: str, *args: Any) -> int: + if self.command_flags.get(command) == SLOT_ID: + # The command contains the slot ID + return int(args[0]) + + # Get the keys in the command + + # EVAL and EVALSHA are common enough that it's wasteful to go to the + # redis server to parse the keys. Besides, there is a bug in redis<7.0 + # where `self._get_command_keys()` fails anyway. So, we special case + # EVAL/EVALSHA. + # - issue: https://github.com/redis/redis/issues/9493 + # - fix: https://github.com/redis/redis/pull/9733 + if command.upper() in ("EVAL", "EVALSHA"): + # command syntax: EVAL "script body" num_keys ... + if len(args) < 2: + raise RedisClusterException( + f"Invalid args in command: {command, *args}" + ) + keys = args[2 : 2 + int(args[1])] + # if there are 0 keys, that means the script can be run on any node + # so we can just return a random slot + if not keys: + return random.randrange(0, REDIS_CLUSTER_HASH_SLOTS) + else: + keys = await self.commands_parser.get_keys(command, *args) + if not keys: + # FCALL can call a function with 0 keys, that means the function + # can be run on any node so we can just return a random slot + if command.upper() in ("FCALL", "FCALL_RO"): + return random.randrange(0, REDIS_CLUSTER_HASH_SLOTS) + raise RedisClusterException( + "No way to dispatch this command to Redis Cluster. " + "Missing key.\nYou can execute the command by specifying " + f"target nodes.\nCommand: {args}" + ) + + # single key command + if len(keys) == 1: + return self.keyslot(keys[0]) + + # multi-key command; we need to make sure all keys are mapped to + # the same slot + slots = {self.keyslot(key) for key in keys} + if len(slots) != 1: + raise RedisClusterException( + f"{command} - all keys must map to the same key slot" + ) + + return slots.pop() + + def _is_node_flag(self, target_nodes: Any) -> bool: + return isinstance(target_nodes, str) and target_nodes in self.node_flags + + def _parse_target_nodes(self, target_nodes: Any) -> List["ClusterNode"]: + if isinstance(target_nodes, list): + nodes = target_nodes + elif isinstance(target_nodes, ClusterNode): + # Supports passing a single ClusterNode as a variable + nodes = [target_nodes] + elif isinstance(target_nodes, dict): + # Supports dictionaries of the format {node_name: node}. + # It enables to execute commands with multi nodes as follows: + # rc.cluster_save_config(rc.get_primaries()) + nodes = list(target_nodes.values()) + else: + raise TypeError( + "target_nodes type can be one of the following: " + "node_flag (PRIMARIES, REPLICAS, RANDOM, ALL_NODES)," + "ClusterNode, list, or dict. " + f"The passed type is {type(target_nodes)}" + ) + return nodes + + async def execute_command(self, *args: EncodableT, **kwargs: Any) -> Any: + """ + Execute a raw command on the appropriate cluster node or target_nodes. + + It will retry the command as specified by :attr:`cluster_error_retry_attempts` & + then raise an exception. + + :param args: + | Raw command args + :param kwargs: + + - target_nodes: :attr:`NODE_FLAGS` or :class:`~.ClusterNode` + or List[:class:`~.ClusterNode`] or Dict[Any, :class:`~.ClusterNode`] + - Rest of the kwargs are passed to the Redis connection + + :raises RedisClusterException: if target_nodes is not provided & the command + can't be mapped to a slot + """ + command = args[0] + target_nodes = [] + target_nodes_specified = False + retry_attempts = self.cluster_error_retry_attempts + + passed_targets = kwargs.pop("target_nodes", None) + if passed_targets and not self._is_node_flag(passed_targets): + target_nodes = self._parse_target_nodes(passed_targets) + target_nodes_specified = True + retry_attempts = 0 + + # Add one for the first execution + execute_attempts = 1 + retry_attempts + for _ in range(execute_attempts): + if self._initialize: + await self.initialize() + if ( + len(target_nodes) == 1 + and target_nodes[0] == self.get_default_node() + ): + # Replace the default cluster node + self.replace_default_node() + try: + if not target_nodes_specified: + # Determine the nodes to execute the command on + target_nodes = await self._determine_nodes( + *args, node_flag=passed_targets + ) + if not target_nodes: + raise RedisClusterException( + f"No targets were found to execute {args} command on" + ) + + if len(target_nodes) == 1: + # Return the processed result + ret = await self._execute_command(target_nodes[0], *args, **kwargs) + if command in self.result_callbacks: + return self.result_callbacks[command]( + command, {target_nodes[0].name: ret}, **kwargs + ) + return ret + else: + keys = [node.name for node in target_nodes] + values = await asyncio.gather( + *( + asyncio.create_task( + self._execute_command(node, *args, **kwargs) + ) + for node in target_nodes + ) + ) + if command in self.result_callbacks: + return self.result_callbacks[command]( + command, dict(zip(keys, values)), **kwargs + ) + return dict(zip(keys, values)) + except Exception as e: + if retry_attempts > 0 and type(e) in self.__class__.ERRORS_ALLOW_RETRY: + # The nodes and slots cache were should be reinitialized. + # Try again with the new cluster setup. + retry_attempts -= 1 + continue + else: + # raise the exception + raise e + + async def _execute_command( + self, target_node: "ClusterNode", *args: Union[KeyT, EncodableT], **kwargs: Any + ) -> Any: + asking = moved = False + redirect_addr = None + ttl = self.RedisClusterRequestTTL + + while ttl > 0: + ttl -= 1 + try: + if asking: + target_node = self.get_node(node_name=redirect_addr) + await target_node.execute_command("ASKING") + asking = False + elif moved: + # MOVED occurred and the slots cache was updated, + # refresh the target node + slot = await self._determine_slot(*args) + target_node = self.nodes_manager.get_node_from_slot( + slot, self.read_from_replicas and args[0] in READ_COMMANDS + ) + moved = False + + return await target_node.execute_command(*args, **kwargs) + except (BusyLoadingError, MaxConnectionsError): + raise + except (ConnectionError, TimeoutError): + # Connection retries are being handled in the node's + # Retry object. + # Remove the failed node from the startup nodes before we try + # to reinitialize the cluster + self.nodes_manager.startup_nodes.pop(target_node.name, None) + # Hard force of reinitialize of the node/slots setup + # and try again with the new setup + await self.aclose() + raise + except ClusterDownError: + # ClusterDownError can occur during a failover and to get + # self-healed, we will try to reinitialize the cluster layout + # and retry executing the command + await self.aclose() + await asyncio.sleep(0.25) + raise + except MovedError as e: + # First, we will try to patch the slots/nodes cache with the + # redirected node output and try again. If MovedError exceeds + # 'reinitialize_steps' number of times, we will force + # reinitializing the tables, and then try again. + # 'reinitialize_steps' counter will increase faster when + # the same client object is shared between multiple threads. To + # reduce the frequency you can set this variable in the + # RedisCluster constructor. + self.reinitialize_counter += 1 + if ( + self.reinitialize_steps + and self.reinitialize_counter % self.reinitialize_steps == 0 + ): + await self.aclose() + # Reset the counter + self.reinitialize_counter = 0 + else: + self.nodes_manager._moved_exception = e + moved = True + except AskError as e: + redirect_addr = get_node_name(host=e.host, port=e.port) + asking = True + except TryAgainError: + if ttl < self.RedisClusterRequestTTL / 2: + await asyncio.sleep(0.05) + + raise ClusterError("TTL exhausted.") + + def pipeline( + self, transaction: Optional[Any] = None, shard_hint: Optional[Any] = None + ) -> "ClusterPipeline": + """ + Create & return a new :class:`~.ClusterPipeline` object. + + Cluster implementation of pipeline does not support transaction or shard_hint. + + :raises RedisClusterException: if transaction or shard_hint are truthy values + """ + if shard_hint: + raise RedisClusterException("shard_hint is deprecated in cluster mode") + + if transaction: + raise RedisClusterException("transaction is deprecated in cluster mode") + + return ClusterPipeline(self) + + def lock( + self, + name: KeyT, + timeout: Optional[float] = None, + sleep: float = 0.1, + blocking: bool = True, + blocking_timeout: Optional[float] = None, + lock_class: Optional[Type[Lock]] = None, + thread_local: bool = True, + ) -> Lock: + """ + Return a new Lock object using key ``name`` that mimics + the behavior of threading.Lock. + + If specified, ``timeout`` indicates a maximum life for the lock. + By default, it will remain locked until release() is called. + + ``sleep`` indicates the amount of time to sleep per loop iteration + when the lock is in blocking mode and another client is currently + holding the lock. + + ``blocking`` indicates whether calling ``acquire`` should block until + the lock has been acquired or to fail immediately, causing ``acquire`` + to return False and the lock not being acquired. Defaults to True. + Note this value can be overridden by passing a ``blocking`` + argument to ``acquire``. + + ``blocking_timeout`` indicates the maximum amount of time in seconds to + spend trying to acquire the lock. A value of ``None`` indicates + continue trying forever. ``blocking_timeout`` can be specified as a + float or integer, both representing the number of seconds to wait. + + ``lock_class`` forces the specified lock implementation. Note that as + of redis-py 3.0, the only lock class we implement is ``Lock`` (which is + a Lua-based lock). So, it's unlikely you'll need this parameter, unless + you have created your own custom lock class. + + ``thread_local`` indicates whether the lock token is placed in + thread-local storage. By default, the token is placed in thread local + storage so that a thread only sees its token, not a token set by + another thread. Consider the following timeline: + + time: 0, thread-1 acquires `my-lock`, with a timeout of 5 seconds. + thread-1 sets the token to "abc" + time: 1, thread-2 blocks trying to acquire `my-lock` using the + Lock instance. + time: 5, thread-1 has not yet completed. redis expires the lock + key. + time: 5, thread-2 acquired `my-lock` now that it's available. + thread-2 sets the token to "xyz" + time: 6, thread-1 finishes its work and calls release(). if the + token is *not* stored in thread local storage, then + thread-1 would see the token value as "xyz" and would be + able to successfully release the thread-2's lock. + + In some use cases it's necessary to disable thread local storage. For + example, if you have code where one thread acquires a lock and passes + that lock instance to a worker thread to release later. If thread + local storage isn't disabled in this case, the worker thread won't see + the token set by the thread that acquired the lock. Our assumption + is that these cases aren't common and as such default to using + thread local storage.""" + if lock_class is None: + lock_class = Lock + return lock_class( + self, + name, + timeout=timeout, + sleep=sleep, + blocking=blocking, + blocking_timeout=blocking_timeout, + thread_local=thread_local, + ) + + +class ClusterNode: + """ + Create a new ClusterNode. + + Each ClusterNode manages multiple :class:`~redis.asyncio.connection.Connection` + objects for the (host, port). + """ + + __slots__ = ( + "_connections", + "_free", + "connection_class", + "connection_kwargs", + "host", + "max_connections", + "name", + "port", + "response_callbacks", + "server_type", + ) + + def __init__( + self, + host: str, + port: Union[str, int], + server_type: Optional[str] = None, + *, + max_connections: int = 2**31, + connection_class: Type[Connection] = Connection, + **connection_kwargs: Any, + ) -> None: + if host == "localhost": + host = socket.gethostbyname(host) + + connection_kwargs["host"] = host + connection_kwargs["port"] = port + self.host = host + self.port = port + self.name = get_node_name(host, port) + self.server_type = server_type + + self.max_connections = max_connections + self.connection_class = connection_class + self.connection_kwargs = connection_kwargs + self.response_callbacks = connection_kwargs.pop("response_callbacks", {}) + + self._connections: List[Connection] = [] + self._free: Deque[Connection] = collections.deque(maxlen=self.max_connections) + + def __repr__(self) -> str: + return ( + f"[host={self.host}, port={self.port}, " + f"name={self.name}, server_type={self.server_type}]" + ) + + def __eq__(self, obj: Any) -> bool: + return isinstance(obj, ClusterNode) and obj.name == self.name + + _DEL_MESSAGE = "Unclosed ClusterNode object" + + def __del__( + self, + _warn: Any = warnings.warn, + _grl: Any = asyncio.get_running_loop, + ) -> None: + for connection in self._connections: + if connection.is_connected: + _warn(f"{self._DEL_MESSAGE} {self!r}", ResourceWarning, source=self) + + try: + context = {"client": self, "message": self._DEL_MESSAGE} + _grl().call_exception_handler(context) + except RuntimeError: + pass + break + + async def disconnect(self) -> None: + ret = await asyncio.gather( + *( + asyncio.create_task(connection.disconnect()) + for connection in self._connections + ), + return_exceptions=True, + ) + exc = next((res for res in ret if isinstance(res, Exception)), None) + if exc: + raise exc + + def acquire_connection(self) -> Connection: + try: + return self._free.popleft() + except IndexError: + if len(self._connections) < self.max_connections: + connection = self.connection_class(**self.connection_kwargs) + self._connections.append(connection) + return connection + + raise MaxConnectionsError() + + async def parse_response( + self, connection: Connection, command: str, **kwargs: Any + ) -> Any: + try: + if NEVER_DECODE in kwargs: + response = await connection.read_response(disable_decoding=True) + kwargs.pop(NEVER_DECODE) + else: + response = await connection.read_response() + except ResponseError: + if EMPTY_RESPONSE in kwargs: + return kwargs[EMPTY_RESPONSE] + raise + + if EMPTY_RESPONSE in kwargs: + kwargs.pop(EMPTY_RESPONSE) + + # Return response + if command in self.response_callbacks: + return self.response_callbacks[command](response, **kwargs) + + return response + + async def execute_command(self, *args: Any, **kwargs: Any) -> Any: + # Acquire connection + connection = self.acquire_connection() + + # Execute command + await connection.send_packed_command(connection.pack_command(*args), False) + + # Read response + try: + return await self.parse_response(connection, args[0], **kwargs) + finally: + # Release connection + self._free.append(connection) + + async def execute_pipeline(self, commands: List["PipelineCommand"]) -> bool: + # Acquire connection + connection = self.acquire_connection() + + # Execute command + await connection.send_packed_command( + connection.pack_commands(cmd.args for cmd in commands), False + ) + + # Read responses + ret = False + for cmd in commands: + try: + cmd.result = await self.parse_response( + connection, cmd.args[0], **cmd.kwargs + ) + except Exception as e: + cmd.result = e + ret = True + + # Release connection + self._free.append(connection) + + return ret + + +class NodesManager: + __slots__ = ( + "_moved_exception", + "connection_kwargs", + "default_node", + "nodes_cache", + "read_load_balancer", + "require_full_coverage", + "slots_cache", + "startup_nodes", + "address_remap", + ) + + def __init__( + self, + startup_nodes: List["ClusterNode"], + require_full_coverage: bool, + connection_kwargs: Dict[str, Any], + address_remap: Optional[Callable[[str, int], Tuple[str, int]]] = None, + ) -> None: + self.startup_nodes = {node.name: node for node in startup_nodes} + self.require_full_coverage = require_full_coverage + self.connection_kwargs = connection_kwargs + self.address_remap = address_remap + + self.default_node: "ClusterNode" = None + self.nodes_cache: Dict[str, "ClusterNode"] = {} + self.slots_cache: Dict[int, List["ClusterNode"]] = {} + self.read_load_balancer = LoadBalancer() + self._moved_exception: MovedError = None + + def get_node( + self, + host: Optional[str] = None, + port: Optional[int] = None, + node_name: Optional[str] = None, + ) -> Optional["ClusterNode"]: + if host and port: + # the user passed host and port + if host == "localhost": + host = socket.gethostbyname(host) + return self.nodes_cache.get(get_node_name(host=host, port=port)) + elif node_name: + return self.nodes_cache.get(node_name) + else: + raise DataError( + "get_node requires one of the following: " + "1. node name " + "2. host and port" + ) + + def set_nodes( + self, + old: Dict[str, "ClusterNode"], + new: Dict[str, "ClusterNode"], + remove_old: bool = False, + ) -> None: + if remove_old: + for name in list(old.keys()): + if name not in new: + task = asyncio.create_task(old.pop(name).disconnect()) # noqa + + for name, node in new.items(): + if name in old: + if old[name] is node: + continue + task = asyncio.create_task(old[name].disconnect()) # noqa + old[name] = node + + def _update_moved_slots(self) -> None: + e = self._moved_exception + redirected_node = self.get_node(host=e.host, port=e.port) + if redirected_node: + # The node already exists + if redirected_node.server_type != PRIMARY: + # Update the node's server type + redirected_node.server_type = PRIMARY + else: + # This is a new node, we will add it to the nodes cache + redirected_node = ClusterNode( + e.host, e.port, PRIMARY, **self.connection_kwargs + ) + self.set_nodes(self.nodes_cache, {redirected_node.name: redirected_node}) + if redirected_node in self.slots_cache[e.slot_id]: + # The MOVED error resulted from a failover, and the new slot owner + # had previously been a replica. + old_primary = self.slots_cache[e.slot_id][0] + # Update the old primary to be a replica and add it to the end of + # the slot's node list + old_primary.server_type = REPLICA + self.slots_cache[e.slot_id].append(old_primary) + # Remove the old replica, which is now a primary, from the slot's + # node list + self.slots_cache[e.slot_id].remove(redirected_node) + # Override the old primary with the new one + self.slots_cache[e.slot_id][0] = redirected_node + if self.default_node == old_primary: + # Update the default node with the new primary + self.default_node = redirected_node + else: + # The new slot owner is a new server, or a server from a different + # shard. We need to remove all current nodes from the slot's list + # (including replications) and add just the new node. + self.slots_cache[e.slot_id] = [redirected_node] + # Reset moved_exception + self._moved_exception = None + + def get_node_from_slot( + self, slot: int, read_from_replicas: bool = False + ) -> "ClusterNode": + if self._moved_exception: + self._update_moved_slots() + + try: + if read_from_replicas: + # get the server index in a Round-Robin manner + primary_name = self.slots_cache[slot][0].name + node_idx = self.read_load_balancer.get_server_index( + primary_name, len(self.slots_cache[slot]) + ) + return self.slots_cache[slot][node_idx] + return self.slots_cache[slot][0] + except (IndexError, TypeError): + raise SlotNotCoveredError( + f'Slot "{slot}" not covered by the cluster. ' + f'"require_full_coverage={self.require_full_coverage}"' + ) + + def get_nodes_by_server_type(self, server_type: str) -> List["ClusterNode"]: + return [ + node + for node in self.nodes_cache.values() + if node.server_type == server_type + ] + + async def initialize(self) -> None: + self.read_load_balancer.reset() + tmp_nodes_cache: Dict[str, "ClusterNode"] = {} + tmp_slots: Dict[int, List["ClusterNode"]] = {} + disagreements = [] + startup_nodes_reachable = False + fully_covered = False + exception = None + for startup_node in self.startup_nodes.values(): + try: + # Make sure cluster mode is enabled on this node + if not (await startup_node.execute_command("INFO")).get( + "cluster_enabled" + ): + raise RedisClusterException( + "Cluster mode is not enabled on this node" + ) + cluster_slots = await startup_node.execute_command("CLUSTER SLOTS") + startup_nodes_reachable = True + except Exception as e: + # Try the next startup node. + # The exception is saved and raised only if we have no more nodes. + exception = e + continue + + # CLUSTER SLOTS command results in the following output: + # [[slot_section[from_slot,to_slot,master,replica1,...,replicaN]]] + # where each node contains the following list: [IP, port, node_id] + # Therefore, cluster_slots[0][2][0] will be the IP address of the + # primary node of the first slot section. + # If there's only one server in the cluster, its ``host`` is '' + # Fix it to the host in startup_nodes + if ( + len(cluster_slots) == 1 + and not cluster_slots[0][2][0] + and len(self.startup_nodes) == 1 + ): + cluster_slots[0][2][0] = startup_node.host + + for slot in cluster_slots: + for i in range(2, len(slot)): + slot[i] = [str_if_bytes(val) for val in slot[i]] + primary_node = slot[2] + host = primary_node[0] + if host == "": + host = startup_node.host + port = int(primary_node[1]) + host, port = self.remap_host_port(host, port) + + target_node = tmp_nodes_cache.get(get_node_name(host, port)) + if not target_node: + target_node = ClusterNode( + host, port, PRIMARY, **self.connection_kwargs + ) + # add this node to the nodes cache + tmp_nodes_cache[target_node.name] = target_node + + for i in range(int(slot[0]), int(slot[1]) + 1): + if i not in tmp_slots: + tmp_slots[i] = [] + tmp_slots[i].append(target_node) + replica_nodes = [slot[j] for j in range(3, len(slot))] + + for replica_node in replica_nodes: + host = replica_node[0] + port = replica_node[1] + host, port = self.remap_host_port(host, port) + + target_replica_node = tmp_nodes_cache.get( + get_node_name(host, port) + ) + if not target_replica_node: + target_replica_node = ClusterNode( + host, port, REPLICA, **self.connection_kwargs + ) + tmp_slots[i].append(target_replica_node) + # add this node to the nodes cache + tmp_nodes_cache[ + target_replica_node.name + ] = target_replica_node + else: + # Validate that 2 nodes want to use the same slot cache + # setup + tmp_slot = tmp_slots[i][0] + if tmp_slot.name != target_node.name: + disagreements.append( + f"{tmp_slot.name} vs {target_node.name} on slot: {i}" + ) + + if len(disagreements) > 5: + raise RedisClusterException( + f"startup_nodes could not agree on a valid " + f'slots cache: {", ".join(disagreements)}' + ) + + # Validate if all slots are covered or if we should try next startup node + fully_covered = True + for i in range(REDIS_CLUSTER_HASH_SLOTS): + if i not in tmp_slots: + fully_covered = False + break + if fully_covered: + break + + if not startup_nodes_reachable: + raise RedisClusterException( + f"Redis Cluster cannot be connected. Please provide at least " + f"one reachable node: {str(exception)}" + ) from exception + + # Check if the slots are not fully covered + if not fully_covered and self.require_full_coverage: + # Despite the requirement that the slots be covered, there + # isn't a full coverage + raise RedisClusterException( + f"All slots are not covered after query all startup_nodes. " + f"{len(tmp_slots)} of {REDIS_CLUSTER_HASH_SLOTS} " + f"covered..." + ) + + # Set the tmp variables to the real variables + self.slots_cache = tmp_slots + self.set_nodes(self.nodes_cache, tmp_nodes_cache, remove_old=True) + # Populate the startup nodes with all discovered nodes + self.set_nodes(self.startup_nodes, self.nodes_cache, remove_old=True) + + # Set the default node + self.default_node = self.get_nodes_by_server_type(PRIMARY)[0] + # If initialize was called after a MovedError, clear it + self._moved_exception = None + + async def aclose(self, attr: str = "nodes_cache") -> None: + self.default_node = None + await asyncio.gather( + *( + asyncio.create_task(node.disconnect()) + for node in getattr(self, attr).values() + ) + ) + + def remap_host_port(self, host: str, port: int) -> Tuple[str, int]: + """ + Remap the host and port returned from the cluster to a different + internal value. Useful if the client is not connecting directly + to the cluster. + """ + if self.address_remap: + return self.address_remap((host, port)) + return host, port + + +class ClusterPipeline(AbstractRedis, AbstractRedisCluster, AsyncRedisClusterCommands): + """ + Create a new ClusterPipeline object. + + Usage:: + + result = await ( + rc.pipeline() + .set("A", 1) + .get("A") + .hset("K", "F", "V") + .hgetall("K") + .mset_nonatomic({"A": 2, "B": 3}) + .get("A") + .get("B") + .delete("A", "B", "K") + .execute() + ) + # result = [True, "1", 1, {"F": "V"}, True, True, "2", "3", 1, 1, 1] + + Note: For commands `DELETE`, `EXISTS`, `TOUCH`, `UNLINK`, `mset_nonatomic`, which + are split across multiple nodes, you'll get multiple results for them in the array. + + Retryable errors: + - :class:`~.ClusterDownError` + - :class:`~.ConnectionError` + - :class:`~.TimeoutError` + + Redirection errors: + - :class:`~.TryAgainError` + - :class:`~.MovedError` + - :class:`~.AskError` + + :param client: + | Existing :class:`~.RedisCluster` client + """ + + __slots__ = ("_command_stack", "_client") + + def __init__(self, client: RedisCluster) -> None: + self._client = client + + self._command_stack: List["PipelineCommand"] = [] + + async def initialize(self) -> "ClusterPipeline": + if self._client._initialize: + await self._client.initialize() + self._command_stack = [] + return self + + async def __aenter__(self) -> "ClusterPipeline": + return await self.initialize() + + async def __aexit__(self, exc_type: None, exc_value: None, traceback: None) -> None: + self._command_stack = [] + + def __await__(self) -> Generator[Any, None, "ClusterPipeline"]: + return self.initialize().__await__() + + def __enter__(self) -> "ClusterPipeline": + self._command_stack = [] + return self + + def __exit__(self, exc_type: None, exc_value: None, traceback: None) -> None: + self._command_stack = [] + + def __bool__(self) -> bool: + return bool(self._command_stack) + + def __len__(self) -> int: + return len(self._command_stack) + + def execute_command( + self, *args: Union[KeyT, EncodableT], **kwargs: Any + ) -> "ClusterPipeline": + """ + Append a raw command to the pipeline. + + :param args: + | Raw command args + :param kwargs: + + - target_nodes: :attr:`NODE_FLAGS` or :class:`~.ClusterNode` + or List[:class:`~.ClusterNode`] or Dict[Any, :class:`~.ClusterNode`] + - Rest of the kwargs are passed to the Redis connection + """ + self._command_stack.append( + PipelineCommand(len(self._command_stack), *args, **kwargs) + ) + return self + + async def execute( + self, raise_on_error: bool = True, allow_redirections: bool = True + ) -> List[Any]: + """ + Execute the pipeline. + + It will retry the commands as specified by :attr:`cluster_error_retry_attempts` + & then raise an exception. + + :param raise_on_error: + | Raise the first error if there are any errors + :param allow_redirections: + | Whether to retry each failed command individually in case of redirection + errors + + :raises RedisClusterException: if target_nodes is not provided & the command + can't be mapped to a slot + """ + if not self._command_stack: + return [] + + try: + for _ in range(self._client.cluster_error_retry_attempts): + if self._client._initialize: + await self._client.initialize() + + try: + return await self._execute( + self._client, + self._command_stack, + raise_on_error=raise_on_error, + allow_redirections=allow_redirections, + ) + except BaseException as e: + if type(e) in self.__class__.ERRORS_ALLOW_RETRY: + # Try again with the new cluster setup. + exception = e + await self._client.aclose() + await asyncio.sleep(0.25) + else: + # All other errors should be raised. + raise + + # If it fails the configured number of times then raise an exception + raise exception + finally: + self._command_stack = [] + + async def _execute( + self, + client: "RedisCluster", + stack: List["PipelineCommand"], + raise_on_error: bool = True, + allow_redirections: bool = True, + ) -> List[Any]: + todo = [ + cmd for cmd in stack if not cmd.result or isinstance(cmd.result, Exception) + ] + + nodes = {} + for cmd in todo: + passed_targets = cmd.kwargs.pop("target_nodes", None) + if passed_targets and not client._is_node_flag(passed_targets): + target_nodes = client._parse_target_nodes(passed_targets) + else: + target_nodes = await client._determine_nodes( + *cmd.args, node_flag=passed_targets + ) + if not target_nodes: + raise RedisClusterException( + f"No targets were found to execute {cmd.args} command on" + ) + if len(target_nodes) > 1: + raise RedisClusterException(f"Too many targets for command {cmd.args}") + node = target_nodes[0] + if node.name not in nodes: + nodes[node.name] = (node, []) + nodes[node.name][1].append(cmd) + + errors = await asyncio.gather( + *( + asyncio.create_task(node[0].execute_pipeline(node[1])) + for node in nodes.values() + ) + ) + + if any(errors): + if allow_redirections: + # send each errored command individually + for cmd in todo: + if isinstance(cmd.result, (TryAgainError, MovedError, AskError)): + try: + cmd.result = await client.execute_command( + *cmd.args, **cmd.kwargs + ) + except Exception as e: + cmd.result = e + + if raise_on_error: + for cmd in todo: + result = cmd.result + if isinstance(result, Exception): + command = " ".join(map(safe_str, cmd.args)) + msg = ( + f"Command # {cmd.position + 1} ({command}) of pipeline " + f"caused error: {result.args}" + ) + result.args = (msg,) + result.args[1:] + raise result + + default_node = nodes.get(client.get_default_node().name) + if default_node is not None: + # This pipeline execution used the default node, check if we need + # to replace it. + # Note: when the error is raised we'll reset the default node in the + # caller function. + for cmd in default_node[1]: + # Check if it has a command that failed with a relevant + # exception + if type(cmd.result) in self.__class__.ERRORS_ALLOW_RETRY: + client.replace_default_node() + break + + return [cmd.result for cmd in stack] + + def _split_command_across_slots( + self, command: str, *keys: KeyT + ) -> "ClusterPipeline": + for slot_keys in self._client._partition_keys_by_slot(keys).values(): + self.execute_command(command, *slot_keys) + + return self + + def mset_nonatomic( + self, mapping: Mapping[AnyKeyT, EncodableT] + ) -> "ClusterPipeline": + encoder = self._client.encoder + + slots_pairs = {} + for pair in mapping.items(): + slot = key_slot(encoder.encode(pair[0])) + slots_pairs.setdefault(slot, []).extend(pair) + + for pairs in slots_pairs.values(): + self.execute_command("MSET", *pairs) + + return self + + +for command in PIPELINE_BLOCKED_COMMANDS: + command = command.replace(" ", "_").lower() + if command == "mset_nonatomic": + continue + + setattr(ClusterPipeline, command, block_pipeline_command(command)) + + +class PipelineCommand: + def __init__(self, position: int, *args: Any, **kwargs: Any) -> None: + self.args = args + self.kwargs = kwargs + self.position = position + self.result: Union[Any, Exception] = None + + def __repr__(self) -> str: + return f"[{self.position}] {self.args} ({self.kwargs})" diff --git a/.venv/Lib/site-packages/redis/asyncio/connection.py b/.venv/Lib/site-packages/redis/asyncio/connection.py new file mode 100644 index 00000000..65fa5864 --- /dev/null +++ b/.venv/Lib/site-packages/redis/asyncio/connection.py @@ -0,0 +1,1180 @@ +import asyncio +import copy +import enum +import inspect +import socket +import ssl +import sys +import weakref +from abc import abstractmethod +from itertools import chain +from types import MappingProxyType +from typing import ( + Any, + Callable, + Iterable, + List, + Mapping, + Optional, + Set, + Tuple, + Type, + TypeVar, + Union, +) +from urllib.parse import ParseResult, parse_qs, unquote, urlparse + +# the functionality is available in 3.11.x but has a major issue before +# 3.11.3. See https://github.com/redis/redis-py/issues/2633 +if sys.version_info >= (3, 11, 3): + from asyncio import timeout as async_timeout +else: + from async_timeout import timeout as async_timeout + +from redis.asyncio.retry import Retry +from redis.backoff import NoBackoff +from redis.compat import Protocol, TypedDict +from redis.connection import DEFAULT_RESP_VERSION +from redis.credentials import CredentialProvider, UsernamePasswordCredentialProvider +from redis.exceptions import ( + AuthenticationError, + AuthenticationWrongNumberOfArgsError, + ConnectionError, + DataError, + RedisError, + ResponseError, + TimeoutError, +) +from redis.typing import EncodableT +from redis.utils import HIREDIS_AVAILABLE, get_lib_version, str_if_bytes + +from .._parsers import ( + BaseParser, + Encoder, + _AsyncHiredisParser, + _AsyncRESP2Parser, + _AsyncRESP3Parser, +) + +SYM_STAR = b"*" +SYM_DOLLAR = b"$" +SYM_CRLF = b"\r\n" +SYM_LF = b"\n" +SYM_EMPTY = b"" + + +class _Sentinel(enum.Enum): + sentinel = object() + + +SENTINEL = _Sentinel.sentinel + + +DefaultParser: Type[Union[_AsyncRESP2Parser, _AsyncRESP3Parser, _AsyncHiredisParser]] +if HIREDIS_AVAILABLE: + DefaultParser = _AsyncHiredisParser +else: + DefaultParser = _AsyncRESP2Parser + + +class ConnectCallbackProtocol(Protocol): + def __call__(self, connection: "AbstractConnection"): + ... + + +class AsyncConnectCallbackProtocol(Protocol): + async def __call__(self, connection: "AbstractConnection"): + ... + + +ConnectCallbackT = Union[ConnectCallbackProtocol, AsyncConnectCallbackProtocol] + + +class AbstractConnection: + """Manages communication to and from a Redis server""" + + __slots__ = ( + "db", + "username", + "client_name", + "lib_name", + "lib_version", + "credential_provider", + "password", + "socket_timeout", + "socket_connect_timeout", + "redis_connect_func", + "retry_on_timeout", + "retry_on_error", + "health_check_interval", + "next_health_check", + "last_active_at", + "encoder", + "ssl_context", + "protocol", + "_reader", + "_writer", + "_parser", + "_connect_callbacks", + "_buffer_cutoff", + "_lock", + "_socket_read_size", + "__dict__", + ) + + def __init__( + self, + *, + db: Union[str, int] = 0, + password: Optional[str] = None, + socket_timeout: Optional[float] = None, + socket_connect_timeout: Optional[float] = None, + retry_on_timeout: bool = False, + retry_on_error: Union[list, _Sentinel] = SENTINEL, + encoding: str = "utf-8", + encoding_errors: str = "strict", + decode_responses: bool = False, + parser_class: Type[BaseParser] = DefaultParser, + socket_read_size: int = 65536, + health_check_interval: float = 0, + client_name: Optional[str] = None, + lib_name: Optional[str] = "redis-py", + lib_version: Optional[str] = get_lib_version(), + username: Optional[str] = None, + retry: Optional[Retry] = None, + redis_connect_func: Optional[ConnectCallbackT] = None, + encoder_class: Type[Encoder] = Encoder, + credential_provider: Optional[CredentialProvider] = None, + protocol: Optional[int] = 2, + ): + if (username or password) and credential_provider is not None: + raise DataError( + "'username' and 'password' cannot be passed along with 'credential_" + "provider'. Please provide only one of the following arguments: \n" + "1. 'password' and (optional) 'username'\n" + "2. 'credential_provider'" + ) + self.db = db + self.client_name = client_name + self.lib_name = lib_name + self.lib_version = lib_version + self.credential_provider = credential_provider + self.password = password + self.username = username + self.socket_timeout = socket_timeout + if socket_connect_timeout is None: + socket_connect_timeout = socket_timeout + self.socket_connect_timeout = socket_connect_timeout + self.retry_on_timeout = retry_on_timeout + if retry_on_error is SENTINEL: + retry_on_error = [] + if retry_on_timeout: + retry_on_error.append(TimeoutError) + retry_on_error.append(socket.timeout) + retry_on_error.append(asyncio.TimeoutError) + self.retry_on_error = retry_on_error + if retry or retry_on_error: + if not retry: + self.retry = Retry(NoBackoff(), 1) + else: + # deep-copy the Retry object as it is mutable + self.retry = copy.deepcopy(retry) + # Update the retry's supported errors with the specified errors + self.retry.update_supported_errors(retry_on_error) + else: + self.retry = Retry(NoBackoff(), 0) + self.health_check_interval = health_check_interval + self.next_health_check: float = -1 + self.encoder = encoder_class(encoding, encoding_errors, decode_responses) + self.redis_connect_func = redis_connect_func + self._reader: Optional[asyncio.StreamReader] = None + self._writer: Optional[asyncio.StreamWriter] = None + self._socket_read_size = socket_read_size + self.set_parser(parser_class) + self._connect_callbacks: List[weakref.WeakMethod[ConnectCallbackT]] = [] + self._buffer_cutoff = 6000 + try: + p = int(protocol) + except TypeError: + p = DEFAULT_RESP_VERSION + except ValueError: + raise ConnectionError("protocol must be an integer") + finally: + if p < 2 or p > 3: + raise ConnectionError("protocol must be either 2 or 3") + self.protocol = protocol + + def __repr__(self): + repr_args = ",".join((f"{k}={v}" for k, v in self.repr_pieces())) + return f"{self.__class__.__name__}<{repr_args}>" + + @abstractmethod + def repr_pieces(self): + pass + + @property + def is_connected(self): + return self._reader is not None and self._writer is not None + + def _register_connect_callback(self, callback): + wm = weakref.WeakMethod(callback) + if wm not in self._connect_callbacks: + self._connect_callbacks.append(wm) + + def _deregister_connect_callback(self, callback): + try: + self._connect_callbacks.remove(weakref.WeakMethod(callback)) + except ValueError: + pass + + def set_parser(self, parser_class: Type[BaseParser]) -> None: + """ + Creates a new instance of parser_class with socket size: + _socket_read_size and assigns it to the parser for the connection + :param parser_class: The required parser class + """ + self._parser = parser_class(socket_read_size=self._socket_read_size) + + async def connect(self): + """Connects to the Redis server if not already connected""" + if self.is_connected: + return + try: + await self.retry.call_with_retry( + lambda: self._connect(), lambda error: self.disconnect() + ) + except asyncio.CancelledError: + raise # in 3.7 and earlier, this is an Exception, not BaseException + except (socket.timeout, asyncio.TimeoutError): + raise TimeoutError("Timeout connecting to server") + except OSError as e: + raise ConnectionError(self._error_message(e)) + except Exception as exc: + raise ConnectionError(exc) from exc + + try: + if not self.redis_connect_func: + # Use the default on_connect function + await self.on_connect() + else: + # Use the passed function redis_connect_func + await self.redis_connect_func(self) if asyncio.iscoroutinefunction( + self.redis_connect_func + ) else self.redis_connect_func(self) + except RedisError: + # clean up after any error in on_connect + await self.disconnect() + raise + + # run any user callbacks. right now the only internal callback + # is for pubsub channel/pattern resubscription + # first, remove any dead weakrefs + self._connect_callbacks = [ref for ref in self._connect_callbacks if ref()] + for ref in self._connect_callbacks: + callback = ref() + task = callback(self) + if task and inspect.isawaitable(task): + await task + + @abstractmethod + async def _connect(self): + pass + + @abstractmethod + def _host_error(self) -> str: + pass + + @abstractmethod + def _error_message(self, exception: BaseException) -> str: + pass + + async def on_connect(self) -> None: + """Initialize the connection, authenticate and select a database""" + self._parser.on_connect(self) + parser = self._parser + + auth_args = None + # if credential provider or username and/or password are set, authenticate + if self.credential_provider or (self.username or self.password): + cred_provider = ( + self.credential_provider + or UsernamePasswordCredentialProvider(self.username, self.password) + ) + auth_args = cred_provider.get_credentials() + # if resp version is specified and we have auth args, + # we need to send them via HELLO + if auth_args and self.protocol not in [2, "2"]: + if isinstance(self._parser, _AsyncRESP2Parser): + self.set_parser(_AsyncRESP3Parser) + # update cluster exception classes + self._parser.EXCEPTION_CLASSES = parser.EXCEPTION_CLASSES + self._parser.on_connect(self) + if len(auth_args) == 1: + auth_args = ["default", auth_args[0]] + await self.send_command("HELLO", self.protocol, "AUTH", *auth_args) + response = await self.read_response() + if response.get(b"proto") != int(self.protocol) and response.get( + "proto" + ) != int(self.protocol): + raise ConnectionError("Invalid RESP version") + # avoid checking health here -- PING will fail if we try + # to check the health prior to the AUTH + elif auth_args: + await self.send_command("AUTH", *auth_args, check_health=False) + + try: + auth_response = await self.read_response() + except AuthenticationWrongNumberOfArgsError: + # a username and password were specified but the Redis + # server seems to be < 6.0.0 which expects a single password + # arg. retry auth with just the password. + # https://github.com/andymccurdy/redis-py/issues/1274 + await self.send_command("AUTH", auth_args[-1], check_health=False) + auth_response = await self.read_response() + + if str_if_bytes(auth_response) != "OK": + raise AuthenticationError("Invalid Username or Password") + + # if resp version is specified, switch to it + elif self.protocol not in [2, "2"]: + if isinstance(self._parser, _AsyncRESP2Parser): + self.set_parser(_AsyncRESP3Parser) + # update cluster exception classes + self._parser.EXCEPTION_CLASSES = parser.EXCEPTION_CLASSES + self._parser.on_connect(self) + await self.send_command("HELLO", self.protocol) + response = await self.read_response() + # if response.get(b"proto") != self.protocol and response.get( + # "proto" + # ) != self.protocol: + # raise ConnectionError("Invalid RESP version") + + # if a client_name is given, set it + if self.client_name: + await self.send_command("CLIENT", "SETNAME", self.client_name) + if str_if_bytes(await self.read_response()) != "OK": + raise ConnectionError("Error setting client name") + + # set the library name and version, pipeline for lower startup latency + if self.lib_name: + await self.send_command("CLIENT", "SETINFO", "LIB-NAME", self.lib_name) + if self.lib_version: + await self.send_command("CLIENT", "SETINFO", "LIB-VER", self.lib_version) + # if a database is specified, switch to it. Also pipeline this + if self.db: + await self.send_command("SELECT", self.db) + + # read responses from pipeline + for _ in (sent for sent in (self.lib_name, self.lib_version) if sent): + try: + await self.read_response() + except ResponseError: + pass + + if self.db: + if str_if_bytes(await self.read_response()) != "OK": + raise ConnectionError("Invalid Database") + + async def disconnect(self, nowait: bool = False) -> None: + """Disconnects from the Redis server""" + try: + async with async_timeout(self.socket_connect_timeout): + self._parser.on_disconnect() + if not self.is_connected: + return + try: + self._writer.close() # type: ignore[union-attr] + # wait for close to finish, except when handling errors and + # forcefully disconnecting. + if not nowait: + await self._writer.wait_closed() # type: ignore[union-attr] + except OSError: + pass + finally: + self._reader = None + self._writer = None + except asyncio.TimeoutError: + raise TimeoutError( + f"Timed out closing connection after {self.socket_connect_timeout}" + ) from None + + async def _send_ping(self): + """Send PING, expect PONG in return""" + await self.send_command("PING", check_health=False) + if str_if_bytes(await self.read_response()) != "PONG": + raise ConnectionError("Bad response from PING health check") + + async def _ping_failed(self, error): + """Function to call when PING fails""" + await self.disconnect() + + async def check_health(self): + """Check the health of the connection with a PING/PONG""" + if ( + self.health_check_interval + and asyncio.get_running_loop().time() > self.next_health_check + ): + await self.retry.call_with_retry(self._send_ping, self._ping_failed) + + async def _send_packed_command(self, command: Iterable[bytes]) -> None: + self._writer.writelines(command) + await self._writer.drain() + + async def send_packed_command( + self, command: Union[bytes, str, Iterable[bytes]], check_health: bool = True + ) -> None: + if not self.is_connected: + await self.connect() + elif check_health: + await self.check_health() + + try: + if isinstance(command, str): + command = command.encode() + if isinstance(command, bytes): + command = [command] + if self.socket_timeout: + await asyncio.wait_for( + self._send_packed_command(command), self.socket_timeout + ) + else: + self._writer.writelines(command) + await self._writer.drain() + except asyncio.TimeoutError: + await self.disconnect(nowait=True) + raise TimeoutError("Timeout writing to socket") from None + except OSError as e: + await self.disconnect(nowait=True) + if len(e.args) == 1: + err_no, errmsg = "UNKNOWN", e.args[0] + else: + err_no = e.args[0] + errmsg = e.args[1] + raise ConnectionError( + f"Error {err_no} while writing to socket. {errmsg}." + ) from e + except BaseException: + # BaseExceptions can be raised when a socket send operation is not + # finished, e.g. due to a timeout. Ideally, a caller could then re-try + # to send un-sent data. However, the send_packed_command() API + # does not support it so there is no point in keeping the connection open. + await self.disconnect(nowait=True) + raise + + async def send_command(self, *args: Any, **kwargs: Any) -> None: + """Pack and send a command to the Redis server""" + await self.send_packed_command( + self.pack_command(*args), check_health=kwargs.get("check_health", True) + ) + + async def can_read_destructive(self): + """Poll the socket to see if there's data that can be read.""" + try: + return await self._parser.can_read_destructive() + except OSError as e: + await self.disconnect(nowait=True) + host_error = self._host_error() + raise ConnectionError(f"Error while reading from {host_error}: {e.args}") + + async def read_response( + self, + disable_decoding: bool = False, + timeout: Optional[float] = None, + *, + disconnect_on_error: bool = True, + push_request: Optional[bool] = False, + ): + """Read the response from a previously sent command""" + read_timeout = timeout if timeout is not None else self.socket_timeout + host_error = self._host_error() + try: + if ( + read_timeout is not None + and self.protocol in ["3", 3] + and not HIREDIS_AVAILABLE + ): + async with async_timeout(read_timeout): + response = await self._parser.read_response( + disable_decoding=disable_decoding, push_request=push_request + ) + elif read_timeout is not None: + async with async_timeout(read_timeout): + response = await self._parser.read_response( + disable_decoding=disable_decoding + ) + elif self.protocol in ["3", 3] and not HIREDIS_AVAILABLE: + response = await self._parser.read_response( + disable_decoding=disable_decoding, push_request=push_request + ) + else: + response = await self._parser.read_response( + disable_decoding=disable_decoding + ) + except asyncio.TimeoutError: + if timeout is not None: + # user requested timeout, return None. Operation can be retried + return None + # it was a self.socket_timeout error. + if disconnect_on_error: + await self.disconnect(nowait=True) + raise TimeoutError(f"Timeout reading from {host_error}") + except OSError as e: + if disconnect_on_error: + await self.disconnect(nowait=True) + raise ConnectionError(f"Error while reading from {host_error} : {e.args}") + except BaseException: + # Also by default close in case of BaseException. A lot of code + # relies on this behaviour when doing Command/Response pairs. + # See #1128. + if disconnect_on_error: + await self.disconnect(nowait=True) + raise + + if self.health_check_interval: + next_time = asyncio.get_running_loop().time() + self.health_check_interval + self.next_health_check = next_time + + if isinstance(response, ResponseError): + raise response from None + return response + + def pack_command(self, *args: EncodableT) -> List[bytes]: + """Pack a series of arguments into the Redis protocol""" + output = [] + # the client might have included 1 or more literal arguments in + # the command name, e.g., 'CONFIG GET'. The Redis server expects these + # arguments to be sent separately, so split the first argument + # manually. These arguments should be bytestrings so that they are + # not encoded. + assert not isinstance(args[0], float) + if isinstance(args[0], str): + args = tuple(args[0].encode().split()) + args[1:] + elif b" " in args[0]: + args = tuple(args[0].split()) + args[1:] + + buff = SYM_EMPTY.join((SYM_STAR, str(len(args)).encode(), SYM_CRLF)) + + buffer_cutoff = self._buffer_cutoff + for arg in map(self.encoder.encode, args): + # to avoid large string mallocs, chunk the command into the + # output list if we're sending large values or memoryviews + arg_length = len(arg) + if ( + len(buff) > buffer_cutoff + or arg_length > buffer_cutoff + or isinstance(arg, memoryview) + ): + buff = SYM_EMPTY.join( + (buff, SYM_DOLLAR, str(arg_length).encode(), SYM_CRLF) + ) + output.append(buff) + output.append(arg) + buff = SYM_CRLF + else: + buff = SYM_EMPTY.join( + ( + buff, + SYM_DOLLAR, + str(arg_length).encode(), + SYM_CRLF, + arg, + SYM_CRLF, + ) + ) + output.append(buff) + return output + + def pack_commands(self, commands: Iterable[Iterable[EncodableT]]) -> List[bytes]: + """Pack multiple commands into the Redis protocol""" + output: List[bytes] = [] + pieces: List[bytes] = [] + buffer_length = 0 + buffer_cutoff = self._buffer_cutoff + + for cmd in commands: + for chunk in self.pack_command(*cmd): + chunklen = len(chunk) + if ( + buffer_length > buffer_cutoff + or chunklen > buffer_cutoff + or isinstance(chunk, memoryview) + ): + if pieces: + output.append(SYM_EMPTY.join(pieces)) + buffer_length = 0 + pieces = [] + + if chunklen > buffer_cutoff or isinstance(chunk, memoryview): + output.append(chunk) + else: + pieces.append(chunk) + buffer_length += chunklen + + if pieces: + output.append(SYM_EMPTY.join(pieces)) + return output + + +class Connection(AbstractConnection): + "Manages TCP communication to and from a Redis server" + + def __init__( + self, + *, + host: str = "localhost", + port: Union[str, int] = 6379, + socket_keepalive: bool = False, + socket_keepalive_options: Optional[Mapping[int, Union[int, bytes]]] = None, + socket_type: int = 0, + **kwargs, + ): + self.host = host + self.port = int(port) + self.socket_keepalive = socket_keepalive + self.socket_keepalive_options = socket_keepalive_options or {} + self.socket_type = socket_type + super().__init__(**kwargs) + + def repr_pieces(self): + pieces = [("host", self.host), ("port", self.port), ("db", self.db)] + if self.client_name: + pieces.append(("client_name", self.client_name)) + return pieces + + def _connection_arguments(self) -> Mapping: + return {"host": self.host, "port": self.port} + + async def _connect(self): + """Create a TCP socket connection""" + async with async_timeout(self.socket_connect_timeout): + reader, writer = await asyncio.open_connection( + **self._connection_arguments() + ) + self._reader = reader + self._writer = writer + sock = writer.transport.get_extra_info("socket") + if sock: + sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + try: + # TCP_KEEPALIVE + if self.socket_keepalive: + sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) + for k, v in self.socket_keepalive_options.items(): + sock.setsockopt(socket.SOL_TCP, k, v) + + except (OSError, TypeError): + # `socket_keepalive_options` might contain invalid options + # causing an error. Do not leave the connection open. + writer.close() + raise + + def _host_error(self) -> str: + return f"{self.host}:{self.port}" + + def _error_message(self, exception: BaseException) -> str: + # args for socket.error can either be (errno, "message") + # or just "message" + + host_error = self._host_error() + + if not exception.args: + # asyncio has a bug where on Connection reset by peer, the + # exception is not instanciated, so args is empty. This is the + # workaround. + # See: https://github.com/redis/redis-py/issues/2237 + # See: https://github.com/python/cpython/issues/94061 + return f"Error connecting to {host_error}. Connection reset by peer" + elif len(exception.args) == 1: + return f"Error connecting to {host_error}. {exception.args[0]}." + else: + return ( + f"Error {exception.args[0]} connecting to {host_error}. " + f"{exception.args[0]}." + ) + + +class SSLConnection(Connection): + """Manages SSL connections to and from the Redis server(s). + This class extends the Connection class, adding SSL functionality, and making + use of ssl.SSLContext (https://docs.python.org/3/library/ssl.html#ssl.SSLContext) + """ + + def __init__( + self, + ssl_keyfile: Optional[str] = None, + ssl_certfile: Optional[str] = None, + ssl_cert_reqs: str = "required", + ssl_ca_certs: Optional[str] = None, + ssl_ca_data: Optional[str] = None, + ssl_check_hostname: bool = False, + **kwargs, + ): + self.ssl_context: RedisSSLContext = RedisSSLContext( + keyfile=ssl_keyfile, + certfile=ssl_certfile, + cert_reqs=ssl_cert_reqs, + ca_certs=ssl_ca_certs, + ca_data=ssl_ca_data, + check_hostname=ssl_check_hostname, + ) + super().__init__(**kwargs) + + def _connection_arguments(self) -> Mapping: + kwargs = super()._connection_arguments() + kwargs["ssl"] = self.ssl_context.get() + return kwargs + + @property + def keyfile(self): + return self.ssl_context.keyfile + + @property + def certfile(self): + return self.ssl_context.certfile + + @property + def cert_reqs(self): + return self.ssl_context.cert_reqs + + @property + def ca_certs(self): + return self.ssl_context.ca_certs + + @property + def ca_data(self): + return self.ssl_context.ca_data + + @property + def check_hostname(self): + return self.ssl_context.check_hostname + + +class RedisSSLContext: + __slots__ = ( + "keyfile", + "certfile", + "cert_reqs", + "ca_certs", + "ca_data", + "context", + "check_hostname", + ) + + def __init__( + self, + keyfile: Optional[str] = None, + certfile: Optional[str] = None, + cert_reqs: Optional[str] = None, + ca_certs: Optional[str] = None, + ca_data: Optional[str] = None, + check_hostname: bool = False, + ): + self.keyfile = keyfile + self.certfile = certfile + if cert_reqs is None: + self.cert_reqs = ssl.CERT_NONE + elif isinstance(cert_reqs, str): + CERT_REQS = { + "none": ssl.CERT_NONE, + "optional": ssl.CERT_OPTIONAL, + "required": ssl.CERT_REQUIRED, + } + if cert_reqs not in CERT_REQS: + raise RedisError( + f"Invalid SSL Certificate Requirements Flag: {cert_reqs}" + ) + self.cert_reqs = CERT_REQS[cert_reqs] + self.ca_certs = ca_certs + self.ca_data = ca_data + self.check_hostname = check_hostname + self.context: Optional[ssl.SSLContext] = None + + def get(self) -> ssl.SSLContext: + if not self.context: + context = ssl.create_default_context() + context.check_hostname = self.check_hostname + context.verify_mode = self.cert_reqs + if self.certfile and self.keyfile: + context.load_cert_chain(certfile=self.certfile, keyfile=self.keyfile) + if self.ca_certs or self.ca_data: + context.load_verify_locations(cafile=self.ca_certs, cadata=self.ca_data) + self.context = context + return self.context + + +class UnixDomainSocketConnection(AbstractConnection): + "Manages UDS communication to and from a Redis server" + + def __init__(self, *, path: str = "", **kwargs): + self.path = path + super().__init__(**kwargs) + + def repr_pieces(self) -> Iterable[Tuple[str, Union[str, int]]]: + pieces = [("path", self.path), ("db", self.db)] + if self.client_name: + pieces.append(("client_name", self.client_name)) + return pieces + + async def _connect(self): + async with async_timeout(self.socket_connect_timeout): + reader, writer = await asyncio.open_unix_connection(path=self.path) + self._reader = reader + self._writer = writer + await self.on_connect() + + def _host_error(self) -> str: + return self.path + + def _error_message(self, exception: BaseException) -> str: + # args for socket.error can either be (errno, "message") + # or just "message" + host_error = self._host_error() + if len(exception.args) == 1: + return ( + f"Error connecting to unix socket: {host_error}. {exception.args[0]}." + ) + else: + return ( + f"Error {exception.args[0]} connecting to unix socket: " + f"{host_error}. {exception.args[1]}." + ) + + +FALSE_STRINGS = ("0", "F", "FALSE", "N", "NO") + + +def to_bool(value) -> Optional[bool]: + if value is None or value == "": + return None + if isinstance(value, str) and value.upper() in FALSE_STRINGS: + return False + return bool(value) + + +URL_QUERY_ARGUMENT_PARSERS: Mapping[str, Callable[..., object]] = MappingProxyType( + { + "db": int, + "socket_timeout": float, + "socket_connect_timeout": float, + "socket_keepalive": to_bool, + "retry_on_timeout": to_bool, + "max_connections": int, + "health_check_interval": int, + "ssl_check_hostname": to_bool, + } +) + + +class ConnectKwargs(TypedDict, total=False): + username: str + password: str + connection_class: Type[AbstractConnection] + host: str + port: int + db: int + path: str + + +def parse_url(url: str) -> ConnectKwargs: + parsed: ParseResult = urlparse(url) + kwargs: ConnectKwargs = {} + + for name, value_list in parse_qs(parsed.query).items(): + if value_list and len(value_list) > 0: + value = unquote(value_list[0]) + parser = URL_QUERY_ARGUMENT_PARSERS.get(name) + if parser: + try: + kwargs[name] = parser(value) + except (TypeError, ValueError): + raise ValueError(f"Invalid value for `{name}` in connection URL.") + else: + kwargs[name] = value + + if parsed.username: + kwargs["username"] = unquote(parsed.username) + if parsed.password: + kwargs["password"] = unquote(parsed.password) + + # We only support redis://, rediss:// and unix:// schemes. + if parsed.scheme == "unix": + if parsed.path: + kwargs["path"] = unquote(parsed.path) + kwargs["connection_class"] = UnixDomainSocketConnection + + elif parsed.scheme in ("redis", "rediss"): + if parsed.hostname: + kwargs["host"] = unquote(parsed.hostname) + if parsed.port: + kwargs["port"] = int(parsed.port) + + # If there's a path argument, use it as the db argument if a + # querystring value wasn't specified + if parsed.path and "db" not in kwargs: + try: + kwargs["db"] = int(unquote(parsed.path).replace("/", "")) + except (AttributeError, ValueError): + pass + + if parsed.scheme == "rediss": + kwargs["connection_class"] = SSLConnection + else: + valid_schemes = "redis://, rediss://, unix://" + raise ValueError( + f"Redis URL must specify one of the following schemes ({valid_schemes})" + ) + + return kwargs + + +_CP = TypeVar("_CP", bound="ConnectionPool") + + +class ConnectionPool: + """ + Create a connection pool. ``If max_connections`` is set, then this + object raises :py:class:`~redis.ConnectionError` when the pool's + limit is reached. + + By default, TCP connections are created unless ``connection_class`` + is specified. Use :py:class:`~redis.UnixDomainSocketConnection` for + unix sockets. + + Any additional keyword arguments are passed to the constructor of + ``connection_class``. + """ + + @classmethod + def from_url(cls: Type[_CP], url: str, **kwargs) -> _CP: + """ + Return a connection pool configured from the given URL. + + For example:: + + redis://[[username]:[password]]@localhost:6379/0 + rediss://[[username]:[password]]@localhost:6379/0 + unix://[username@]/path/to/socket.sock?db=0[&password=password] + + Three URL schemes are supported: + + - `redis://` creates a TCP socket connection. See more at: + + - `rediss://` creates a SSL wrapped TCP socket connection. See more at: + + - ``unix://``: creates a Unix Domain Socket connection. + + The username, password, hostname, path and all querystring values + are passed through urllib.parse.unquote in order to replace any + percent-encoded values with their corresponding characters. + + There are several ways to specify a database number. The first value + found will be used: + + 1. A ``db`` querystring option, e.g. redis://localhost?db=0 + + 2. If using the redis:// or rediss:// schemes, the path argument + of the url, e.g. redis://localhost/0 + + 3. A ``db`` keyword argument to this function. + + If none of these options are specified, the default db=0 is used. + + All querystring options are cast to their appropriate Python types. + Boolean arguments can be specified with string values "True"/"False" + or "Yes"/"No". Values that cannot be properly cast cause a + ``ValueError`` to be raised. Once parsed, the querystring arguments + and keyword arguments are passed to the ``ConnectionPool``'s + class initializer. In the case of conflicting arguments, querystring + arguments always win. + """ + url_options = parse_url(url) + kwargs.update(url_options) + return cls(**kwargs) + + def __init__( + self, + connection_class: Type[AbstractConnection] = Connection, + max_connections: Optional[int] = None, + **connection_kwargs, + ): + max_connections = max_connections or 2**31 + if not isinstance(max_connections, int) or max_connections < 0: + raise ValueError('"max_connections" must be a positive integer') + + self.connection_class = connection_class + self.connection_kwargs = connection_kwargs + self.max_connections = max_connections + + self._available_connections: List[AbstractConnection] = [] + self._in_use_connections: Set[AbstractConnection] = set() + self.encoder_class = self.connection_kwargs.get("encoder_class", Encoder) + + def __repr__(self): + return ( + f"{self.__class__.__name__}" + f"<{self.connection_class(**self.connection_kwargs)!r}>" + ) + + def reset(self): + self._available_connections = [] + self._in_use_connections = set() + + def can_get_connection(self) -> bool: + """Return True if a connection can be retrieved from the pool.""" + return ( + self._available_connections + or len(self._in_use_connections) < self.max_connections + ) + + async def get_connection(self, command_name, *keys, **options): + """Get a connection from the pool""" + try: + connection = self._available_connections.pop() + except IndexError: + if len(self._in_use_connections) >= self.max_connections: + raise ConnectionError("Too many connections") from None + connection = self.make_connection() + self._in_use_connections.add(connection) + + try: + await self.ensure_connection(connection) + except BaseException: + await self.release(connection) + raise + + return connection + + def get_encoder(self): + """Return an encoder based on encoding settings""" + kwargs = self.connection_kwargs + return self.encoder_class( + encoding=kwargs.get("encoding", "utf-8"), + encoding_errors=kwargs.get("encoding_errors", "strict"), + decode_responses=kwargs.get("decode_responses", False), + ) + + def make_connection(self): + """Create a new connection. Can be overridden by child classes.""" + return self.connection_class(**self.connection_kwargs) + + async def ensure_connection(self, connection: AbstractConnection): + """Ensure that the connection object is connected and valid""" + await connection.connect() + # connections that the pool provides should be ready to send + # a command. if not, the connection was either returned to the + # pool before all data has been read or the socket has been + # closed. either way, reconnect and verify everything is good. + try: + if await connection.can_read_destructive(): + raise ConnectionError("Connection has data") from None + except (ConnectionError, OSError): + await connection.disconnect() + await connection.connect() + if await connection.can_read_destructive(): + raise ConnectionError("Connection not ready") from None + + async def release(self, connection: AbstractConnection): + """Releases the connection back to the pool""" + # Connections should always be returned to the correct pool, + # not doing so is an error that will cause an exception here. + self._in_use_connections.remove(connection) + self._available_connections.append(connection) + + async def disconnect(self, inuse_connections: bool = True): + """ + Disconnects connections in the pool + + If ``inuse_connections`` is True, disconnect connections that are + current in use, potentially by other tasks. Otherwise only disconnect + connections that are idle in the pool. + """ + if inuse_connections: + connections: Iterable[AbstractConnection] = chain( + self._available_connections, self._in_use_connections + ) + else: + connections = self._available_connections + resp = await asyncio.gather( + *(connection.disconnect() for connection in connections), + return_exceptions=True, + ) + exc = next((r for r in resp if isinstance(r, BaseException)), None) + if exc: + raise exc + + async def aclose(self) -> None: + """Close the pool, disconnecting all connections""" + await self.disconnect() + + def set_retry(self, retry: "Retry") -> None: + for conn in self._available_connections: + conn.retry = retry + for conn in self._in_use_connections: + conn.retry = retry + + +class BlockingConnectionPool(ConnectionPool): + """ + A blocking connection pool:: + + >>> from redis.asyncio import Redis, BlockingConnectionPool + >>> client = Redis.from_pool(BlockingConnectionPool()) + + It performs the same function as the default + :py:class:`~redis.asyncio.ConnectionPool` implementation, in that, + it maintains a pool of reusable connections that can be shared by + multiple async redis clients. + + The difference is that, in the event that a client tries to get a + connection from the pool when all of connections are in use, rather than + raising a :py:class:`~redis.ConnectionError` (as the default + :py:class:`~redis.asyncio.ConnectionPool` implementation does), it + makes blocks the current `Task` for a specified number of seconds until + a connection becomes available. + + Use ``max_connections`` to increase / decrease the pool size:: + + >>> pool = BlockingConnectionPool(max_connections=10) + + Use ``timeout`` to tell it either how many seconds to wait for a connection + to become available, or to block forever: + + >>> # Block forever. + >>> pool = BlockingConnectionPool(timeout=None) + + >>> # Raise a ``ConnectionError`` after five seconds if a connection is + >>> # not available. + >>> pool = BlockingConnectionPool(timeout=5) + """ + + def __init__( + self, + max_connections: int = 50, + timeout: Optional[int] = 20, + connection_class: Type[AbstractConnection] = Connection, + queue_class: Type[asyncio.Queue] = asyncio.LifoQueue, # deprecated + **connection_kwargs, + ): + super().__init__( + connection_class=connection_class, + max_connections=max_connections, + **connection_kwargs, + ) + self._condition = asyncio.Condition() + self.timeout = timeout + + async def get_connection(self, command_name, *keys, **options): + """Gets a connection from the pool, blocking until one is available""" + try: + async with async_timeout(self.timeout): + async with self._condition: + await self._condition.wait_for(self.can_get_connection) + return await super().get_connection(command_name, *keys, **options) + except asyncio.TimeoutError as err: + raise ConnectionError("No connection available.") from err + + async def release(self, connection: AbstractConnection): + """Releases the connection back to the pool.""" + async with self._condition: + await super().release(connection) + self._condition.notify() diff --git a/.venv/Lib/site-packages/redis/asyncio/lock.py b/.venv/Lib/site-packages/redis/asyncio/lock.py new file mode 100644 index 00000000..e1d11a88 --- /dev/null +++ b/.venv/Lib/site-packages/redis/asyncio/lock.py @@ -0,0 +1,313 @@ +import asyncio +import threading +import uuid +from types import SimpleNamespace +from typing import TYPE_CHECKING, Awaitable, Optional, Union + +from redis.exceptions import LockError, LockNotOwnedError + +if TYPE_CHECKING: + from redis.asyncio import Redis, RedisCluster + + +class Lock: + """ + A shared, distributed Lock. Using Redis for locking allows the Lock + to be shared across processes and/or machines. + + It's left to the user to resolve deadlock issues and make sure + multiple clients play nicely together. + """ + + lua_release = None + lua_extend = None + lua_reacquire = None + + # KEYS[1] - lock name + # ARGV[1] - token + # return 1 if the lock was released, otherwise 0 + LUA_RELEASE_SCRIPT = """ + local token = redis.call('get', KEYS[1]) + if not token or token ~= ARGV[1] then + return 0 + end + redis.call('del', KEYS[1]) + return 1 + """ + + # KEYS[1] - lock name + # ARGV[1] - token + # ARGV[2] - additional milliseconds + # ARGV[3] - "0" if the additional time should be added to the lock's + # existing ttl or "1" if the existing ttl should be replaced + # return 1 if the locks time was extended, otherwise 0 + LUA_EXTEND_SCRIPT = """ + local token = redis.call('get', KEYS[1]) + if not token or token ~= ARGV[1] then + return 0 + end + local expiration = redis.call('pttl', KEYS[1]) + if not expiration then + expiration = 0 + end + if expiration < 0 then + return 0 + end + + local newttl = ARGV[2] + if ARGV[3] == "0" then + newttl = ARGV[2] + expiration + end + redis.call('pexpire', KEYS[1], newttl) + return 1 + """ + + # KEYS[1] - lock name + # ARGV[1] - token + # ARGV[2] - milliseconds + # return 1 if the locks time was reacquired, otherwise 0 + LUA_REACQUIRE_SCRIPT = """ + local token = redis.call('get', KEYS[1]) + if not token or token ~= ARGV[1] then + return 0 + end + redis.call('pexpire', KEYS[1], ARGV[2]) + return 1 + """ + + def __init__( + self, + redis: Union["Redis", "RedisCluster"], + name: Union[str, bytes, memoryview], + timeout: Optional[float] = None, + sleep: float = 0.1, + blocking: bool = True, + blocking_timeout: Optional[float] = None, + thread_local: bool = True, + ): + """ + Create a new Lock instance named ``name`` using the Redis client + supplied by ``redis``. + + ``timeout`` indicates a maximum life for the lock in seconds. + By default, it will remain locked until release() is called. + ``timeout`` can be specified as a float or integer, both representing + the number of seconds to wait. + + ``sleep`` indicates the amount of time to sleep in seconds per loop + iteration when the lock is in blocking mode and another client is + currently holding the lock. + + ``blocking`` indicates whether calling ``acquire`` should block until + the lock has been acquired or to fail immediately, causing ``acquire`` + to return False and the lock not being acquired. Defaults to True. + Note this value can be overridden by passing a ``blocking`` + argument to ``acquire``. + + ``blocking_timeout`` indicates the maximum amount of time in seconds to + spend trying to acquire the lock. A value of ``None`` indicates + continue trying forever. ``blocking_timeout`` can be specified as a + float or integer, both representing the number of seconds to wait. + + ``thread_local`` indicates whether the lock token is placed in + thread-local storage. By default, the token is placed in thread local + storage so that a thread only sees its token, not a token set by + another thread. Consider the following timeline: + + time: 0, thread-1 acquires `my-lock`, with a timeout of 5 seconds. + thread-1 sets the token to "abc" + time: 1, thread-2 blocks trying to acquire `my-lock` using the + Lock instance. + time: 5, thread-1 has not yet completed. redis expires the lock + key. + time: 5, thread-2 acquired `my-lock` now that it's available. + thread-2 sets the token to "xyz" + time: 6, thread-1 finishes its work and calls release(). if the + token is *not* stored in thread local storage, then + thread-1 would see the token value as "xyz" and would be + able to successfully release the thread-2's lock. + + In some use cases it's necessary to disable thread local storage. For + example, if you have code where one thread acquires a lock and passes + that lock instance to a worker thread to release later. If thread + local storage isn't disabled in this case, the worker thread won't see + the token set by the thread that acquired the lock. Our assumption + is that these cases aren't common and as such default to using + thread local storage. + """ + self.redis = redis + self.name = name + self.timeout = timeout + self.sleep = sleep + self.blocking = blocking + self.blocking_timeout = blocking_timeout + self.thread_local = bool(thread_local) + self.local = threading.local() if self.thread_local else SimpleNamespace() + self.local.token = None + self.register_scripts() + + def register_scripts(self): + cls = self.__class__ + client = self.redis + if cls.lua_release is None: + cls.lua_release = client.register_script(cls.LUA_RELEASE_SCRIPT) + if cls.lua_extend is None: + cls.lua_extend = client.register_script(cls.LUA_EXTEND_SCRIPT) + if cls.lua_reacquire is None: + cls.lua_reacquire = client.register_script(cls.LUA_REACQUIRE_SCRIPT) + + async def __aenter__(self): + if await self.acquire(): + return self + raise LockError("Unable to acquire lock within the time specified") + + async def __aexit__(self, exc_type, exc_value, traceback): + await self.release() + + async def acquire( + self, + blocking: Optional[bool] = None, + blocking_timeout: Optional[float] = None, + token: Optional[Union[str, bytes]] = None, + ): + """ + Use Redis to hold a shared, distributed lock named ``name``. + Returns True once the lock is acquired. + + If ``blocking`` is False, always return immediately. If the lock + was acquired, return True, otherwise return False. + + ``blocking_timeout`` specifies the maximum number of seconds to + wait trying to acquire the lock. + + ``token`` specifies the token value to be used. If provided, token + must be a bytes object or a string that can be encoded to a bytes + object with the default encoding. If a token isn't specified, a UUID + will be generated. + """ + sleep = self.sleep + if token is None: + token = uuid.uuid1().hex.encode() + else: + try: + encoder = self.redis.connection_pool.get_encoder() + except AttributeError: + # Cluster + encoder = self.redis.get_encoder() + token = encoder.encode(token) + if blocking is None: + blocking = self.blocking + if blocking_timeout is None: + blocking_timeout = self.blocking_timeout + stop_trying_at = None + if blocking_timeout is not None: + stop_trying_at = asyncio.get_running_loop().time() + blocking_timeout + while True: + if await self.do_acquire(token): + self.local.token = token + return True + if not blocking: + return False + next_try_at = asyncio.get_running_loop().time() + sleep + if stop_trying_at is not None and next_try_at > stop_trying_at: + return False + await asyncio.sleep(sleep) + + async def do_acquire(self, token: Union[str, bytes]) -> bool: + if self.timeout: + # convert to milliseconds + timeout = int(self.timeout * 1000) + else: + timeout = None + if await self.redis.set(self.name, token, nx=True, px=timeout): + return True + return False + + async def locked(self) -> bool: + """ + Returns True if this key is locked by any process, otherwise False. + """ + return await self.redis.get(self.name) is not None + + async def owned(self) -> bool: + """ + Returns True if this key is locked by this lock, otherwise False. + """ + stored_token = await self.redis.get(self.name) + # need to always compare bytes to bytes + # TODO: this can be simplified when the context manager is finished + if stored_token and not isinstance(stored_token, bytes): + try: + encoder = self.redis.connection_pool.get_encoder() + except AttributeError: + # Cluster + encoder = self.redis.get_encoder() + stored_token = encoder.encode(stored_token) + return self.local.token is not None and stored_token == self.local.token + + def release(self) -> Awaitable[None]: + """Releases the already acquired lock""" + expected_token = self.local.token + if expected_token is None: + raise LockError("Cannot release an unlocked lock") + self.local.token = None + return self.do_release(expected_token) + + async def do_release(self, expected_token: bytes) -> None: + if not bool( + await self.lua_release( + keys=[self.name], args=[expected_token], client=self.redis + ) + ): + raise LockNotOwnedError("Cannot release a lock that's no longer owned") + + def extend( + self, additional_time: float, replace_ttl: bool = False + ) -> Awaitable[bool]: + """ + Adds more time to an already acquired lock. + + ``additional_time`` can be specified as an integer or a float, both + representing the number of seconds to add. + + ``replace_ttl`` if False (the default), add `additional_time` to + the lock's existing ttl. If True, replace the lock's ttl with + `additional_time`. + """ + if self.local.token is None: + raise LockError("Cannot extend an unlocked lock") + if self.timeout is None: + raise LockError("Cannot extend a lock with no timeout") + return self.do_extend(additional_time, replace_ttl) + + async def do_extend(self, additional_time, replace_ttl) -> bool: + additional_time = int(additional_time * 1000) + if not bool( + await self.lua_extend( + keys=[self.name], + args=[self.local.token, additional_time, replace_ttl and "1" or "0"], + client=self.redis, + ) + ): + raise LockNotOwnedError("Cannot extend a lock that's no longer owned") + return True + + def reacquire(self) -> Awaitable[bool]: + """ + Resets a TTL of an already acquired lock back to a timeout value. + """ + if self.local.token is None: + raise LockError("Cannot reacquire an unlocked lock") + if self.timeout is None: + raise LockError("Cannot reacquire a lock with no timeout") + return self.do_reacquire() + + async def do_reacquire(self) -> bool: + timeout = int(self.timeout * 1000) + if not bool( + await self.lua_reacquire( + keys=[self.name], args=[self.local.token, timeout], client=self.redis + ) + ): + raise LockNotOwnedError("Cannot reacquire a lock that's no longer owned") + return True diff --git a/.venv/Lib/site-packages/redis/asyncio/retry.py b/.venv/Lib/site-packages/redis/asyncio/retry.py new file mode 100644 index 00000000..7c5e3b0e --- /dev/null +++ b/.venv/Lib/site-packages/redis/asyncio/retry.py @@ -0,0 +1,67 @@ +from asyncio import sleep +from typing import TYPE_CHECKING, Any, Awaitable, Callable, Tuple, Type, TypeVar + +from redis.exceptions import ConnectionError, RedisError, TimeoutError + +if TYPE_CHECKING: + from redis.backoff import AbstractBackoff + + +T = TypeVar("T") + + +class Retry: + """Retry a specific number of times after a failure""" + + __slots__ = "_backoff", "_retries", "_supported_errors" + + def __init__( + self, + backoff: "AbstractBackoff", + retries: int, + supported_errors: Tuple[Type[RedisError], ...] = ( + ConnectionError, + TimeoutError, + ), + ): + """ + Initialize a `Retry` object with a `Backoff` object + that retries a maximum of `retries` times. + `retries` can be negative to retry forever. + You can specify the types of supported errors which trigger + a retry with the `supported_errors` parameter. + """ + self._backoff = backoff + self._retries = retries + self._supported_errors = supported_errors + + def update_supported_errors(self, specified_errors: list): + """ + Updates the supported errors with the specified error types + """ + self._supported_errors = tuple( + set(self._supported_errors + tuple(specified_errors)) + ) + + async def call_with_retry( + self, do: Callable[[], Awaitable[T]], fail: Callable[[RedisError], Any] + ) -> T: + """ + Execute an operation that might fail and returns its result, or + raise the exception that was thrown depending on the `Backoff` object. + `do`: the operation to call. Expects no argument. + `fail`: the failure handler, expects the last error that was thrown + """ + self._backoff.reset() + failures = 0 + while True: + try: + return await do() + except self._supported_errors as error: + failures += 1 + await fail(error) + if self._retries >= 0 and failures > self._retries: + raise error + backoff = self._backoff.compute(failures) + if backoff > 0: + await sleep(backoff) diff --git a/.venv/Lib/site-packages/redis/asyncio/sentinel.py b/.venv/Lib/site-packages/redis/asyncio/sentinel.py new file mode 100644 index 00000000..6834fb19 --- /dev/null +++ b/.venv/Lib/site-packages/redis/asyncio/sentinel.py @@ -0,0 +1,375 @@ +import asyncio +import random +import weakref +from typing import AsyncIterator, Iterable, Mapping, Optional, Sequence, Tuple, Type + +from redis.asyncio.client import Redis +from redis.asyncio.connection import ( + Connection, + ConnectionPool, + EncodableT, + SSLConnection, +) +from redis.commands import AsyncSentinelCommands +from redis.exceptions import ConnectionError, ReadOnlyError, ResponseError, TimeoutError +from redis.utils import str_if_bytes + + +class MasterNotFoundError(ConnectionError): + pass + + +class SlaveNotFoundError(ConnectionError): + pass + + +class SentinelManagedConnection(Connection): + def __init__(self, **kwargs): + self.connection_pool = kwargs.pop("connection_pool") + super().__init__(**kwargs) + + def __repr__(self): + pool = self.connection_pool + s = f"{self.__class__.__name__}" + + async def connect_to(self, address): + self.host, self.port = address + await super().connect() + if self.connection_pool.check_connection: + await self.send_command("PING") + if str_if_bytes(await self.read_response()) != "PONG": + raise ConnectionError("PING failed") + + async def _connect_retry(self): + if self._reader: + return # already connected + if self.connection_pool.is_master: + await self.connect_to(await self.connection_pool.get_master_address()) + else: + async for slave in self.connection_pool.rotate_slaves(): + try: + return await self.connect_to(slave) + except ConnectionError: + continue + raise SlaveNotFoundError # Never be here + + async def connect(self): + return await self.retry.call_with_retry( + self._connect_retry, + lambda error: asyncio.sleep(0), + ) + + async def read_response( + self, + disable_decoding: bool = False, + timeout: Optional[float] = None, + *, + disconnect_on_error: Optional[float] = True, + push_request: Optional[bool] = False, + ): + try: + return await super().read_response( + disable_decoding=disable_decoding, + timeout=timeout, + disconnect_on_error=disconnect_on_error, + push_request=push_request, + ) + except ReadOnlyError: + if self.connection_pool.is_master: + # When talking to a master, a ReadOnlyError when likely + # indicates that the previous master that we're still connected + # to has been demoted to a slave and there's a new master. + # calling disconnect will force the connection to re-query + # sentinel during the next connect() attempt. + await self.disconnect() + raise ConnectionError("The previous master is now a slave") + raise + + +class SentinelManagedSSLConnection(SentinelManagedConnection, SSLConnection): + pass + + +class SentinelConnectionPool(ConnectionPool): + """ + Sentinel backed connection pool. + + If ``check_connection`` flag is set to True, SentinelManagedConnection + sends a PING command right after establishing the connection. + """ + + def __init__(self, service_name, sentinel_manager, **kwargs): + kwargs["connection_class"] = kwargs.get( + "connection_class", + SentinelManagedSSLConnection + if kwargs.pop("ssl", False) + else SentinelManagedConnection, + ) + self.is_master = kwargs.pop("is_master", True) + self.check_connection = kwargs.pop("check_connection", False) + super().__init__(**kwargs) + self.connection_kwargs["connection_pool"] = weakref.proxy(self) + self.service_name = service_name + self.sentinel_manager = sentinel_manager + self.master_address = None + self.slave_rr_counter = None + + def __repr__(self): + return ( + f"{self.__class__.__name__}" + f"" + ) + + def reset(self): + super().reset() + self.master_address = None + self.slave_rr_counter = None + + def owns_connection(self, connection: Connection): + check = not self.is_master or ( + self.is_master and self.master_address == (connection.host, connection.port) + ) + return check and super().owns_connection(connection) + + async def get_master_address(self): + master_address = await self.sentinel_manager.discover_master(self.service_name) + if self.is_master: + if self.master_address != master_address: + self.master_address = master_address + # disconnect any idle connections so that they reconnect + # to the new master the next time that they are used. + await self.disconnect(inuse_connections=False) + return master_address + + async def rotate_slaves(self) -> AsyncIterator: + """Round-robin slave balancer""" + slaves = await self.sentinel_manager.discover_slaves(self.service_name) + if slaves: + if self.slave_rr_counter is None: + self.slave_rr_counter = random.randint(0, len(slaves) - 1) + for _ in range(len(slaves)): + self.slave_rr_counter = (self.slave_rr_counter + 1) % len(slaves) + slave = slaves[self.slave_rr_counter] + yield slave + # Fallback to the master connection + try: + yield await self.get_master_address() + except MasterNotFoundError: + pass + raise SlaveNotFoundError(f"No slave found for {self.service_name!r}") + + +class Sentinel(AsyncSentinelCommands): + """ + Redis Sentinel cluster client + + >>> from redis.sentinel import Sentinel + >>> sentinel = Sentinel([('localhost', 26379)], socket_timeout=0.1) + >>> master = sentinel.master_for('mymaster', socket_timeout=0.1) + >>> await master.set('foo', 'bar') + >>> slave = sentinel.slave_for('mymaster', socket_timeout=0.1) + >>> await slave.get('foo') + b'bar' + + ``sentinels`` is a list of sentinel nodes. Each node is represented by + a pair (hostname, port). + + ``min_other_sentinels`` defined a minimum number of peers for a sentinel. + When querying a sentinel, if it doesn't meet this threshold, responses + from that sentinel won't be considered valid. + + ``sentinel_kwargs`` is a dictionary of connection arguments used when + connecting to sentinel instances. Any argument that can be passed to + a normal Redis connection can be specified here. If ``sentinel_kwargs`` is + not specified, any socket_timeout and socket_keepalive options specified + in ``connection_kwargs`` will be used. + + ``connection_kwargs`` are keyword arguments that will be used when + establishing a connection to a Redis server. + """ + + def __init__( + self, + sentinels, + min_other_sentinels=0, + sentinel_kwargs=None, + **connection_kwargs, + ): + # if sentinel_kwargs isn't defined, use the socket_* options from + # connection_kwargs + if sentinel_kwargs is None: + sentinel_kwargs = { + k: v for k, v in connection_kwargs.items() if k.startswith("socket_") + } + self.sentinel_kwargs = sentinel_kwargs + + self.sentinels = [ + Redis(host=hostname, port=port, **self.sentinel_kwargs) + for hostname, port in sentinels + ] + self.min_other_sentinels = min_other_sentinels + self.connection_kwargs = connection_kwargs + + async def execute_command(self, *args, **kwargs): + """ + Execute Sentinel command in sentinel nodes. + once - If set to True, then execute the resulting command on a single + node at random, rather than across the entire sentinel cluster. + """ + once = bool(kwargs.get("once", False)) + if "once" in kwargs.keys(): + kwargs.pop("once") + + if once: + await random.choice(self.sentinels).execute_command(*args, **kwargs) + else: + tasks = [ + asyncio.Task(sentinel.execute_command(*args, **kwargs)) + for sentinel in self.sentinels + ] + await asyncio.gather(*tasks) + return True + + def __repr__(self): + sentinel_addresses = [] + for sentinel in self.sentinels: + sentinel_addresses.append( + f"{sentinel.connection_pool.connection_kwargs['host']}:" + f"{sentinel.connection_pool.connection_kwargs['port']}" + ) + return f"{self.__class__.__name__}" + + def check_master_state(self, state: dict, service_name: str) -> bool: + if not state["is_master"] or state["is_sdown"] or state["is_odown"]: + return False + # Check if our sentinel doesn't see other nodes + if state["num-other-sentinels"] < self.min_other_sentinels: + return False + return True + + async def discover_master(self, service_name: str): + """ + Asks sentinel servers for the Redis master's address corresponding + to the service labeled ``service_name``. + + Returns a pair (address, port) or raises MasterNotFoundError if no + master is found. + """ + collected_errors = list() + for sentinel_no, sentinel in enumerate(self.sentinels): + try: + masters = await sentinel.sentinel_masters() + except (ConnectionError, TimeoutError) as e: + collected_errors.append(f"{sentinel} - {e!r}") + continue + state = masters.get(service_name) + if state and self.check_master_state(state, service_name): + # Put this sentinel at the top of the list + self.sentinels[0], self.sentinels[sentinel_no] = ( + sentinel, + self.sentinels[0], + ) + return state["ip"], state["port"] + + error_info = "" + if len(collected_errors) > 0: + error_info = f" : {', '.join(collected_errors)}" + raise MasterNotFoundError(f"No master found for {service_name!r}{error_info}") + + def filter_slaves( + self, slaves: Iterable[Mapping] + ) -> Sequence[Tuple[EncodableT, EncodableT]]: + """Remove slaves that are in an ODOWN or SDOWN state""" + slaves_alive = [] + for slave in slaves: + if slave["is_odown"] or slave["is_sdown"]: + continue + slaves_alive.append((slave["ip"], slave["port"])) + return slaves_alive + + async def discover_slaves( + self, service_name: str + ) -> Sequence[Tuple[EncodableT, EncodableT]]: + """Returns a list of alive slaves for service ``service_name``""" + for sentinel in self.sentinels: + try: + slaves = await sentinel.sentinel_slaves(service_name) + except (ConnectionError, ResponseError, TimeoutError): + continue + slaves = self.filter_slaves(slaves) + if slaves: + return slaves + return [] + + def master_for( + self, + service_name: str, + redis_class: Type[Redis] = Redis, + connection_pool_class: Type[SentinelConnectionPool] = SentinelConnectionPool, + **kwargs, + ): + """ + Returns a redis client instance for the ``service_name`` master. + + A :py:class:`~redis.sentinel.SentinelConnectionPool` class is + used to retrieve the master's address before establishing a new + connection. + + NOTE: If the master's address has changed, any cached connections to + the old master are closed. + + By default clients will be a :py:class:`~redis.Redis` instance. + Specify a different class to the ``redis_class`` argument if you + desire something different. + + The ``connection_pool_class`` specifies the connection pool to + use. The :py:class:`~redis.sentinel.SentinelConnectionPool` + will be used by default. + + All other keyword arguments are merged with any connection_kwargs + passed to this class and passed to the connection pool as keyword + arguments to be used to initialize Redis connections. + """ + kwargs["is_master"] = True + connection_kwargs = dict(self.connection_kwargs) + connection_kwargs.update(kwargs) + + connection_pool = connection_pool_class(service_name, self, **connection_kwargs) + # The Redis object "owns" the pool + return redis_class.from_pool(connection_pool) + + def slave_for( + self, + service_name: str, + redis_class: Type[Redis] = Redis, + connection_pool_class: Type[SentinelConnectionPool] = SentinelConnectionPool, + **kwargs, + ): + """ + Returns redis client instance for the ``service_name`` slave(s). + + A SentinelConnectionPool class is used to retrieve the slave's + address before establishing a new connection. + + By default clients will be a :py:class:`~redis.Redis` instance. + Specify a different class to the ``redis_class`` argument if you + desire something different. + + The ``connection_pool_class`` specifies the connection pool to use. + The SentinelConnectionPool will be used by default. + + All other keyword arguments are merged with any connection_kwargs + passed to this class and passed to the connection pool as keyword + arguments to be used to initialize Redis connections. + """ + kwargs["is_master"] = False + connection_kwargs = dict(self.connection_kwargs) + connection_kwargs.update(kwargs) + + connection_pool = connection_pool_class(service_name, self, **connection_kwargs) + # The Redis object "owns" the pool + return redis_class.from_pool(connection_pool) diff --git a/.venv/Lib/site-packages/redis/asyncio/utils.py b/.venv/Lib/site-packages/redis/asyncio/utils.py new file mode 100644 index 00000000..5a55b36a --- /dev/null +++ b/.venv/Lib/site-packages/redis/asyncio/utils.py @@ -0,0 +1,28 @@ +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from redis.asyncio.client import Pipeline, Redis + + +def from_url(url, **kwargs): + """ + Returns an active Redis client generated from the given database URL. + + Will attempt to extract the database id from the path url fragment, if + none is provided. + """ + from redis.asyncio.client import Redis + + return Redis.from_url(url, **kwargs) + + +class pipeline: + def __init__(self, redis_obj: "Redis"): + self.p: "Pipeline" = redis_obj.pipeline() + + async def __aenter__(self) -> "Pipeline": + return self.p + + async def __aexit__(self, exc_type, exc_value, traceback): + await self.p.execute() + del self.p diff --git a/.venv/Lib/site-packages/redis/backoff.py b/.venv/Lib/site-packages/redis/backoff.py new file mode 100644 index 00000000..c62e760b --- /dev/null +++ b/.venv/Lib/site-packages/redis/backoff.py @@ -0,0 +1,114 @@ +import random +from abc import ABC, abstractmethod + +# Maximum backoff between each retry in seconds +DEFAULT_CAP = 0.512 +# Minimum backoff between each retry in seconds +DEFAULT_BASE = 0.008 + + +class AbstractBackoff(ABC): + """Backoff interface""" + + def reset(self): + """ + Reset internal state before an operation. + `reset` is called once at the beginning of + every call to `Retry.call_with_retry` + """ + pass + + @abstractmethod + def compute(self, failures): + """Compute backoff in seconds upon failure""" + pass + + +class ConstantBackoff(AbstractBackoff): + """Constant backoff upon failure""" + + def __init__(self, backoff): + """`backoff`: backoff time in seconds""" + self._backoff = backoff + + def compute(self, failures): + return self._backoff + + +class NoBackoff(ConstantBackoff): + """No backoff upon failure""" + + def __init__(self): + super().__init__(0) + + +class ExponentialBackoff(AbstractBackoff): + """Exponential backoff upon failure""" + + def __init__(self, cap=DEFAULT_CAP, base=DEFAULT_BASE): + """ + `cap`: maximum backoff time in seconds + `base`: base backoff time in seconds + """ + self._cap = cap + self._base = base + + def compute(self, failures): + return min(self._cap, self._base * 2**failures) + + +class FullJitterBackoff(AbstractBackoff): + """Full jitter backoff upon failure""" + + def __init__(self, cap=DEFAULT_CAP, base=DEFAULT_BASE): + """ + `cap`: maximum backoff time in seconds + `base`: base backoff time in seconds + """ + self._cap = cap + self._base = base + + def compute(self, failures): + return random.uniform(0, min(self._cap, self._base * 2**failures)) + + +class EqualJitterBackoff(AbstractBackoff): + """Equal jitter backoff upon failure""" + + def __init__(self, cap=DEFAULT_CAP, base=DEFAULT_BASE): + """ + `cap`: maximum backoff time in seconds + `base`: base backoff time in seconds + """ + self._cap = cap + self._base = base + + def compute(self, failures): + temp = min(self._cap, self._base * 2**failures) / 2 + return temp + random.uniform(0, temp) + + +class DecorrelatedJitterBackoff(AbstractBackoff): + """Decorrelated jitter backoff upon failure""" + + def __init__(self, cap=DEFAULT_CAP, base=DEFAULT_BASE): + """ + `cap`: maximum backoff time in seconds + `base`: base backoff time in seconds + """ + self._cap = cap + self._base = base + self._previous_backoff = 0 + + def reset(self): + self._previous_backoff = 0 + + def compute(self, failures): + max_backoff = max(self._base, self._previous_backoff * 3) + temp = random.uniform(self._base, max_backoff) + self._previous_backoff = min(self._cap, temp) + return self._previous_backoff + + +def default_backoff(): + return EqualJitterBackoff() diff --git a/.venv/Lib/site-packages/redis/client.py b/.venv/Lib/site-packages/redis/client.py new file mode 100644 index 00000000..49231435 --- /dev/null +++ b/.venv/Lib/site-packages/redis/client.py @@ -0,0 +1,1500 @@ +import copy +import re +import threading +import time +import warnings +from itertools import chain +from typing import Any, Callable, Dict, List, Optional, Type, Union + +from redis._parsers.encoders import Encoder +from redis._parsers.helpers import ( + _RedisCallbacks, + _RedisCallbacksRESP2, + _RedisCallbacksRESP3, + bool_ok, +) +from redis.commands import ( + CoreCommands, + RedisModuleCommands, + SentinelCommands, + list_or_args, +) +from redis.connection import ConnectionPool, SSLConnection, UnixDomainSocketConnection +from redis.credentials import CredentialProvider +from redis.exceptions import ( + ConnectionError, + ExecAbortError, + PubSubError, + RedisError, + ResponseError, + TimeoutError, + WatchError, +) +from redis.lock import Lock +from redis.retry import Retry +from redis.utils import ( + HIREDIS_AVAILABLE, + _set_info_logger, + get_lib_version, + safe_str, + str_if_bytes, +) + +SYM_EMPTY = b"" +EMPTY_RESPONSE = "EMPTY_RESPONSE" + +# some responses (ie. dump) are binary, and just meant to never be decoded +NEVER_DECODE = "NEVER_DECODE" + + +class CaseInsensitiveDict(dict): + "Case insensitive dict implementation. Assumes string keys only." + + def __init__(self, data: Dict[str, str]) -> None: + for k, v in data.items(): + self[k.upper()] = v + + def __contains__(self, k): + return super().__contains__(k.upper()) + + def __delitem__(self, k): + super().__delitem__(k.upper()) + + def __getitem__(self, k): + return super().__getitem__(k.upper()) + + def get(self, k, default=None): + return super().get(k.upper(), default) + + def __setitem__(self, k, v): + super().__setitem__(k.upper(), v) + + def update(self, data): + data = CaseInsensitiveDict(data) + super().update(data) + + +class AbstractRedis: + pass + + +class Redis(RedisModuleCommands, CoreCommands, SentinelCommands): + """ + Implementation of the Redis protocol. + + This abstract class provides a Python interface to all Redis commands + and an implementation of the Redis protocol. + + Pipelines derive from this, implementing how + the commands are sent and received to the Redis server. Based on + configuration, an instance will either use a ConnectionPool, or + Connection object to talk to redis. + + It is not safe to pass PubSub or Pipeline objects between threads. + """ + + @classmethod + def from_url(cls, url: str, **kwargs) -> None: + """ + Return a Redis client object configured from the given URL + + For example:: + + redis://[[username]:[password]]@localhost:6379/0 + rediss://[[username]:[password]]@localhost:6379/0 + unix://[username@]/path/to/socket.sock?db=0[&password=password] + + Three URL schemes are supported: + + - `redis://` creates a TCP socket connection. See more at: + + - `rediss://` creates a SSL wrapped TCP socket connection. See more at: + + - ``unix://``: creates a Unix Domain Socket connection. + + The username, password, hostname, path and all querystring values + are passed through urllib.parse.unquote in order to replace any + percent-encoded values with their corresponding characters. + + There are several ways to specify a database number. The first value + found will be used: + + 1. A ``db`` querystring option, e.g. redis://localhost?db=0 + 2. If using the redis:// or rediss:// schemes, the path argument + of the url, e.g. redis://localhost/0 + 3. A ``db`` keyword argument to this function. + + If none of these options are specified, the default db=0 is used. + + All querystring options are cast to their appropriate Python types. + Boolean arguments can be specified with string values "True"/"False" + or "Yes"/"No". Values that cannot be properly cast cause a + ``ValueError`` to be raised. Once parsed, the querystring arguments + and keyword arguments are passed to the ``ConnectionPool``'s + class initializer. In the case of conflicting arguments, querystring + arguments always win. + + """ + single_connection_client = kwargs.pop("single_connection_client", False) + connection_pool = ConnectionPool.from_url(url, **kwargs) + client = cls( + connection_pool=connection_pool, + single_connection_client=single_connection_client, + ) + client.auto_close_connection_pool = True + return client + + @classmethod + def from_pool( + cls: Type["Redis"], + connection_pool: ConnectionPool, + ) -> "Redis": + """ + Return a Redis client from the given connection pool. + The Redis client will take ownership of the connection pool and + close it when the Redis client is closed. + """ + client = cls( + connection_pool=connection_pool, + ) + client.auto_close_connection_pool = True + return client + + def __init__( + self, + host="localhost", + port=6379, + db=0, + password=None, + socket_timeout=None, + socket_connect_timeout=None, + socket_keepalive=None, + socket_keepalive_options=None, + connection_pool=None, + unix_socket_path=None, + encoding="utf-8", + encoding_errors="strict", + charset=None, + errors=None, + decode_responses=False, + retry_on_timeout=False, + retry_on_error=None, + ssl=False, + ssl_keyfile=None, + ssl_certfile=None, + ssl_cert_reqs="required", + ssl_ca_certs=None, + ssl_ca_path=None, + ssl_ca_data=None, + ssl_check_hostname=False, + ssl_password=None, + ssl_validate_ocsp=False, + ssl_validate_ocsp_stapled=False, + ssl_ocsp_context=None, + ssl_ocsp_expected_cert=None, + max_connections=None, + single_connection_client=False, + health_check_interval=0, + client_name=None, + lib_name="redis-py", + lib_version=get_lib_version(), + username=None, + retry=None, + redis_connect_func=None, + credential_provider: Optional[CredentialProvider] = None, + protocol: Optional[int] = 2, + ) -> None: + """ + Initialize a new Redis client. + To specify a retry policy for specific errors, first set + `retry_on_error` to a list of the error/s to retry on, then set + `retry` to a valid `Retry` object. + To retry on TimeoutError, `retry_on_timeout` can also be set to `True`. + + Args: + + single_connection_client: + if `True`, connection pool is not used. In that case `Redis` + instance use is not thread safe. + """ + if not connection_pool: + if charset is not None: + warnings.warn( + DeprecationWarning( + '"charset" is deprecated. Use "encoding" instead' + ) + ) + encoding = charset + if errors is not None: + warnings.warn( + DeprecationWarning( + '"errors" is deprecated. Use "encoding_errors" instead' + ) + ) + encoding_errors = errors + if not retry_on_error: + retry_on_error = [] + if retry_on_timeout is True: + retry_on_error.append(TimeoutError) + kwargs = { + "db": db, + "username": username, + "password": password, + "socket_timeout": socket_timeout, + "encoding": encoding, + "encoding_errors": encoding_errors, + "decode_responses": decode_responses, + "retry_on_error": retry_on_error, + "retry": copy.deepcopy(retry), + "max_connections": max_connections, + "health_check_interval": health_check_interval, + "client_name": client_name, + "lib_name": lib_name, + "lib_version": lib_version, + "redis_connect_func": redis_connect_func, + "credential_provider": credential_provider, + "protocol": protocol, + } + # based on input, setup appropriate connection args + if unix_socket_path is not None: + kwargs.update( + { + "path": unix_socket_path, + "connection_class": UnixDomainSocketConnection, + } + ) + else: + # TCP specific options + kwargs.update( + { + "host": host, + "port": port, + "socket_connect_timeout": socket_connect_timeout, + "socket_keepalive": socket_keepalive, + "socket_keepalive_options": socket_keepalive_options, + } + ) + + if ssl: + kwargs.update( + { + "connection_class": SSLConnection, + "ssl_keyfile": ssl_keyfile, + "ssl_certfile": ssl_certfile, + "ssl_cert_reqs": ssl_cert_reqs, + "ssl_ca_certs": ssl_ca_certs, + "ssl_ca_data": ssl_ca_data, + "ssl_check_hostname": ssl_check_hostname, + "ssl_password": ssl_password, + "ssl_ca_path": ssl_ca_path, + "ssl_validate_ocsp_stapled": ssl_validate_ocsp_stapled, + "ssl_validate_ocsp": ssl_validate_ocsp, + "ssl_ocsp_context": ssl_ocsp_context, + "ssl_ocsp_expected_cert": ssl_ocsp_expected_cert, + } + ) + connection_pool = ConnectionPool(**kwargs) + self.auto_close_connection_pool = True + else: + self.auto_close_connection_pool = False + + self.connection_pool = connection_pool + self.connection = None + if single_connection_client: + self.connection = self.connection_pool.get_connection("_") + + self.response_callbacks = CaseInsensitiveDict(_RedisCallbacks) + + if self.connection_pool.connection_kwargs.get("protocol") in ["3", 3]: + self.response_callbacks.update(_RedisCallbacksRESP3) + else: + self.response_callbacks.update(_RedisCallbacksRESP2) + + def __repr__(self) -> str: + return f"{type(self).__name__}<{repr(self.connection_pool)}>" + + def get_encoder(self) -> "Encoder": + """Get the connection pool's encoder""" + return self.connection_pool.get_encoder() + + def get_connection_kwargs(self) -> Dict: + """Get the connection's key-word arguments""" + return self.connection_pool.connection_kwargs + + def get_retry(self) -> Optional["Retry"]: + return self.get_connection_kwargs().get("retry") + + def set_retry(self, retry: "Retry") -> None: + self.get_connection_kwargs().update({"retry": retry}) + self.connection_pool.set_retry(retry) + + def set_response_callback(self, command: str, callback: Callable) -> None: + """Set a custom Response Callback""" + self.response_callbacks[command] = callback + + def load_external_module(self, funcname, func) -> None: + """ + This function can be used to add externally defined redis modules, + and their namespaces to the redis client. + + funcname - A string containing the name of the function to create + func - The function, being added to this class. + + ex: Assume that one has a custom redis module named foomod that + creates command named 'foo.dothing' and 'foo.anotherthing' in redis. + To load function functions into this namespace: + + from redis import Redis + from foomodule import F + r = Redis() + r.load_external_module("foo", F) + r.foo().dothing('your', 'arguments') + + For a concrete example see the reimport of the redisjson module in + tests/test_connection.py::test_loading_external_modules + """ + setattr(self, funcname, func) + + def pipeline(self, transaction=True, shard_hint=None) -> "Pipeline": + """ + Return a new pipeline object that can queue multiple commands for + later execution. ``transaction`` indicates whether all commands + should be executed atomically. Apart from making a group of operations + atomic, pipelines are useful for reducing the back-and-forth overhead + between the client and server. + """ + return Pipeline( + self.connection_pool, self.response_callbacks, transaction, shard_hint + ) + + def transaction( + self, func: Callable[["Pipeline"], None], *watches, **kwargs + ) -> None: + """ + Convenience method for executing the callable `func` as a transaction + while watching all keys specified in `watches`. The 'func' callable + should expect a single argument which is a Pipeline object. + """ + shard_hint = kwargs.pop("shard_hint", None) + value_from_callable = kwargs.pop("value_from_callable", False) + watch_delay = kwargs.pop("watch_delay", None) + with self.pipeline(True, shard_hint) as pipe: + while True: + try: + if watches: + pipe.watch(*watches) + func_value = func(pipe) + exec_value = pipe.execute() + return func_value if value_from_callable else exec_value + except WatchError: + if watch_delay is not None and watch_delay > 0: + time.sleep(watch_delay) + continue + + def lock( + self, + name: str, + timeout: Optional[float] = None, + sleep: float = 0.1, + blocking: bool = True, + blocking_timeout: Optional[float] = None, + lock_class: Union[None, Any] = None, + thread_local: bool = True, + ): + """ + Return a new Lock object using key ``name`` that mimics + the behavior of threading.Lock. + + If specified, ``timeout`` indicates a maximum life for the lock. + By default, it will remain locked until release() is called. + + ``sleep`` indicates the amount of time to sleep per loop iteration + when the lock is in blocking mode and another client is currently + holding the lock. + + ``blocking`` indicates whether calling ``acquire`` should block until + the lock has been acquired or to fail immediately, causing ``acquire`` + to return False and the lock not being acquired. Defaults to True. + Note this value can be overridden by passing a ``blocking`` + argument to ``acquire``. + + ``blocking_timeout`` indicates the maximum amount of time in seconds to + spend trying to acquire the lock. A value of ``None`` indicates + continue trying forever. ``blocking_timeout`` can be specified as a + float or integer, both representing the number of seconds to wait. + + ``lock_class`` forces the specified lock implementation. Note that as + of redis-py 3.0, the only lock class we implement is ``Lock`` (which is + a Lua-based lock). So, it's unlikely you'll need this parameter, unless + you have created your own custom lock class. + + ``thread_local`` indicates whether the lock token is placed in + thread-local storage. By default, the token is placed in thread local + storage so that a thread only sees its token, not a token set by + another thread. Consider the following timeline: + + time: 0, thread-1 acquires `my-lock`, with a timeout of 5 seconds. + thread-1 sets the token to "abc" + time: 1, thread-2 blocks trying to acquire `my-lock` using the + Lock instance. + time: 5, thread-1 has not yet completed. redis expires the lock + key. + time: 5, thread-2 acquired `my-lock` now that it's available. + thread-2 sets the token to "xyz" + time: 6, thread-1 finishes its work and calls release(). if the + token is *not* stored in thread local storage, then + thread-1 would see the token value as "xyz" and would be + able to successfully release the thread-2's lock. + + In some use cases it's necessary to disable thread local storage. For + example, if you have code where one thread acquires a lock and passes + that lock instance to a worker thread to release later. If thread + local storage isn't disabled in this case, the worker thread won't see + the token set by the thread that acquired the lock. Our assumption + is that these cases aren't common and as such default to using + thread local storage.""" + if lock_class is None: + lock_class = Lock + return lock_class( + self, + name, + timeout=timeout, + sleep=sleep, + blocking=blocking, + blocking_timeout=blocking_timeout, + thread_local=thread_local, + ) + + def pubsub(self, **kwargs): + """ + Return a Publish/Subscribe object. With this object, you can + subscribe to channels and listen for messages that get published to + them. + """ + return PubSub(self.connection_pool, **kwargs) + + def monitor(self): + return Monitor(self.connection_pool) + + def client(self): + return self.__class__( + connection_pool=self.connection_pool, single_connection_client=True + ) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.close() + + def __del__(self): + self.close() + + def close(self): + # In case a connection property does not yet exist + # (due to a crash earlier in the Redis() constructor), return + # immediately as there is nothing to clean-up. + if not hasattr(self, "connection"): + return + + conn = self.connection + if conn: + self.connection = None + self.connection_pool.release(conn) + + if self.auto_close_connection_pool: + self.connection_pool.disconnect() + + def _send_command_parse_response(self, conn, command_name, *args, **options): + """ + Send a command and parse the response + """ + conn.send_command(*args) + return self.parse_response(conn, command_name, **options) + + def _disconnect_raise(self, conn, error): + """ + Close the connection and raise an exception + if retry_on_error is not set or the error + is not one of the specified error types + """ + conn.disconnect() + if ( + conn.retry_on_error is None + or isinstance(error, tuple(conn.retry_on_error)) is False + ): + raise error + + # COMMAND EXECUTION AND PROTOCOL PARSING + def execute_command(self, *args, **options): + """Execute a command and return a parsed response""" + pool = self.connection_pool + command_name = args[0] + conn = self.connection or pool.get_connection(command_name, **options) + + try: + return conn.retry.call_with_retry( + lambda: self._send_command_parse_response( + conn, command_name, *args, **options + ), + lambda error: self._disconnect_raise(conn, error), + ) + finally: + if not self.connection: + pool.release(conn) + + def parse_response(self, connection, command_name, **options): + """Parses a response from the Redis server""" + try: + if NEVER_DECODE in options: + response = connection.read_response(disable_decoding=True) + options.pop(NEVER_DECODE) + else: + response = connection.read_response() + except ResponseError: + if EMPTY_RESPONSE in options: + return options[EMPTY_RESPONSE] + raise + + if EMPTY_RESPONSE in options: + options.pop(EMPTY_RESPONSE) + + if command_name in self.response_callbacks: + return self.response_callbacks[command_name](response, **options) + return response + + +StrictRedis = Redis + + +class Monitor: + """ + Monitor is useful for handling the MONITOR command to the redis server. + next_command() method returns one command from monitor + listen() method yields commands from monitor. + """ + + monitor_re = re.compile(r"\[(\d+) (.*?)\] (.*)") + command_re = re.compile(r'"(.*?)(? "PubSub": + return self + + def __exit__(self, exc_type, exc_value, traceback) -> None: + self.reset() + + def __del__(self) -> None: + try: + # if this object went out of scope prior to shutting down + # subscriptions, close the connection manually before + # returning it to the connection pool + self.reset() + except Exception: + pass + + def reset(self) -> None: + if self.connection: + self.connection.disconnect() + self.connection._deregister_connect_callback(self.on_connect) + self.connection_pool.release(self.connection) + self.connection = None + self.health_check_response_counter = 0 + self.channels = {} + self.pending_unsubscribe_channels = set() + self.shard_channels = {} + self.pending_unsubscribe_shard_channels = set() + self.patterns = {} + self.pending_unsubscribe_patterns = set() + self.subscribed_event.clear() + + def close(self) -> None: + self.reset() + + def on_connect(self, connection) -> None: + "Re-subscribe to any channels and patterns previously subscribed to" + # NOTE: for python3, we can't pass bytestrings as keyword arguments + # so we need to decode channel/pattern names back to unicode strings + # before passing them to [p]subscribe. + self.pending_unsubscribe_channels.clear() + self.pending_unsubscribe_patterns.clear() + self.pending_unsubscribe_shard_channels.clear() + if self.channels: + channels = { + self.encoder.decode(k, force=True): v for k, v in self.channels.items() + } + self.subscribe(**channels) + if self.patterns: + patterns = { + self.encoder.decode(k, force=True): v for k, v in self.patterns.items() + } + self.psubscribe(**patterns) + if self.shard_channels: + shard_channels = { + self.encoder.decode(k, force=True): v + for k, v in self.shard_channels.items() + } + self.ssubscribe(**shard_channels) + + @property + def subscribed(self) -> bool: + """Indicates if there are subscriptions to any channels or patterns""" + return self.subscribed_event.is_set() + + def execute_command(self, *args): + """Execute a publish/subscribe command""" + + # NOTE: don't parse the response in this function -- it could pull a + # legitimate message off the stack if the connection is already + # subscribed to one or more channels + + if self.connection is None: + self.connection = self.connection_pool.get_connection( + "pubsub", self.shard_hint + ) + # register a callback that re-subscribes to any channels we + # were listening to when we were disconnected + self.connection._register_connect_callback(self.on_connect) + if self.push_handler_func is not None and not HIREDIS_AVAILABLE: + self.connection._parser.set_push_handler(self.push_handler_func) + connection = self.connection + kwargs = {"check_health": not self.subscribed} + if not self.subscribed: + self.clean_health_check_responses() + self._execute(connection, connection.send_command, *args, **kwargs) + + def clean_health_check_responses(self) -> None: + """ + If any health check responses are present, clean them + """ + ttl = 10 + conn = self.connection + while self.health_check_response_counter > 0 and ttl > 0: + if self._execute(conn, conn.can_read, timeout=conn.socket_timeout): + response = self._execute(conn, conn.read_response) + if self.is_health_check_response(response): + self.health_check_response_counter -= 1 + else: + raise PubSubError( + "A non health check response was cleaned by " + "execute_command: {0}".format(response) + ) + ttl -= 1 + + def _disconnect_raise_connect(self, conn, error) -> None: + """ + Close the connection and raise an exception + if retry_on_timeout is not set or the error + is not a TimeoutError. Otherwise, try to reconnect + """ + conn.disconnect() + if not (conn.retry_on_timeout and isinstance(error, TimeoutError)): + raise error + conn.connect() + + def _execute(self, conn, command, *args, **kwargs): + """ + Connect manually upon disconnection. If the Redis server is down, + this will fail and raise a ConnectionError as desired. + After reconnection, the ``on_connect`` callback should have been + called by the # connection to resubscribe us to any channels and + patterns we were previously listening to + """ + return conn.retry.call_with_retry( + lambda: command(*args, **kwargs), + lambda error: self._disconnect_raise_connect(conn, error), + ) + + def parse_response(self, block=True, timeout=0): + """Parse the response from a publish/subscribe command""" + conn = self.connection + if conn is None: + raise RuntimeError( + "pubsub connection not set: " + "did you forget to call subscribe() or psubscribe()?" + ) + + self.check_health() + + def try_read(): + if not block: + if not conn.can_read(timeout=timeout): + return None + else: + conn.connect() + return conn.read_response(disconnect_on_error=False, push_request=True) + + response = self._execute(conn, try_read) + + if self.is_health_check_response(response): + # ignore the health check message as user might not expect it + self.health_check_response_counter -= 1 + return None + return response + + def is_health_check_response(self, response) -> bool: + """ + Check if the response is a health check response. + If there are no subscriptions redis responds to PING command with a + bulk response, instead of a multi-bulk with "pong" and the response. + """ + return response in [ + self.health_check_response, # If there was a subscription + self.health_check_response_b, # If there wasn't + ] + + def check_health(self) -> None: + conn = self.connection + if conn is None: + raise RuntimeError( + "pubsub connection not set: " + "did you forget to call subscribe() or psubscribe()?" + ) + + if conn.health_check_interval and time.time() > conn.next_health_check: + conn.send_command("PING", self.HEALTH_CHECK_MESSAGE, check_health=False) + self.health_check_response_counter += 1 + + def _normalize_keys(self, data) -> Dict: + """ + normalize channel/pattern names to be either bytes or strings + based on whether responses are automatically decoded. this saves us + from coercing the value for each message coming in. + """ + encode = self.encoder.encode + decode = self.encoder.decode + return {decode(encode(k)): v for k, v in data.items()} + + def psubscribe(self, *args, **kwargs): + """ + Subscribe to channel patterns. Patterns supplied as keyword arguments + expect a pattern name as the key and a callable as the value. A + pattern's callable will be invoked automatically when a message is + received on that pattern rather than producing a message via + ``listen()``. + """ + if args: + args = list_or_args(args[0], args[1:]) + new_patterns = dict.fromkeys(args) + new_patterns.update(kwargs) + ret_val = self.execute_command("PSUBSCRIBE", *new_patterns.keys()) + # update the patterns dict AFTER we send the command. we don't want to + # subscribe twice to these patterns, once for the command and again + # for the reconnection. + new_patterns = self._normalize_keys(new_patterns) + self.patterns.update(new_patterns) + if not self.subscribed: + # Set the subscribed_event flag to True + self.subscribed_event.set() + # Clear the health check counter + self.health_check_response_counter = 0 + self.pending_unsubscribe_patterns.difference_update(new_patterns) + return ret_val + + def punsubscribe(self, *args): + """ + Unsubscribe from the supplied patterns. If empty, unsubscribe from + all patterns. + """ + if args: + args = list_or_args(args[0], args[1:]) + patterns = self._normalize_keys(dict.fromkeys(args)) + else: + patterns = self.patterns + self.pending_unsubscribe_patterns.update(patterns) + return self.execute_command("PUNSUBSCRIBE", *args) + + def subscribe(self, *args, **kwargs): + """ + Subscribe to channels. Channels supplied as keyword arguments expect + a channel name as the key and a callable as the value. A channel's + callable will be invoked automatically when a message is received on + that channel rather than producing a message via ``listen()`` or + ``get_message()``. + """ + if args: + args = list_or_args(args[0], args[1:]) + new_channels = dict.fromkeys(args) + new_channels.update(kwargs) + ret_val = self.execute_command("SUBSCRIBE", *new_channels.keys()) + # update the channels dict AFTER we send the command. we don't want to + # subscribe twice to these channels, once for the command and again + # for the reconnection. + new_channels = self._normalize_keys(new_channels) + self.channels.update(new_channels) + if not self.subscribed: + # Set the subscribed_event flag to True + self.subscribed_event.set() + # Clear the health check counter + self.health_check_response_counter = 0 + self.pending_unsubscribe_channels.difference_update(new_channels) + return ret_val + + def unsubscribe(self, *args): + """ + Unsubscribe from the supplied channels. If empty, unsubscribe from + all channels + """ + if args: + args = list_or_args(args[0], args[1:]) + channels = self._normalize_keys(dict.fromkeys(args)) + else: + channels = self.channels + self.pending_unsubscribe_channels.update(channels) + return self.execute_command("UNSUBSCRIBE", *args) + + def ssubscribe(self, *args, target_node=None, **kwargs): + """ + Subscribes the client to the specified shard channels. + Channels supplied as keyword arguments expect a channel name as the key + and a callable as the value. A channel's callable will be invoked automatically + when a message is received on that channel rather than producing a message via + ``listen()`` or ``get_sharded_message()``. + """ + if args: + args = list_or_args(args[0], args[1:]) + new_s_channels = dict.fromkeys(args) + new_s_channels.update(kwargs) + ret_val = self.execute_command("SSUBSCRIBE", *new_s_channels.keys()) + # update the s_channels dict AFTER we send the command. we don't want to + # subscribe twice to these channels, once for the command and again + # for the reconnection. + new_s_channels = self._normalize_keys(new_s_channels) + self.shard_channels.update(new_s_channels) + if not self.subscribed: + # Set the subscribed_event flag to True + self.subscribed_event.set() + # Clear the health check counter + self.health_check_response_counter = 0 + self.pending_unsubscribe_shard_channels.difference_update(new_s_channels) + return ret_val + + def sunsubscribe(self, *args, target_node=None): + """ + Unsubscribe from the supplied shard_channels. If empty, unsubscribe from + all shard_channels + """ + if args: + args = list_or_args(args[0], args[1:]) + s_channels = self._normalize_keys(dict.fromkeys(args)) + else: + s_channels = self.shard_channels + self.pending_unsubscribe_shard_channels.update(s_channels) + return self.execute_command("SUNSUBSCRIBE", *args) + + def listen(self): + "Listen for messages on channels this client has been subscribed to" + while self.subscribed: + response = self.handle_message(self.parse_response(block=True)) + if response is not None: + yield response + + def get_message( + self, ignore_subscribe_messages: bool = False, timeout: float = 0.0 + ): + """ + Get the next message if one is available, otherwise None. + + If timeout is specified, the system will wait for `timeout` seconds + before returning. Timeout should be specified as a floating point + number, or None, to wait indefinitely. + """ + if not self.subscribed: + # Wait for subscription + start_time = time.time() + if self.subscribed_event.wait(timeout) is True: + # The connection was subscribed during the timeout time frame. + # The timeout should be adjusted based on the time spent + # waiting for the subscription + time_spent = time.time() - start_time + timeout = max(0.0, timeout - time_spent) + else: + # The connection isn't subscribed to any channels or patterns, + # so no messages are available + return None + + response = self.parse_response(block=(timeout is None), timeout=timeout) + if response: + return self.handle_message(response, ignore_subscribe_messages) + return None + + get_sharded_message = get_message + + def ping(self, message: Union[str, None] = None) -> bool: + """ + Ping the Redis server + """ + args = ["PING", message] if message is not None else ["PING"] + return self.execute_command(*args) + + def handle_message(self, response, ignore_subscribe_messages=False): + """ + Parses a pub/sub message. If the channel or pattern was subscribed to + with a message handler, the handler is invoked instead of a parsed + message being returned. + """ + if response is None: + return None + if isinstance(response, bytes): + response = [b"pong", response] if response != b"PONG" else [b"pong", b""] + message_type = str_if_bytes(response[0]) + if message_type == "pmessage": + message = { + "type": message_type, + "pattern": response[1], + "channel": response[2], + "data": response[3], + } + elif message_type == "pong": + message = { + "type": message_type, + "pattern": None, + "channel": None, + "data": response[1], + } + else: + message = { + "type": message_type, + "pattern": None, + "channel": response[1], + "data": response[2], + } + + # if this is an unsubscribe message, remove it from memory + if message_type in self.UNSUBSCRIBE_MESSAGE_TYPES: + if message_type == "punsubscribe": + pattern = response[1] + if pattern in self.pending_unsubscribe_patterns: + self.pending_unsubscribe_patterns.remove(pattern) + self.patterns.pop(pattern, None) + elif message_type == "sunsubscribe": + s_channel = response[1] + if s_channel in self.pending_unsubscribe_shard_channels: + self.pending_unsubscribe_shard_channels.remove(s_channel) + self.shard_channels.pop(s_channel, None) + else: + channel = response[1] + if channel in self.pending_unsubscribe_channels: + self.pending_unsubscribe_channels.remove(channel) + self.channels.pop(channel, None) + if not self.channels and not self.patterns and not self.shard_channels: + # There are no subscriptions anymore, set subscribed_event flag + # to false + self.subscribed_event.clear() + + if message_type in self.PUBLISH_MESSAGE_TYPES: + # if there's a message handler, invoke it + if message_type == "pmessage": + handler = self.patterns.get(message["pattern"], None) + elif message_type == "smessage": + handler = self.shard_channels.get(message["channel"], None) + else: + handler = self.channels.get(message["channel"], None) + if handler: + handler(message) + return None + elif message_type != "pong": + # this is a subscribe/unsubscribe message. ignore if we don't + # want them + if ignore_subscribe_messages or self.ignore_subscribe_messages: + return None + + return message + + def run_in_thread( + self, + sleep_time: int = 0, + daemon: bool = False, + exception_handler: Optional[Callable] = None, + ) -> "PubSubWorkerThread": + for channel, handler in self.channels.items(): + if handler is None: + raise PubSubError(f"Channel: '{channel}' has no handler registered") + for pattern, handler in self.patterns.items(): + if handler is None: + raise PubSubError(f"Pattern: '{pattern}' has no handler registered") + for s_channel, handler in self.shard_channels.items(): + if handler is None: + raise PubSubError( + f"Shard Channel: '{s_channel}' has no handler registered" + ) + + thread = PubSubWorkerThread( + self, sleep_time, daemon=daemon, exception_handler=exception_handler + ) + thread.start() + return thread + + +class PubSubWorkerThread(threading.Thread): + def __init__( + self, + pubsub, + sleep_time: float, + daemon: bool = False, + exception_handler: Union[ + Callable[[Exception, "PubSub", "PubSubWorkerThread"], None], None + ] = None, + ): + super().__init__() + self.daemon = daemon + self.pubsub = pubsub + self.sleep_time = sleep_time + self.exception_handler = exception_handler + self._running = threading.Event() + + def run(self) -> None: + if self._running.is_set(): + return + self._running.set() + pubsub = self.pubsub + sleep_time = self.sleep_time + while self._running.is_set(): + try: + pubsub.get_message(ignore_subscribe_messages=True, timeout=sleep_time) + except BaseException as e: + if self.exception_handler is None: + raise + self.exception_handler(e, pubsub, self) + pubsub.close() + + def stop(self) -> None: + # trip the flag so the run loop exits. the run loop will + # close the pubsub connection, which disconnects the socket + # and returns the connection to the pool. + self._running.clear() + + +class Pipeline(Redis): + """ + Pipelines provide a way to transmit multiple commands to the Redis server + in one transmission. This is convenient for batch processing, such as + saving all the values in a list to Redis. + + All commands executed within a pipeline are wrapped with MULTI and EXEC + calls. This guarantees all commands executed in the pipeline will be + executed atomically. + + Any command raising an exception does *not* halt the execution of + subsequent commands in the pipeline. Instead, the exception is caught + and its instance is placed into the response list returned by execute(). + Code iterating over the response list should be able to deal with an + instance of an exception as a potential value. In general, these will be + ResponseError exceptions, such as those raised when issuing a command + on a key of a different datatype. + """ + + UNWATCH_COMMANDS = {"DISCARD", "EXEC", "UNWATCH"} + + def __init__(self, connection_pool, response_callbacks, transaction, shard_hint): + self.connection_pool = connection_pool + self.connection = None + self.response_callbacks = response_callbacks + self.transaction = transaction + self.shard_hint = shard_hint + + self.watching = False + self.reset() + + def __enter__(self) -> "Pipeline": + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.reset() + + def __del__(self): + try: + self.reset() + except Exception: + pass + + def __len__(self) -> int: + return len(self.command_stack) + + def __bool__(self) -> bool: + """Pipeline instances should always evaluate to True""" + return True + + def reset(self) -> None: + self.command_stack = [] + self.scripts = set() + # make sure to reset the connection state in the event that we were + # watching something + if self.watching and self.connection: + try: + # call this manually since our unwatch or + # immediate_execute_command methods can call reset() + self.connection.send_command("UNWATCH") + self.connection.read_response() + except ConnectionError: + # disconnect will also remove any previous WATCHes + self.connection.disconnect() + # clean up the other instance attributes + self.watching = False + self.explicit_transaction = False + # we can safely return the connection to the pool here since we're + # sure we're no longer WATCHing anything + if self.connection: + self.connection_pool.release(self.connection) + self.connection = None + + def close(self) -> None: + """Close the pipeline""" + self.reset() + + def multi(self) -> None: + """ + Start a transactional block of the pipeline after WATCH commands + are issued. End the transactional block with `execute`. + """ + if self.explicit_transaction: + raise RedisError("Cannot issue nested calls to MULTI") + if self.command_stack: + raise RedisError( + "Commands without an initial WATCH have already been issued" + ) + self.explicit_transaction = True + + def execute_command(self, *args, **kwargs): + if (self.watching or args[0] == "WATCH") and not self.explicit_transaction: + return self.immediate_execute_command(*args, **kwargs) + return self.pipeline_execute_command(*args, **kwargs) + + def _disconnect_reset_raise(self, conn, error) -> None: + """ + Close the connection, reset watching state and + raise an exception if we were watching, + retry_on_timeout is not set, + or the error is not a TimeoutError + """ + conn.disconnect() + # if we were already watching a variable, the watch is no longer + # valid since this connection has died. raise a WatchError, which + # indicates the user should retry this transaction. + if self.watching: + self.reset() + raise WatchError( + "A ConnectionError occurred on while watching one or more keys" + ) + # if retry_on_timeout is not set, or the error is not + # a TimeoutError, raise it + if not (conn.retry_on_timeout and isinstance(error, TimeoutError)): + self.reset() + raise + + def immediate_execute_command(self, *args, **options): + """ + Execute a command immediately, but don't auto-retry on a + ConnectionError if we're already WATCHing a variable. Used when + issuing WATCH or subsequent commands retrieving their values but before + MULTI is called. + """ + command_name = args[0] + conn = self.connection + # if this is the first call, we need a connection + if not conn: + conn = self.connection_pool.get_connection(command_name, self.shard_hint) + self.connection = conn + + return conn.retry.call_with_retry( + lambda: self._send_command_parse_response( + conn, command_name, *args, **options + ), + lambda error: self._disconnect_reset_raise(conn, error), + ) + + def pipeline_execute_command(self, *args, **options) -> "Pipeline": + """ + Stage a command to be executed when execute() is next called + + Returns the current Pipeline object back so commands can be + chained together, such as: + + pipe = pipe.set('foo', 'bar').incr('baz').decr('bang') + + At some other point, you can then run: pipe.execute(), + which will execute all commands queued in the pipe. + """ + self.command_stack.append((args, options)) + return self + + def _execute_transaction(self, connection, commands, raise_on_error) -> List: + cmds = chain([(("MULTI",), {})], commands, [(("EXEC",), {})]) + all_cmds = connection.pack_commands( + [args for args, options in cmds if EMPTY_RESPONSE not in options] + ) + connection.send_packed_command(all_cmds) + errors = [] + + # parse off the response for MULTI + # NOTE: we need to handle ResponseErrors here and continue + # so that we read all the additional command messages from + # the socket + try: + self.parse_response(connection, "_") + except ResponseError as e: + errors.append((0, e)) + + # and all the other commands + for i, command in enumerate(commands): + if EMPTY_RESPONSE in command[1]: + errors.append((i, command[1][EMPTY_RESPONSE])) + else: + try: + self.parse_response(connection, "_") + except ResponseError as e: + self.annotate_exception(e, i + 1, command[0]) + errors.append((i, e)) + + # parse the EXEC. + try: + response = self.parse_response(connection, "_") + except ExecAbortError: + if errors: + raise errors[0][1] + raise + + # EXEC clears any watched keys + self.watching = False + + if response is None: + raise WatchError("Watched variable changed.") + + # put any parse errors into the response + for i, e in errors: + response.insert(i, e) + + if len(response) != len(commands): + self.connection.disconnect() + raise ResponseError( + "Wrong number of response items from pipeline execution" + ) + + # find any errors in the response and raise if necessary + if raise_on_error: + self.raise_first_error(commands, response) + + # We have to run response callbacks manually + data = [] + for r, cmd in zip(response, commands): + if not isinstance(r, Exception): + args, options = cmd + command_name = args[0] + if command_name in self.response_callbacks: + r = self.response_callbacks[command_name](r, **options) + data.append(r) + return data + + def _execute_pipeline(self, connection, commands, raise_on_error): + # build up all commands into a single request to increase network perf + all_cmds = connection.pack_commands([args for args, _ in commands]) + connection.send_packed_command(all_cmds) + + response = [] + for args, options in commands: + try: + response.append(self.parse_response(connection, args[0], **options)) + except ResponseError as e: + response.append(e) + + if raise_on_error: + self.raise_first_error(commands, response) + return response + + def raise_first_error(self, commands, response): + for i, r in enumerate(response): + if isinstance(r, ResponseError): + self.annotate_exception(r, i + 1, commands[i][0]) + raise r + + def annotate_exception(self, exception, number, command): + cmd = " ".join(map(safe_str, command)) + msg = ( + f"Command # {number} ({cmd}) of pipeline " + f"caused error: {exception.args[0]}" + ) + exception.args = (msg,) + exception.args[1:] + + def parse_response(self, connection, command_name, **options): + result = Redis.parse_response(self, connection, command_name, **options) + if command_name in self.UNWATCH_COMMANDS: + self.watching = False + elif command_name == "WATCH": + self.watching = True + return result + + def load_scripts(self): + # make sure all scripts that are about to be run on this pipeline exist + scripts = list(self.scripts) + immediate = self.immediate_execute_command + shas = [s.sha for s in scripts] + # we can't use the normal script_* methods because they would just + # get buffered in the pipeline. + exists = immediate("SCRIPT EXISTS", *shas) + if not all(exists): + for s, exist in zip(scripts, exists): + if not exist: + s.sha = immediate("SCRIPT LOAD", s.script) + + def _disconnect_raise_reset(self, conn: Redis, error: Exception) -> None: + """ + Close the connection, raise an exception if we were watching, + and raise an exception if TimeoutError is not part of retry_on_error, + or the error is not a TimeoutError + """ + conn.disconnect() + # if we were watching a variable, the watch is no longer valid + # since this connection has died. raise a WatchError, which + # indicates the user should retry this transaction. + if self.watching: + raise WatchError( + "A ConnectionError occurred on while watching one or more keys" + ) + # if TimeoutError is not part of retry_on_error, or the error + # is not a TimeoutError, raise it + if not ( + TimeoutError in conn.retry_on_error and isinstance(error, TimeoutError) + ): + self.reset() + raise error + + def execute(self, raise_on_error=True): + """Execute all the commands in the current pipeline""" + stack = self.command_stack + if not stack and not self.watching: + return [] + if self.scripts: + self.load_scripts() + if self.transaction or self.explicit_transaction: + execute = self._execute_transaction + else: + execute = self._execute_pipeline + + conn = self.connection + if not conn: + conn = self.connection_pool.get_connection("MULTI", self.shard_hint) + # assign to self.connection so reset() releases the connection + # back to the pool after we're done + self.connection = conn + + try: + return conn.retry.call_with_retry( + lambda: execute(conn, stack, raise_on_error), + lambda error: self._disconnect_raise_reset(conn, error), + ) + finally: + self.reset() + + def discard(self): + """ + Flushes all previously queued commands + See: https://redis.io/commands/DISCARD + """ + self.execute_command("DISCARD") + + def watch(self, *names): + """Watches the values at keys ``names``""" + if self.explicit_transaction: + raise RedisError("Cannot issue a WATCH after a MULTI") + return self.execute_command("WATCH", *names) + + def unwatch(self) -> bool: + """Unwatches all previously specified keys""" + return self.watching and self.execute_command("UNWATCH") or True diff --git a/.venv/Lib/site-packages/redis/cluster.py b/.venv/Lib/site-packages/redis/cluster.py new file mode 100644 index 00000000..873d586c --- /dev/null +++ b/.venv/Lib/site-packages/redis/cluster.py @@ -0,0 +1,2486 @@ +import random +import socket +import sys +import threading +import time +from collections import OrderedDict +from typing import Any, Callable, Dict, List, Optional, Tuple, Union + +from redis._parsers import CommandsParser, Encoder +from redis._parsers.helpers import parse_scan +from redis.backoff import default_backoff +from redis.client import CaseInsensitiveDict, PubSub, Redis +from redis.commands import READ_COMMANDS, RedisClusterCommands +from redis.commands.helpers import list_or_args +from redis.connection import ConnectionPool, DefaultParser, parse_url +from redis.crc import REDIS_CLUSTER_HASH_SLOTS, key_slot +from redis.exceptions import ( + AskError, + AuthenticationError, + ClusterCrossSlotError, + ClusterDownError, + ClusterError, + ConnectionError, + DataError, + MasterDownError, + MovedError, + RedisClusterException, + RedisError, + ResponseError, + SlotNotCoveredError, + TimeoutError, + TryAgainError, +) +from redis.lock import Lock +from redis.retry import Retry +from redis.utils import ( + HIREDIS_AVAILABLE, + dict_merge, + list_keys_to_dict, + merge_result, + safe_str, + str_if_bytes, +) + + +def get_node_name(host: str, port: Union[str, int]) -> str: + return f"{host}:{port}" + + +def get_connection(redis_node, *args, **options): + return redis_node.connection or redis_node.connection_pool.get_connection( + args[0], **options + ) + + +def parse_scan_result(command, res, **options): + cursors = {} + ret = [] + for node_name, response in res.items(): + cursor, r = parse_scan(response, **options) + cursors[node_name] = cursor + ret += r + + return cursors, ret + + +def parse_pubsub_numsub(command, res, **options): + numsub_d = OrderedDict() + for numsub_tups in res.values(): + for channel, numsubbed in numsub_tups: + try: + numsub_d[channel] += numsubbed + except KeyError: + numsub_d[channel] = numsubbed + + ret_numsub = [(channel, numsub) for channel, numsub in numsub_d.items()] + return ret_numsub + + +def parse_cluster_slots( + resp: Any, **options: Any +) -> Dict[Tuple[int, int], Dict[str, Any]]: + current_host = options.get("current_host", "") + + def fix_server(*args: Any) -> Tuple[str, Any]: + return str_if_bytes(args[0]) or current_host, args[1] + + slots = {} + for slot in resp: + start, end, primary = slot[:3] + replicas = slot[3:] + slots[start, end] = { + "primary": fix_server(*primary), + "replicas": [fix_server(*replica) for replica in replicas], + } + + return slots + + +def parse_cluster_shards(resp, **options): + """ + Parse CLUSTER SHARDS response. + """ + if isinstance(resp[0], dict): + return resp + shards = [] + for x in resp: + shard = {"slots": [], "nodes": []} + for i in range(0, len(x[1]), 2): + shard["slots"].append((x[1][i], (x[1][i + 1]))) + nodes = x[3] + for node in nodes: + dict_node = {} + for i in range(0, len(node), 2): + dict_node[node[i]] = node[i + 1] + shard["nodes"].append(dict_node) + shards.append(shard) + + return shards + + +def parse_cluster_myshardid(resp, **options): + """ + Parse CLUSTER MYSHARDID response. + """ + return resp.decode("utf-8") + + +PRIMARY = "primary" +REPLICA = "replica" +SLOT_ID = "slot-id" + +REDIS_ALLOWED_KEYS = ( + "charset", + "connection_class", + "connection_pool", + "connection_pool_class", + "client_name", + "credential_provider", + "db", + "decode_responses", + "encoding", + "encoding_errors", + "errors", + "host", + "lib_name", + "lib_version", + "max_connections", + "nodes_flag", + "redis_connect_func", + "password", + "port", + "queue_class", + "retry", + "retry_on_timeout", + "protocol", + "socket_connect_timeout", + "socket_keepalive", + "socket_keepalive_options", + "socket_timeout", + "ssl", + "ssl_ca_certs", + "ssl_ca_data", + "ssl_certfile", + "ssl_cert_reqs", + "ssl_keyfile", + "ssl_password", + "unix_socket_path", + "username", +) +KWARGS_DISABLED_KEYS = ("host", "port") + + +def cleanup_kwargs(**kwargs): + """ + Remove unsupported or disabled keys from kwargs + """ + connection_kwargs = { + k: v + for k, v in kwargs.items() + if k in REDIS_ALLOWED_KEYS and k not in KWARGS_DISABLED_KEYS + } + + return connection_kwargs + + +class ClusterParser(DefaultParser): + EXCEPTION_CLASSES = dict_merge( + DefaultParser.EXCEPTION_CLASSES, + { + "ASK": AskError, + "TRYAGAIN": TryAgainError, + "MOVED": MovedError, + "CLUSTERDOWN": ClusterDownError, + "CROSSSLOT": ClusterCrossSlotError, + "MASTERDOWN": MasterDownError, + }, + ) + + +class AbstractRedisCluster: + RedisClusterRequestTTL = 16 + + PRIMARIES = "primaries" + REPLICAS = "replicas" + ALL_NODES = "all" + RANDOM = "random" + DEFAULT_NODE = "default-node" + + NODE_FLAGS = {PRIMARIES, REPLICAS, ALL_NODES, RANDOM, DEFAULT_NODE} + + COMMAND_FLAGS = dict_merge( + list_keys_to_dict( + [ + "ACL CAT", + "ACL DELUSER", + "ACL DRYRUN", + "ACL GENPASS", + "ACL GETUSER", + "ACL HELP", + "ACL LIST", + "ACL LOG", + "ACL LOAD", + "ACL SAVE", + "ACL SETUSER", + "ACL USERS", + "ACL WHOAMI", + "AUTH", + "CLIENT LIST", + "CLIENT SETINFO", + "CLIENT SETNAME", + "CLIENT GETNAME", + "CONFIG SET", + "CONFIG REWRITE", + "CONFIG RESETSTAT", + "TIME", + "PUBSUB CHANNELS", + "PUBSUB NUMPAT", + "PUBSUB NUMSUB", + "PUBSUB SHARDCHANNELS", + "PUBSUB SHARDNUMSUB", + "PING", + "INFO", + "SHUTDOWN", + "KEYS", + "DBSIZE", + "BGSAVE", + "SLOWLOG GET", + "SLOWLOG LEN", + "SLOWLOG RESET", + "WAIT", + "WAITAOF", + "SAVE", + "MEMORY PURGE", + "MEMORY MALLOC-STATS", + "MEMORY STATS", + "LASTSAVE", + "CLIENT TRACKINGINFO", + "CLIENT PAUSE", + "CLIENT UNPAUSE", + "CLIENT UNBLOCK", + "CLIENT ID", + "CLIENT REPLY", + "CLIENT GETREDIR", + "CLIENT INFO", + "CLIENT KILL", + "READONLY", + "CLUSTER INFO", + "CLUSTER MEET", + "CLUSTER MYSHARDID", + "CLUSTER NODES", + "CLUSTER REPLICAS", + "CLUSTER RESET", + "CLUSTER SET-CONFIG-EPOCH", + "CLUSTER SLOTS", + "CLUSTER SHARDS", + "CLUSTER COUNT-FAILURE-REPORTS", + "CLUSTER KEYSLOT", + "COMMAND", + "COMMAND COUNT", + "COMMAND LIST", + "COMMAND GETKEYS", + "CONFIG GET", + "DEBUG", + "RANDOMKEY", + "READONLY", + "READWRITE", + "TIME", + "TFUNCTION LOAD", + "TFUNCTION DELETE", + "TFUNCTION LIST", + "TFCALL", + "TFCALLASYNC", + "GRAPH.CONFIG", + "LATENCY HISTORY", + "LATENCY LATEST", + "LATENCY RESET", + "MODULE LIST", + "MODULE LOAD", + "MODULE UNLOAD", + "MODULE LOADEX", + ], + DEFAULT_NODE, + ), + list_keys_to_dict( + [ + "FLUSHALL", + "FLUSHDB", + "FUNCTION DELETE", + "FUNCTION FLUSH", + "FUNCTION LIST", + "FUNCTION LOAD", + "FUNCTION RESTORE", + "REDISGEARS_2.REFRESHCLUSTER", + "SCAN", + "SCRIPT EXISTS", + "SCRIPT FLUSH", + "SCRIPT LOAD", + ], + PRIMARIES, + ), + list_keys_to_dict(["FUNCTION DUMP"], RANDOM), + list_keys_to_dict( + [ + "CLUSTER COUNTKEYSINSLOT", + "CLUSTER DELSLOTS", + "CLUSTER DELSLOTSRANGE", + "CLUSTER GETKEYSINSLOT", + "CLUSTER SETSLOT", + ], + SLOT_ID, + ), + ) + + SEARCH_COMMANDS = ( + [ + "FT.CREATE", + "FT.SEARCH", + "FT.AGGREGATE", + "FT.EXPLAIN", + "FT.EXPLAINCLI", + "FT,PROFILE", + "FT.ALTER", + "FT.DROPINDEX", + "FT.ALIASADD", + "FT.ALIASUPDATE", + "FT.ALIASDEL", + "FT.TAGVALS", + "FT.SUGADD", + "FT.SUGGET", + "FT.SUGDEL", + "FT.SUGLEN", + "FT.SYNUPDATE", + "FT.SYNDUMP", + "FT.SPELLCHECK", + "FT.DICTADD", + "FT.DICTDEL", + "FT.DICTDUMP", + "FT.INFO", + "FT._LIST", + "FT.CONFIG", + "FT.ADD", + "FT.DEL", + "FT.DROP", + "FT.GET", + "FT.MGET", + "FT.SYNADD", + ], + ) + + CLUSTER_COMMANDS_RESPONSE_CALLBACKS = { + "CLUSTER SLOTS": parse_cluster_slots, + "CLUSTER SHARDS": parse_cluster_shards, + "CLUSTER MYSHARDID": parse_cluster_myshardid, + } + + RESULT_CALLBACKS = dict_merge( + list_keys_to_dict(["PUBSUB NUMSUB", "PUBSUB SHARDNUMSUB"], parse_pubsub_numsub), + list_keys_to_dict( + ["PUBSUB NUMPAT"], lambda command, res: sum(list(res.values())) + ), + list_keys_to_dict( + ["KEYS", "PUBSUB CHANNELS", "PUBSUB SHARDCHANNELS"], merge_result + ), + list_keys_to_dict( + [ + "PING", + "CONFIG SET", + "CONFIG REWRITE", + "CONFIG RESETSTAT", + "CLIENT SETNAME", + "BGSAVE", + "SLOWLOG RESET", + "SAVE", + "MEMORY PURGE", + "CLIENT PAUSE", + "CLIENT UNPAUSE", + ], + lambda command, res: all(res.values()) if isinstance(res, dict) else res, + ), + list_keys_to_dict( + ["DBSIZE", "WAIT"], + lambda command, res: sum(res.values()) if isinstance(res, dict) else res, + ), + list_keys_to_dict( + ["CLIENT UNBLOCK"], lambda command, res: 1 if sum(res.values()) > 0 else 0 + ), + list_keys_to_dict(["SCAN"], parse_scan_result), + list_keys_to_dict( + ["SCRIPT LOAD"], lambda command, res: list(res.values()).pop() + ), + list_keys_to_dict( + ["SCRIPT EXISTS"], lambda command, res: [all(k) for k in zip(*res.values())] + ), + list_keys_to_dict(["SCRIPT FLUSH"], lambda command, res: all(res.values())), + ) + + ERRORS_ALLOW_RETRY = (ConnectionError, TimeoutError, ClusterDownError) + + def replace_default_node(self, target_node: "ClusterNode" = None) -> None: + """Replace the default cluster node. + A random cluster node will be chosen if target_node isn't passed, and primaries + will be prioritized. The default node will not be changed if there are no other + nodes in the cluster. + + Args: + target_node (ClusterNode, optional): Target node to replace the default + node. Defaults to None. + """ + if target_node: + self.nodes_manager.default_node = target_node + else: + curr_node = self.get_default_node() + primaries = [node for node in self.get_primaries() if node != curr_node] + if primaries: + # Choose a primary if the cluster contains different primaries + self.nodes_manager.default_node = random.choice(primaries) + else: + # Otherwise, hoose a primary if the cluster contains different primaries + replicas = [node for node in self.get_replicas() if node != curr_node] + if replicas: + self.nodes_manager.default_node = random.choice(replicas) + + +class RedisCluster(AbstractRedisCluster, RedisClusterCommands): + @classmethod + def from_url(cls, url, **kwargs): + """ + Return a Redis client object configured from the given URL + + For example:: + + redis://[[username]:[password]]@localhost:6379/0 + rediss://[[username]:[password]]@localhost:6379/0 + unix://[username@]/path/to/socket.sock?db=0[&password=password] + + Three URL schemes are supported: + + - `redis://` creates a TCP socket connection. See more at: + + - `rediss://` creates a SSL wrapped TCP socket connection. See more at: + + - ``unix://``: creates a Unix Domain Socket connection. + + The username, password, hostname, path and all querystring values + are passed through urllib.parse.unquote in order to replace any + percent-encoded values with their corresponding characters. + + There are several ways to specify a database number. The first value + found will be used: + + 1. A ``db`` querystring option, e.g. redis://localhost?db=0 + 2. If using the redis:// or rediss:// schemes, the path argument + of the url, e.g. redis://localhost/0 + 3. A ``db`` keyword argument to this function. + + If none of these options are specified, the default db=0 is used. + + All querystring options are cast to their appropriate Python types. + Boolean arguments can be specified with string values "True"/"False" + or "Yes"/"No". Values that cannot be properly cast cause a + ``ValueError`` to be raised. Once parsed, the querystring arguments + and keyword arguments are passed to the ``ConnectionPool``'s + class initializer. In the case of conflicting arguments, querystring + arguments always win. + + """ + return cls(url=url, **kwargs) + + def __init__( + self, + host: Optional[str] = None, + port: int = 6379, + startup_nodes: Optional[List["ClusterNode"]] = None, + cluster_error_retry_attempts: int = 3, + retry: Optional["Retry"] = None, + require_full_coverage: bool = False, + reinitialize_steps: int = 5, + read_from_replicas: bool = False, + dynamic_startup_nodes: bool = True, + url: Optional[str] = None, + address_remap: Optional[Callable[[str, int], Tuple[str, int]]] = None, + **kwargs, + ): + """ + Initialize a new RedisCluster client. + + :param startup_nodes: + List of nodes from which initial bootstrapping can be done + :param host: + Can be used to point to a startup node + :param port: + Can be used to point to a startup node + :param require_full_coverage: + When set to False (default value): the client will not require a + full coverage of the slots. However, if not all slots are covered, + and at least one node has 'cluster-require-full-coverage' set to + 'yes,' the server will throw a ClusterDownError for some key-based + commands. See - + https://redis.io/topics/cluster-tutorial#redis-cluster-configuration-parameters + When set to True: all slots must be covered to construct the + cluster client. If not all slots are covered, RedisClusterException + will be thrown. + :param read_from_replicas: + Enable read from replicas in READONLY mode. You can read possibly + stale data. + When set to true, read commands will be assigned between the + primary and its replications in a Round-Robin manner. + :param dynamic_startup_nodes: + Set the RedisCluster's startup nodes to all of the discovered nodes. + If true (default value), the cluster's discovered nodes will be used to + determine the cluster nodes-slots mapping in the next topology refresh. + It will remove the initial passed startup nodes if their endpoints aren't + listed in the CLUSTER SLOTS output. + If you use dynamic DNS endpoints for startup nodes but CLUSTER SLOTS lists + specific IP addresses, it is best to set it to false. + :param cluster_error_retry_attempts: + Number of times to retry before raising an error when + :class:`~.TimeoutError` or :class:`~.ConnectionError` or + :class:`~.ClusterDownError` are encountered + :param reinitialize_steps: + Specifies the number of MOVED errors that need to occur before + reinitializing the whole cluster topology. If a MOVED error occurs + and the cluster does not need to be reinitialized on this current + error handling, only the MOVED slot will be patched with the + redirected node. + To reinitialize the cluster on every MOVED error, set + reinitialize_steps to 1. + To avoid reinitializing the cluster on moved errors, set + reinitialize_steps to 0. + :param address_remap: + An optional callable which, when provided with an internal network + address of a node, e.g. a `(host, port)` tuple, will return the address + where the node is reachable. This can be used to map the addresses at + which the nodes _think_ they are, to addresses at which a client may + reach them, such as when they sit behind a proxy. + + :**kwargs: + Extra arguments that will be sent into Redis instance when created + (See Official redis-py doc for supported kwargs + [https://github.com/andymccurdy/redis-py/blob/master/redis/client.py]) + Some kwargs are not supported and will raise a + RedisClusterException: + - db (Redis do not support database SELECT in cluster mode) + """ + if startup_nodes is None: + startup_nodes = [] + + if "db" in kwargs: + # Argument 'db' is not possible to use in cluster mode + raise RedisClusterException( + "Argument 'db' is not possible to use in cluster mode" + ) + + # Get the startup node/s + from_url = False + if url is not None: + from_url = True + url_options = parse_url(url) + if "path" in url_options: + raise RedisClusterException( + "RedisCluster does not currently support Unix Domain " + "Socket connections" + ) + if "db" in url_options and url_options["db"] != 0: + # Argument 'db' is not possible to use in cluster mode + raise RedisClusterException( + "A ``db`` querystring option can only be 0 in cluster mode" + ) + kwargs.update(url_options) + host = kwargs.get("host") + port = kwargs.get("port", port) + startup_nodes.append(ClusterNode(host, port)) + elif host is not None and port is not None: + startup_nodes.append(ClusterNode(host, port)) + elif len(startup_nodes) == 0: + # No startup node was provided + raise RedisClusterException( + "RedisCluster requires at least one node to discover the " + "cluster. Please provide one of the followings:\n" + "1. host and port, for example:\n" + " RedisCluster(host='localhost', port=6379)\n" + "2. list of startup nodes, for example:\n" + " RedisCluster(startup_nodes=[ClusterNode('localhost', 6379)," + " ClusterNode('localhost', 6378)])" + ) + # Update the connection arguments + # Whenever a new connection is established, RedisCluster's on_connect + # method should be run + # If the user passed on_connect function we'll save it and run it + # inside the RedisCluster.on_connect() function + self.user_on_connect_func = kwargs.pop("redis_connect_func", None) + kwargs.update({"redis_connect_func": self.on_connect}) + kwargs = cleanup_kwargs(**kwargs) + if retry: + self.retry = retry + kwargs.update({"retry": self.retry}) + else: + kwargs.update({"retry": Retry(default_backoff(), 0)}) + + self.encoder = Encoder( + kwargs.get("encoding", "utf-8"), + kwargs.get("encoding_errors", "strict"), + kwargs.get("decode_responses", False), + ) + self.cluster_error_retry_attempts = cluster_error_retry_attempts + self.command_flags = self.__class__.COMMAND_FLAGS.copy() + self.node_flags = self.__class__.NODE_FLAGS.copy() + self.read_from_replicas = read_from_replicas + self.reinitialize_counter = 0 + self.reinitialize_steps = reinitialize_steps + self.nodes_manager = NodesManager( + startup_nodes=startup_nodes, + from_url=from_url, + require_full_coverage=require_full_coverage, + dynamic_startup_nodes=dynamic_startup_nodes, + address_remap=address_remap, + **kwargs, + ) + + self.cluster_response_callbacks = CaseInsensitiveDict( + self.__class__.CLUSTER_COMMANDS_RESPONSE_CALLBACKS + ) + self.result_callbacks = CaseInsensitiveDict(self.__class__.RESULT_CALLBACKS) + self.commands_parser = CommandsParser(self) + self._lock = threading.Lock() + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.close() + + def __del__(self): + self.close() + + def disconnect_connection_pools(self): + for node in self.get_nodes(): + if node.redis_connection: + try: + node.redis_connection.connection_pool.disconnect() + except OSError: + # Client was already disconnected. do nothing + pass + + def on_connect(self, connection): + """ + Initialize the connection, authenticate and select a database and send + READONLY if it is set during object initialization. + """ + connection.set_parser(ClusterParser) + connection.on_connect() + + if self.read_from_replicas: + # Sending READONLY command to server to configure connection as + # readonly. Since each cluster node may change its server type due + # to a failover, we should establish a READONLY connection + # regardless of the server type. If this is a primary connection, + # READONLY would not affect executing write commands. + connection.send_command("READONLY") + if str_if_bytes(connection.read_response()) != "OK": + raise ConnectionError("READONLY command failed") + + if self.user_on_connect_func is not None: + self.user_on_connect_func(connection) + + def get_redis_connection(self, node): + if not node.redis_connection: + with self._lock: + if not node.redis_connection: + self.nodes_manager.create_redis_connections([node]) + return node.redis_connection + + def get_node(self, host=None, port=None, node_name=None): + return self.nodes_manager.get_node(host, port, node_name) + + def get_primaries(self): + return self.nodes_manager.get_nodes_by_server_type(PRIMARY) + + def get_replicas(self): + return self.nodes_manager.get_nodes_by_server_type(REPLICA) + + def get_random_node(self): + return random.choice(list(self.nodes_manager.nodes_cache.values())) + + def get_nodes(self): + return list(self.nodes_manager.nodes_cache.values()) + + def get_node_from_key(self, key, replica=False): + """ + Get the node that holds the key's slot. + If replica set to True but the slot doesn't have any replicas, None is + returned. + """ + slot = self.keyslot(key) + slot_cache = self.nodes_manager.slots_cache.get(slot) + if slot_cache is None or len(slot_cache) == 0: + raise SlotNotCoveredError(f'Slot "{slot}" is not covered by the cluster.') + if replica and len(self.nodes_manager.slots_cache[slot]) < 2: + return None + elif replica: + node_idx = 1 + else: + # primary + node_idx = 0 + + return slot_cache[node_idx] + + def get_default_node(self): + """ + Get the cluster's default node + """ + return self.nodes_manager.default_node + + def set_default_node(self, node): + """ + Set the default node of the cluster. + :param node: 'ClusterNode' + :return True if the default node was set, else False + """ + if node is None or self.get_node(node_name=node.name) is None: + return False + self.nodes_manager.default_node = node + return True + + def get_retry(self) -> Optional["Retry"]: + return self.retry + + def set_retry(self, retry: "Retry") -> None: + self.retry = retry + for node in self.get_nodes(): + node.redis_connection.set_retry(retry) + + def monitor(self, target_node=None): + """ + Returns a Monitor object for the specified target node. + The default cluster node will be selected if no target node was + specified. + Monitor is useful for handling the MONITOR command to the redis server. + next_command() method returns one command from monitor + listen() method yields commands from monitor. + """ + if target_node is None: + target_node = self.get_default_node() + if target_node.redis_connection is None: + raise RedisClusterException( + f"Cluster Node {target_node.name} has no redis_connection" + ) + return target_node.redis_connection.monitor() + + def pubsub(self, node=None, host=None, port=None, **kwargs): + """ + Allows passing a ClusterNode, or host&port, to get a pubsub instance + connected to the specified node + """ + return ClusterPubSub(self, node=node, host=host, port=port, **kwargs) + + def pipeline(self, transaction=None, shard_hint=None): + """ + Cluster impl: + Pipelines do not work in cluster mode the same way they + do in normal mode. Create a clone of this object so + that simulating pipelines will work correctly. Each + command will be called directly when used and + when calling execute() will only return the result stack. + """ + if shard_hint: + raise RedisClusterException("shard_hint is deprecated in cluster mode") + + if transaction: + raise RedisClusterException("transaction is deprecated in cluster mode") + + return ClusterPipeline( + nodes_manager=self.nodes_manager, + commands_parser=self.commands_parser, + startup_nodes=self.nodes_manager.startup_nodes, + result_callbacks=self.result_callbacks, + cluster_response_callbacks=self.cluster_response_callbacks, + cluster_error_retry_attempts=self.cluster_error_retry_attempts, + read_from_replicas=self.read_from_replicas, + reinitialize_steps=self.reinitialize_steps, + lock=self._lock, + ) + + def lock( + self, + name, + timeout=None, + sleep=0.1, + blocking=True, + blocking_timeout=None, + lock_class=None, + thread_local=True, + ): + """ + Return a new Lock object using key ``name`` that mimics + the behavior of threading.Lock. + + If specified, ``timeout`` indicates a maximum life for the lock. + By default, it will remain locked until release() is called. + + ``sleep`` indicates the amount of time to sleep per loop iteration + when the lock is in blocking mode and another client is currently + holding the lock. + + ``blocking`` indicates whether calling ``acquire`` should block until + the lock has been acquired or to fail immediately, causing ``acquire`` + to return False and the lock not being acquired. Defaults to True. + Note this value can be overridden by passing a ``blocking`` + argument to ``acquire``. + + ``blocking_timeout`` indicates the maximum amount of time in seconds to + spend trying to acquire the lock. A value of ``None`` indicates + continue trying forever. ``blocking_timeout`` can be specified as a + float or integer, both representing the number of seconds to wait. + + ``lock_class`` forces the specified lock implementation. Note that as + of redis-py 3.0, the only lock class we implement is ``Lock`` (which is + a Lua-based lock). So, it's unlikely you'll need this parameter, unless + you have created your own custom lock class. + + ``thread_local`` indicates whether the lock token is placed in + thread-local storage. By default, the token is placed in thread local + storage so that a thread only sees its token, not a token set by + another thread. Consider the following timeline: + + time: 0, thread-1 acquires `my-lock`, with a timeout of 5 seconds. + thread-1 sets the token to "abc" + time: 1, thread-2 blocks trying to acquire `my-lock` using the + Lock instance. + time: 5, thread-1 has not yet completed. redis expires the lock + key. + time: 5, thread-2 acquired `my-lock` now that it's available. + thread-2 sets the token to "xyz" + time: 6, thread-1 finishes its work and calls release(). if the + token is *not* stored in thread local storage, then + thread-1 would see the token value as "xyz" and would be + able to successfully release the thread-2's lock. + + In some use cases it's necessary to disable thread local storage. For + example, if you have code where one thread acquires a lock and passes + that lock instance to a worker thread to release later. If thread + local storage isn't disabled in this case, the worker thread won't see + the token set by the thread that acquired the lock. Our assumption + is that these cases aren't common and as such default to using + thread local storage.""" + if lock_class is None: + lock_class = Lock + return lock_class( + self, + name, + timeout=timeout, + sleep=sleep, + blocking=blocking, + blocking_timeout=blocking_timeout, + thread_local=thread_local, + ) + + def set_response_callback(self, command, callback): + """Set a custom Response Callback""" + self.cluster_response_callbacks[command] = callback + + def _determine_nodes(self, *args, **kwargs) -> List["ClusterNode"]: + # Determine which nodes should be executed the command on. + # Returns a list of target nodes. + command = args[0].upper() + if len(args) >= 2 and f"{args[0]} {args[1]}".upper() in self.command_flags: + command = f"{args[0]} {args[1]}".upper() + + nodes_flag = kwargs.pop("nodes_flag", None) + if nodes_flag is not None: + # nodes flag passed by the user + command_flag = nodes_flag + else: + # get the nodes group for this command if it was predefined + command_flag = self.command_flags.get(command) + if command_flag == self.__class__.RANDOM: + # return a random node + return [self.get_random_node()] + elif command_flag == self.__class__.PRIMARIES: + # return all primaries + return self.get_primaries() + elif command_flag == self.__class__.REPLICAS: + # return all replicas + return self.get_replicas() + elif command_flag == self.__class__.ALL_NODES: + # return all nodes + return self.get_nodes() + elif command_flag == self.__class__.DEFAULT_NODE: + # return the cluster's default node + return [self.nodes_manager.default_node] + elif command in self.__class__.SEARCH_COMMANDS[0]: + return [self.nodes_manager.default_node] + else: + # get the node that holds the key's slot + slot = self.determine_slot(*args) + node = self.nodes_manager.get_node_from_slot( + slot, self.read_from_replicas and command in READ_COMMANDS + ) + return [node] + + def _should_reinitialized(self): + # To reinitialize the cluster on every MOVED error, + # set reinitialize_steps to 1. + # To avoid reinitializing the cluster on moved errors, set + # reinitialize_steps to 0. + if self.reinitialize_steps == 0: + return False + else: + return self.reinitialize_counter % self.reinitialize_steps == 0 + + def keyslot(self, key): + """ + Calculate keyslot for a given key. + See Keys distribution model in https://redis.io/topics/cluster-spec + """ + k = self.encoder.encode(key) + return key_slot(k) + + def _get_command_keys(self, *args): + """ + Get the keys in the command. If the command has no keys in in, None is + returned. + + NOTE: Due to a bug in redis<7.0, this function does not work properly + for EVAL or EVALSHA when the `numkeys` arg is 0. + - issue: https://github.com/redis/redis/issues/9493 + - fix: https://github.com/redis/redis/pull/9733 + + So, don't use this function with EVAL or EVALSHA. + """ + redis_conn = self.get_default_node().redis_connection + return self.commands_parser.get_keys(redis_conn, *args) + + def determine_slot(self, *args): + """ + Figure out what slot to use based on args. + + Raises a RedisClusterException if there's a missing key and we can't + determine what slots to map the command to; or, if the keys don't + all map to the same key slot. + """ + command = args[0] + if self.command_flags.get(command) == SLOT_ID: + # The command contains the slot ID + return args[1] + + # Get the keys in the command + + # EVAL and EVALSHA are common enough that it's wasteful to go to the + # redis server to parse the keys. Besides, there is a bug in redis<7.0 + # where `self._get_command_keys()` fails anyway. So, we special case + # EVAL/EVALSHA. + if command.upper() in ("EVAL", "EVALSHA"): + # command syntax: EVAL "script body" num_keys ... + if len(args) <= 2: + raise RedisClusterException(f"Invalid args in command: {args}") + num_actual_keys = int(args[2]) + eval_keys = args[3 : 3 + num_actual_keys] + # if there are 0 keys, that means the script can be run on any node + # so we can just return a random slot + if len(eval_keys) == 0: + return random.randrange(0, REDIS_CLUSTER_HASH_SLOTS) + keys = eval_keys + else: + keys = self._get_command_keys(*args) + if keys is None or len(keys) == 0: + # FCALL can call a function with 0 keys, that means the function + # can be run on any node so we can just return a random slot + if command.upper() in ("FCALL", "FCALL_RO"): + return random.randrange(0, REDIS_CLUSTER_HASH_SLOTS) + raise RedisClusterException( + "No way to dispatch this command to Redis Cluster. " + "Missing key.\nYou can execute the command by specifying " + f"target nodes.\nCommand: {args}" + ) + + # single key command + if len(keys) == 1: + return self.keyslot(keys[0]) + + # multi-key command; we need to make sure all keys are mapped to + # the same slot + slots = {self.keyslot(key) for key in keys} + if len(slots) != 1: + raise RedisClusterException( + f"{command} - all keys must map to the same key slot" + ) + + return slots.pop() + + def get_encoder(self): + """ + Get the connections' encoder + """ + return self.encoder + + def get_connection_kwargs(self): + """ + Get the connections' key-word arguments + """ + return self.nodes_manager.connection_kwargs + + def _is_nodes_flag(self, target_nodes): + return isinstance(target_nodes, str) and target_nodes in self.node_flags + + def _parse_target_nodes(self, target_nodes): + if isinstance(target_nodes, list): + nodes = target_nodes + elif isinstance(target_nodes, ClusterNode): + # Supports passing a single ClusterNode as a variable + nodes = [target_nodes] + elif isinstance(target_nodes, dict): + # Supports dictionaries of the format {node_name: node}. + # It enables to execute commands with multi nodes as follows: + # rc.cluster_save_config(rc.get_primaries()) + nodes = target_nodes.values() + else: + raise TypeError( + "target_nodes type can be one of the following: " + "node_flag (PRIMARIES, REPLICAS, RANDOM, ALL_NODES)," + "ClusterNode, list, or dict. " + f"The passed type is {type(target_nodes)}" + ) + return nodes + + def execute_command(self, *args, **kwargs): + """ + Wrapper for ERRORS_ALLOW_RETRY error handling. + + It will try the number of times specified by the config option + "self.cluster_error_retry_attempts" which defaults to 3 unless manually + configured. + + If it reaches the number of times, the command will raise the exception + + Key argument :target_nodes: can be passed with the following types: + nodes_flag: PRIMARIES, REPLICAS, ALL_NODES, RANDOM + ClusterNode + list + dict + """ + target_nodes_specified = False + is_default_node = False + target_nodes = None + passed_targets = kwargs.pop("target_nodes", None) + if passed_targets is not None and not self._is_nodes_flag(passed_targets): + target_nodes = self._parse_target_nodes(passed_targets) + target_nodes_specified = True + # If an error that allows retrying was thrown, the nodes and slots + # cache were reinitialized. We will retry executing the command with + # the updated cluster setup only when the target nodes can be + # determined again with the new cache tables. Therefore, when target + # nodes were passed to this function, we cannot retry the command + # execution since the nodes may not be valid anymore after the tables + # were reinitialized. So in case of passed target nodes, + # retry_attempts will be set to 0. + retry_attempts = ( + 0 if target_nodes_specified else self.cluster_error_retry_attempts + ) + # Add one for the first execution + execute_attempts = 1 + retry_attempts + for _ in range(execute_attempts): + try: + res = {} + if not target_nodes_specified: + # Determine the nodes to execute the command on + target_nodes = self._determine_nodes( + *args, **kwargs, nodes_flag=passed_targets + ) + if not target_nodes: + raise RedisClusterException( + f"No targets were found to execute {args} command on" + ) + if ( + len(target_nodes) == 1 + and target_nodes[0] == self.get_default_node() + ): + is_default_node = True + for node in target_nodes: + res[node.name] = self._execute_command(node, *args, **kwargs) + # Return the processed result + return self._process_result(args[0], res, **kwargs) + except Exception as e: + if retry_attempts > 0 and type(e) in self.__class__.ERRORS_ALLOW_RETRY: + if is_default_node: + # Replace the default cluster node + self.replace_default_node() + # The nodes and slots cache were reinitialized. + # Try again with the new cluster setup. + retry_attempts -= 1 + continue + else: + # raise the exception + raise e + + def _execute_command(self, target_node, *args, **kwargs): + """ + Send a command to a node in the cluster + """ + command = args[0] + redis_node = None + connection = None + redirect_addr = None + asking = False + moved = False + ttl = int(self.RedisClusterRequestTTL) + + while ttl > 0: + ttl -= 1 + try: + if asking: + target_node = self.get_node(node_name=redirect_addr) + elif moved: + # MOVED occurred and the slots cache was updated, + # refresh the target node + slot = self.determine_slot(*args) + target_node = self.nodes_manager.get_node_from_slot( + slot, self.read_from_replicas and command in READ_COMMANDS + ) + moved = False + + redis_node = self.get_redis_connection(target_node) + connection = get_connection(redis_node, *args, **kwargs) + if asking: + connection.send_command("ASKING") + redis_node.parse_response(connection, "ASKING", **kwargs) + asking = False + + connection.send_command(*args) + response = redis_node.parse_response(connection, command, **kwargs) + if command in self.cluster_response_callbacks: + response = self.cluster_response_callbacks[command]( + response, **kwargs + ) + return response + except AuthenticationError: + raise + except (ConnectionError, TimeoutError) as e: + # Connection retries are being handled in the node's + # Retry object. + # ConnectionError can also be raised if we couldn't get a + # connection from the pool before timing out, so check that + # this is an actual connection before attempting to disconnect. + if connection is not None: + connection.disconnect() + + # Remove the failed node from the startup nodes before we try + # to reinitialize the cluster + self.nodes_manager.startup_nodes.pop(target_node.name, None) + # Reset the cluster node's connection + target_node.redis_connection = None + self.nodes_manager.initialize() + raise e + except MovedError as e: + # First, we will try to patch the slots/nodes cache with the + # redirected node output and try again. If MovedError exceeds + # 'reinitialize_steps' number of times, we will force + # reinitializing the tables, and then try again. + # 'reinitialize_steps' counter will increase faster when + # the same client object is shared between multiple threads. To + # reduce the frequency you can set this variable in the + # RedisCluster constructor. + self.reinitialize_counter += 1 + if self._should_reinitialized(): + self.nodes_manager.initialize() + # Reset the counter + self.reinitialize_counter = 0 + else: + self.nodes_manager.update_moved_exception(e) + moved = True + except TryAgainError: + if ttl < self.RedisClusterRequestTTL / 2: + time.sleep(0.05) + except AskError as e: + redirect_addr = get_node_name(host=e.host, port=e.port) + asking = True + except ClusterDownError as e: + # ClusterDownError can occur during a failover and to get + # self-healed, we will try to reinitialize the cluster layout + # and retry executing the command + time.sleep(0.25) + self.nodes_manager.initialize() + raise e + except ResponseError: + raise + except Exception as e: + if connection: + connection.disconnect() + raise e + finally: + if connection is not None: + redis_node.connection_pool.release(connection) + + raise ClusterError("TTL exhausted.") + + def close(self): + try: + with self._lock: + if self.nodes_manager: + self.nodes_manager.close() + except AttributeError: + # RedisCluster's __init__ can fail before nodes_manager is set + pass + + def _process_result(self, command, res, **kwargs): + """ + Process the result of the executed command. + The function would return a dict or a single value. + + :type command: str + :type res: dict + + `res` should be in the following format: + Dict + """ + if command in self.result_callbacks: + return self.result_callbacks[command](command, res, **kwargs) + elif len(res) == 1: + # When we execute the command on a single node, we can + # remove the dictionary and return a single response + return list(res.values())[0] + else: + return res + + def load_external_module(self, funcname, func): + """ + This function can be used to add externally defined redis modules, + and their namespaces to the redis client. + + ``funcname`` - A string containing the name of the function to create + ``func`` - The function, being added to this class. + """ + setattr(self, funcname, func) + + +class ClusterNode: + def __init__(self, host, port, server_type=None, redis_connection=None): + if host == "localhost": + host = socket.gethostbyname(host) + + self.host = host + self.port = port + self.name = get_node_name(host, port) + self.server_type = server_type + self.redis_connection = redis_connection + + def __repr__(self): + return ( + f"[host={self.host}," + f"port={self.port}," + f"name={self.name}," + f"server_type={self.server_type}," + f"redis_connection={self.redis_connection}]" + ) + + def __eq__(self, obj): + return isinstance(obj, ClusterNode) and obj.name == self.name + + def __del__(self): + if self.redis_connection is not None: + self.redis_connection.close() + + +class LoadBalancer: + """ + Round-Robin Load Balancing + """ + + def __init__(self, start_index: int = 0) -> None: + self.primary_to_idx = {} + self.start_index = start_index + + def get_server_index(self, primary: str, list_size: int) -> int: + server_index = self.primary_to_idx.setdefault(primary, self.start_index) + # Update the index + self.primary_to_idx[primary] = (server_index + 1) % list_size + return server_index + + def reset(self) -> None: + self.primary_to_idx.clear() + + +class NodesManager: + def __init__( + self, + startup_nodes, + from_url=False, + require_full_coverage=False, + lock=None, + dynamic_startup_nodes=True, + connection_pool_class=ConnectionPool, + address_remap: Optional[Callable[[str, int], Tuple[str, int]]] = None, + **kwargs, + ): + self.nodes_cache = {} + self.slots_cache = {} + self.startup_nodes = {} + self.default_node = None + self.populate_startup_nodes(startup_nodes) + self.from_url = from_url + self._require_full_coverage = require_full_coverage + self._dynamic_startup_nodes = dynamic_startup_nodes + self.connection_pool_class = connection_pool_class + self.address_remap = address_remap + self._moved_exception = None + self.connection_kwargs = kwargs + self.read_load_balancer = LoadBalancer() + if lock is None: + lock = threading.Lock() + self._lock = lock + self.initialize() + + def get_node(self, host=None, port=None, node_name=None): + """ + Get the requested node from the cluster's nodes. + nodes. + :return: ClusterNode if the node exists, else None + """ + if host and port: + # the user passed host and port + if host == "localhost": + host = socket.gethostbyname(host) + return self.nodes_cache.get(get_node_name(host=host, port=port)) + elif node_name: + return self.nodes_cache.get(node_name) + else: + return None + + def update_moved_exception(self, exception): + self._moved_exception = exception + + def _update_moved_slots(self): + """ + Update the slot's node with the redirected one + """ + e = self._moved_exception + redirected_node = self.get_node(host=e.host, port=e.port) + if redirected_node is not None: + # The node already exists + if redirected_node.server_type is not PRIMARY: + # Update the node's server type + redirected_node.server_type = PRIMARY + else: + # This is a new node, we will add it to the nodes cache + redirected_node = ClusterNode(e.host, e.port, PRIMARY) + self.nodes_cache[redirected_node.name] = redirected_node + if redirected_node in self.slots_cache[e.slot_id]: + # The MOVED error resulted from a failover, and the new slot owner + # had previously been a replica. + old_primary = self.slots_cache[e.slot_id][0] + # Update the old primary to be a replica and add it to the end of + # the slot's node list + old_primary.server_type = REPLICA + self.slots_cache[e.slot_id].append(old_primary) + # Remove the old replica, which is now a primary, from the slot's + # node list + self.slots_cache[e.slot_id].remove(redirected_node) + # Override the old primary with the new one + self.slots_cache[e.slot_id][0] = redirected_node + if self.default_node == old_primary: + # Update the default node with the new primary + self.default_node = redirected_node + else: + # The new slot owner is a new server, or a server from a different + # shard. We need to remove all current nodes from the slot's list + # (including replications) and add just the new node. + self.slots_cache[e.slot_id] = [redirected_node] + # Reset moved_exception + self._moved_exception = None + + def get_node_from_slot(self, slot, read_from_replicas=False, server_type=None): + """ + Gets a node that servers this hash slot + """ + if self._moved_exception: + with self._lock: + if self._moved_exception: + self._update_moved_slots() + + if self.slots_cache.get(slot) is None or len(self.slots_cache[slot]) == 0: + raise SlotNotCoveredError( + f'Slot "{slot}" not covered by the cluster. ' + f'"require_full_coverage={self._require_full_coverage}"' + ) + + if read_from_replicas is True: + # get the server index in a Round-Robin manner + primary_name = self.slots_cache[slot][0].name + node_idx = self.read_load_balancer.get_server_index( + primary_name, len(self.slots_cache[slot]) + ) + elif ( + server_type is None + or server_type == PRIMARY + or len(self.slots_cache[slot]) == 1 + ): + # return a primary + node_idx = 0 + else: + # return a replica + # randomly choose one of the replicas + node_idx = random.randint(1, len(self.slots_cache[slot]) - 1) + + return self.slots_cache[slot][node_idx] + + def get_nodes_by_server_type(self, server_type): + """ + Get all nodes with the specified server type + :param server_type: 'primary' or 'replica' + :return: list of ClusterNode + """ + return [ + node + for node in self.nodes_cache.values() + if node.server_type == server_type + ] + + def populate_startup_nodes(self, nodes): + """ + Populate all startup nodes and filters out any duplicates + """ + for n in nodes: + self.startup_nodes[n.name] = n + + def check_slots_coverage(self, slots_cache): + # Validate if all slots are covered or if we should try next + # startup node + for i in range(0, REDIS_CLUSTER_HASH_SLOTS): + if i not in slots_cache: + return False + return True + + def create_redis_connections(self, nodes): + """ + This function will create a redis connection to all nodes in :nodes: + """ + for node in nodes: + if node.redis_connection is None: + node.redis_connection = self.create_redis_node( + host=node.host, port=node.port, **self.connection_kwargs + ) + + def create_redis_node(self, host, port, **kwargs): + if self.from_url: + # Create a redis node with a costumed connection pool + kwargs.update({"host": host}) + kwargs.update({"port": port}) + r = Redis(connection_pool=self.connection_pool_class(**kwargs)) + else: + r = Redis(host=host, port=port, **kwargs) + return r + + def _get_or_create_cluster_node(self, host, port, role, tmp_nodes_cache): + node_name = get_node_name(host, port) + # check if we already have this node in the tmp_nodes_cache + target_node = tmp_nodes_cache.get(node_name) + if target_node is None: + # before creating a new cluster node, check if the cluster node already + # exists in the current nodes cache and has a valid connection so we can + # reuse it + target_node = self.nodes_cache.get(node_name) + if target_node is None or target_node.redis_connection is None: + # create new cluster node for this cluster + target_node = ClusterNode(host, port, role) + if target_node.server_type != role: + target_node.server_type = role + + return target_node + + def initialize(self): + """ + Initializes the nodes cache, slots cache and redis connections. + :startup_nodes: + Responsible for discovering other nodes in the cluster + """ + self.reset() + tmp_nodes_cache = {} + tmp_slots = {} + disagreements = [] + startup_nodes_reachable = False + fully_covered = False + kwargs = self.connection_kwargs + exception = None + for startup_node in self.startup_nodes.values(): + try: + if startup_node.redis_connection: + r = startup_node.redis_connection + else: + # Create a new Redis connection + r = self.create_redis_node( + startup_node.host, startup_node.port, **kwargs + ) + self.startup_nodes[startup_node.name].redis_connection = r + # Make sure cluster mode is enabled on this node + if bool(r.info().get("cluster_enabled")) is False: + raise RedisClusterException( + "Cluster mode is not enabled on this node" + ) + cluster_slots = str_if_bytes(r.execute_command("CLUSTER SLOTS")) + startup_nodes_reachable = True + except Exception as e: + # Try the next startup node. + # The exception is saved and raised only if we have no more nodes. + exception = e + continue + + # CLUSTER SLOTS command results in the following output: + # [[slot_section[from_slot,to_slot,master,replica1,...,replicaN]]] + # where each node contains the following list: [IP, port, node_id] + # Therefore, cluster_slots[0][2][0] will be the IP address of the + # primary node of the first slot section. + # If there's only one server in the cluster, its ``host`` is '' + # Fix it to the host in startup_nodes + if ( + len(cluster_slots) == 1 + and len(cluster_slots[0][2][0]) == 0 + and len(self.startup_nodes) == 1 + ): + cluster_slots[0][2][0] = startup_node.host + + for slot in cluster_slots: + primary_node = slot[2] + host = str_if_bytes(primary_node[0]) + if host == "": + host = startup_node.host + port = int(primary_node[1]) + host, port = self.remap_host_port(host, port) + + target_node = self._get_or_create_cluster_node( + host, port, PRIMARY, tmp_nodes_cache + ) + # add this node to the nodes cache + tmp_nodes_cache[target_node.name] = target_node + + for i in range(int(slot[0]), int(slot[1]) + 1): + if i not in tmp_slots: + tmp_slots[i] = [] + tmp_slots[i].append(target_node) + replica_nodes = [slot[j] for j in range(3, len(slot))] + + for replica_node in replica_nodes: + host = str_if_bytes(replica_node[0]) + port = replica_node[1] + host, port = self.remap_host_port(host, port) + + target_replica_node = self._get_or_create_cluster_node( + host, port, REPLICA, tmp_nodes_cache + ) + tmp_slots[i].append(target_replica_node) + # add this node to the nodes cache + tmp_nodes_cache[ + target_replica_node.name + ] = target_replica_node + else: + # Validate that 2 nodes want to use the same slot cache + # setup + tmp_slot = tmp_slots[i][0] + if tmp_slot.name != target_node.name: + disagreements.append( + f"{tmp_slot.name} vs {target_node.name} on slot: {i}" + ) + + if len(disagreements) > 5: + raise RedisClusterException( + f"startup_nodes could not agree on a valid " + f'slots cache: {", ".join(disagreements)}' + ) + + fully_covered = self.check_slots_coverage(tmp_slots) + if fully_covered: + # Don't need to continue to the next startup node if all + # slots are covered + break + + if not startup_nodes_reachable: + raise RedisClusterException( + f"Redis Cluster cannot be connected. Please provide at least " + f"one reachable node: {str(exception)}" + ) from exception + + # Create Redis connections to all nodes + self.create_redis_connections(list(tmp_nodes_cache.values())) + + # Check if the slots are not fully covered + if not fully_covered and self._require_full_coverage: + # Despite the requirement that the slots be covered, there + # isn't a full coverage + raise RedisClusterException( + f"All slots are not covered after query all startup_nodes. " + f"{len(tmp_slots)} of {REDIS_CLUSTER_HASH_SLOTS} " + f"covered..." + ) + + # Set the tmp variables to the real variables + self.nodes_cache = tmp_nodes_cache + self.slots_cache = tmp_slots + # Set the default node + self.default_node = self.get_nodes_by_server_type(PRIMARY)[0] + if self._dynamic_startup_nodes: + # Populate the startup nodes with all discovered nodes + self.startup_nodes = tmp_nodes_cache + # If initialize was called after a MovedError, clear it + self._moved_exception = None + + def close(self): + self.default_node = None + for node in self.nodes_cache.values(): + if node.redis_connection: + node.redis_connection.close() + + def reset(self): + try: + self.read_load_balancer.reset() + except TypeError: + # The read_load_balancer is None, do nothing + pass + + def remap_host_port(self, host: str, port: int) -> Tuple[str, int]: + """ + Remap the host and port returned from the cluster to a different + internal value. Useful if the client is not connecting directly + to the cluster. + """ + if self.address_remap: + return self.address_remap((host, port)) + return host, port + + +class ClusterPubSub(PubSub): + """ + Wrapper for PubSub class. + + IMPORTANT: before using ClusterPubSub, read about the known limitations + with pubsub in Cluster mode and learn how to workaround them: + https://redis-py-cluster.readthedocs.io/en/stable/pubsub.html + """ + + def __init__( + self, + redis_cluster, + node=None, + host=None, + port=None, + push_handler_func=None, + **kwargs, + ): + """ + When a pubsub instance is created without specifying a node, a single + node will be transparently chosen for the pubsub connection on the + first command execution. The node will be determined by: + 1. Hashing the channel name in the request to find its keyslot + 2. Selecting a node that handles the keyslot: If read_from_replicas is + set to true, a replica can be selected. + + :type redis_cluster: RedisCluster + :type node: ClusterNode + :type host: str + :type port: int + """ + self.node = None + self.set_pubsub_node(redis_cluster, node, host, port) + connection_pool = ( + None + if self.node is None + else redis_cluster.get_redis_connection(self.node).connection_pool + ) + self.cluster = redis_cluster + self.node_pubsub_mapping = {} + self._pubsubs_generator = self._pubsubs_generator() + super().__init__( + connection_pool=connection_pool, + encoder=redis_cluster.encoder, + push_handler_func=push_handler_func, + **kwargs, + ) + + def set_pubsub_node(self, cluster, node=None, host=None, port=None): + """ + The pubsub node will be set according to the passed node, host and port + When none of the node, host, or port are specified - the node is set + to None and will be determined by the keyslot of the channel in the + first command to be executed. + RedisClusterException will be thrown if the passed node does not exist + in the cluster. + If host is passed without port, or vice versa, a DataError will be + thrown. + :type cluster: RedisCluster + :type node: ClusterNode + :type host: str + :type port: int + """ + if node is not None: + # node is passed by the user + self._raise_on_invalid_node(cluster, node, node.host, node.port) + pubsub_node = node + elif host is not None and port is not None: + # host and port passed by the user + node = cluster.get_node(host=host, port=port) + self._raise_on_invalid_node(cluster, node, host, port) + pubsub_node = node + elif any([host, port]) is True: + # only 'host' or 'port' passed + raise DataError("Passing a host requires passing a port, and vice versa") + else: + # nothing passed by the user. set node to None + pubsub_node = None + + self.node = pubsub_node + + def get_pubsub_node(self): + """ + Get the node that is being used as the pubsub connection + """ + return self.node + + def _raise_on_invalid_node(self, redis_cluster, node, host, port): + """ + Raise a RedisClusterException if the node is None or doesn't exist in + the cluster. + """ + if node is None or redis_cluster.get_node(node_name=node.name) is None: + raise RedisClusterException( + f"Node {host}:{port} doesn't exist in the cluster" + ) + + def execute_command(self, *args): + """ + Execute a subscribe/unsubscribe command. + + Taken code from redis-py and tweak to make it work within a cluster. + """ + # NOTE: don't parse the response in this function -- it could pull a + # legitimate message off the stack if the connection is already + # subscribed to one or more channels + + if self.connection is None: + if self.connection_pool is None: + if len(args) > 1: + # Hash the first channel and get one of the nodes holding + # this slot + channel = args[1] + slot = self.cluster.keyslot(channel) + node = self.cluster.nodes_manager.get_node_from_slot( + slot, self.cluster.read_from_replicas + ) + else: + # Get a random node + node = self.cluster.get_random_node() + self.node = node + redis_connection = self.cluster.get_redis_connection(node) + self.connection_pool = redis_connection.connection_pool + self.connection = self.connection_pool.get_connection( + "pubsub", self.shard_hint + ) + # register a callback that re-subscribes to any channels we + # were listening to when we were disconnected + self.connection._register_connect_callback(self.on_connect) + if self.push_handler_func is not None and not HIREDIS_AVAILABLE: + self.connection._parser.set_push_handler(self.push_handler_func) + connection = self.connection + self._execute(connection, connection.send_command, *args) + + def _get_node_pubsub(self, node): + try: + return self.node_pubsub_mapping[node.name] + except KeyError: + pubsub = node.redis_connection.pubsub( + push_handler_func=self.push_handler_func + ) + self.node_pubsub_mapping[node.name] = pubsub + return pubsub + + def _sharded_message_generator(self): + for _ in range(len(self.node_pubsub_mapping)): + pubsub = next(self._pubsubs_generator) + message = pubsub.get_message() + if message is not None: + return message + return None + + def _pubsubs_generator(self): + while True: + for pubsub in self.node_pubsub_mapping.values(): + yield pubsub + + def get_sharded_message( + self, ignore_subscribe_messages=False, timeout=0.0, target_node=None + ): + if target_node: + message = self.node_pubsub_mapping[target_node.name].get_message( + ignore_subscribe_messages=ignore_subscribe_messages, timeout=timeout + ) + else: + message = self._sharded_message_generator() + if message is None: + return None + elif str_if_bytes(message["type"]) == "sunsubscribe": + if message["channel"] in self.pending_unsubscribe_shard_channels: + self.pending_unsubscribe_shard_channels.remove(message["channel"]) + self.shard_channels.pop(message["channel"], None) + node = self.cluster.get_node_from_key(message["channel"]) + if self.node_pubsub_mapping[node.name].subscribed is False: + self.node_pubsub_mapping.pop(node.name) + if not self.channels and not self.patterns and not self.shard_channels: + # There are no subscriptions anymore, set subscribed_event flag + # to false + self.subscribed_event.clear() + if self.ignore_subscribe_messages or ignore_subscribe_messages: + return None + return message + + def ssubscribe(self, *args, **kwargs): + if args: + args = list_or_args(args[0], args[1:]) + s_channels = dict.fromkeys(args) + s_channels.update(kwargs) + for s_channel, handler in s_channels.items(): + node = self.cluster.get_node_from_key(s_channel) + pubsub = self._get_node_pubsub(node) + if handler: + pubsub.ssubscribe(**{s_channel: handler}) + else: + pubsub.ssubscribe(s_channel) + self.shard_channels.update(pubsub.shard_channels) + self.pending_unsubscribe_shard_channels.difference_update( + self._normalize_keys({s_channel: None}) + ) + if pubsub.subscribed and not self.subscribed: + self.subscribed_event.set() + self.health_check_response_counter = 0 + + def sunsubscribe(self, *args): + if args: + args = list_or_args(args[0], args[1:]) + else: + args = self.shard_channels + + for s_channel in args: + node = self.cluster.get_node_from_key(s_channel) + p = self._get_node_pubsub(node) + p.sunsubscribe(s_channel) + self.pending_unsubscribe_shard_channels.update( + p.pending_unsubscribe_shard_channels + ) + + def get_redis_connection(self): + """ + Get the Redis connection of the pubsub connected node. + """ + if self.node is not None: + return self.node.redis_connection + + def disconnect(self): + """ + Disconnect the pubsub connection. + """ + if self.connection: + self.connection.disconnect() + for pubsub in self.node_pubsub_mapping.values(): + pubsub.connection.disconnect() + + +class ClusterPipeline(RedisCluster): + """ + Support for Redis pipeline + in cluster mode + """ + + ERRORS_ALLOW_RETRY = ( + ConnectionError, + TimeoutError, + MovedError, + AskError, + TryAgainError, + ) + + def __init__( + self, + nodes_manager: "NodesManager", + commands_parser: "CommandsParser", + result_callbacks: Optional[Dict[str, Callable]] = None, + cluster_response_callbacks: Optional[Dict[str, Callable]] = None, + startup_nodes: Optional[List["ClusterNode"]] = None, + read_from_replicas: bool = False, + cluster_error_retry_attempts: int = 3, + reinitialize_steps: int = 5, + lock=None, + **kwargs, + ): + """ """ + self.command_stack = [] + self.nodes_manager = nodes_manager + self.commands_parser = commands_parser + self.refresh_table_asap = False + self.result_callbacks = ( + result_callbacks or self.__class__.RESULT_CALLBACKS.copy() + ) + self.startup_nodes = startup_nodes if startup_nodes else [] + self.read_from_replicas = read_from_replicas + self.command_flags = self.__class__.COMMAND_FLAGS.copy() + self.cluster_response_callbacks = cluster_response_callbacks + self.cluster_error_retry_attempts = cluster_error_retry_attempts + self.reinitialize_counter = 0 + self.reinitialize_steps = reinitialize_steps + self.encoder = Encoder( + kwargs.get("encoding", "utf-8"), + kwargs.get("encoding_errors", "strict"), + kwargs.get("decode_responses", False), + ) + if lock is None: + lock = threading.Lock() + self._lock = lock + + def __repr__(self): + """ """ + return f"{type(self).__name__}" + + def __enter__(self): + """ """ + return self + + def __exit__(self, exc_type, exc_value, traceback): + """ """ + self.reset() + + def __del__(self): + try: + self.reset() + except Exception: + pass + + def __len__(self): + """ """ + return len(self.command_stack) + + def __bool__(self): + "Pipeline instances should always evaluate to True on Python 3+" + return True + + def execute_command(self, *args, **kwargs): + """ + Wrapper function for pipeline_execute_command + """ + return self.pipeline_execute_command(*args, **kwargs) + + def pipeline_execute_command(self, *args, **options): + """ + Appends the executed command to the pipeline's command stack + """ + self.command_stack.append( + PipelineCommand(args, options, len(self.command_stack)) + ) + return self + + def raise_first_error(self, stack): + """ + Raise the first exception on the stack + """ + for c in stack: + r = c.result + if isinstance(r, Exception): + self.annotate_exception(r, c.position + 1, c.args) + raise r + + def annotate_exception(self, exception, number, command): + """ + Provides extra context to the exception prior to it being handled + """ + cmd = " ".join(map(safe_str, command)) + msg = ( + f"Command # {number} ({cmd}) of pipeline " + f"caused error: {exception.args[0]}" + ) + exception.args = (msg,) + exception.args[1:] + + def execute(self, raise_on_error=True): + """ + Execute all the commands in the current pipeline + """ + stack = self.command_stack + try: + return self.send_cluster_commands(stack, raise_on_error) + finally: + self.reset() + + def reset(self): + """ + Reset back to empty pipeline. + """ + self.command_stack = [] + + self.scripts = set() + + # TODO: Implement + # make sure to reset the connection state in the event that we were + # watching something + # if self.watching and self.connection: + # try: + # # call this manually since our unwatch or + # # immediate_execute_command methods can call reset() + # self.connection.send_command('UNWATCH') + # self.connection.read_response() + # except ConnectionError: + # # disconnect will also remove any previous WATCHes + # self.connection.disconnect() + + # clean up the other instance attributes + self.watching = False + self.explicit_transaction = False + + # TODO: Implement + # we can safely return the connection to the pool here since we're + # sure we're no longer WATCHing anything + # if self.connection: + # self.connection_pool.release(self.connection) + # self.connection = None + + def send_cluster_commands( + self, stack, raise_on_error=True, allow_redirections=True + ): + """ + Wrapper for CLUSTERDOWN error handling. + + If the cluster reports it is down it is assumed that: + - connection_pool was disconnected + - connection_pool was reseted + - refereh_table_asap set to True + + It will try the number of times specified by + the config option "self.cluster_error_retry_attempts" + which defaults to 3 unless manually configured. + + If it reaches the number of times, the command will + raises ClusterDownException. + """ + if not stack: + return [] + retry_attempts = self.cluster_error_retry_attempts + while True: + try: + return self._send_cluster_commands( + stack, + raise_on_error=raise_on_error, + allow_redirections=allow_redirections, + ) + except (ClusterDownError, ConnectionError) as e: + if retry_attempts > 0: + # Try again with the new cluster setup. All other errors + # should be raised. + retry_attempts -= 1 + pass + else: + raise e + + def _send_cluster_commands( + self, stack, raise_on_error=True, allow_redirections=True + ): + """ + Send a bunch of cluster commands to the redis cluster. + + `allow_redirections` If the pipeline should follow + `ASK` & `MOVED` responses automatically. If set + to false it will raise RedisClusterException. + """ + # the first time sending the commands we send all of + # the commands that were queued up. + # if we have to run through it again, we only retry + # the commands that failed. + attempt = sorted(stack, key=lambda x: x.position) + is_default_node = False + # build a list of node objects based on node names we need to + nodes = {} + + # as we move through each command that still needs to be processed, + # we figure out the slot number that command maps to, then from + # the slot determine the node. + for c in attempt: + while True: + # refer to our internal node -> slot table that + # tells us where a given command should route to. + # (it might be possible we have a cached node that no longer + # exists in the cluster, which is why we do this in a loop) + passed_targets = c.options.pop("target_nodes", None) + if passed_targets and not self._is_nodes_flag(passed_targets): + target_nodes = self._parse_target_nodes(passed_targets) + else: + target_nodes = self._determine_nodes( + *c.args, node_flag=passed_targets + ) + if not target_nodes: + raise RedisClusterException( + f"No targets were found to execute {c.args} command on" + ) + if len(target_nodes) > 1: + raise RedisClusterException( + f"Too many targets for command {c.args}" + ) + + node = target_nodes[0] + if node == self.get_default_node(): + is_default_node = True + + # now that we know the name of the node + # ( it's just a string in the form of host:port ) + # we can build a list of commands for each node. + node_name = node.name + if node_name not in nodes: + redis_node = self.get_redis_connection(node) + try: + connection = get_connection(redis_node, c.args) + except ConnectionError: + # Connection retries are being handled in the node's + # Retry object. Reinitialize the node -> slot table. + self.nodes_manager.initialize() + if is_default_node: + self.replace_default_node() + raise + nodes[node_name] = NodeCommands( + redis_node.parse_response, + redis_node.connection_pool, + connection, + ) + nodes[node_name].append(c) + break + + # send the commands in sequence. + # we write to all the open sockets for each node first, + # before reading anything + # this allows us to flush all the requests out across the + # network essentially in parallel + # so that we can read them all in parallel as they come back. + # we dont' multiplex on the sockets as they come available, + # but that shouldn't make too much difference. + node_commands = nodes.values() + for n in node_commands: + n.write() + + for n in node_commands: + n.read() + + # release all of the redis connections we allocated earlier + # back into the connection pool. + # we used to do this step as part of a try/finally block, + # but it is really dangerous to + # release connections back into the pool if for some + # reason the socket has data still left in it + # from a previous operation. The write and + # read operations already have try/catch around them for + # all known types of errors including connection + # and socket level errors. + # So if we hit an exception, something really bad + # happened and putting any oF + # these connections back into the pool is a very bad idea. + # the socket might have unread buffer still sitting in it, + # and then the next time we read from it we pass the + # buffered result back from a previous command and + # every single request after to that connection will always get + # a mismatched result. + for n in nodes.values(): + n.connection_pool.release(n.connection) + + # if the response isn't an exception it is a + # valid response from the node + # we're all done with that command, YAY! + # if we have more commands to attempt, we've run into problems. + # collect all the commands we are allowed to retry. + # (MOVED, ASK, or connection errors or timeout errors) + attempt = sorted( + ( + c + for c in attempt + if isinstance(c.result, ClusterPipeline.ERRORS_ALLOW_RETRY) + ), + key=lambda x: x.position, + ) + if attempt and allow_redirections: + # RETRY MAGIC HAPPENS HERE! + # send these remaing commands one at a time using `execute_command` + # in the main client. This keeps our retry logic + # in one place mostly, + # and allows us to be more confident in correctness of behavior. + # at this point any speed gains from pipelining have been lost + # anyway, so we might as well make the best + # attempt to get the correct behavior. + # + # The client command will handle retries for each + # individual command sequentially as we pass each + # one into `execute_command`. Any exceptions + # that bubble out should only appear once all + # retries have been exhausted. + # + # If a lot of commands have failed, we'll be setting the + # flag to rebuild the slots table from scratch. + # So MOVED errors should correct themselves fairly quickly. + self.reinitialize_counter += 1 + if self._should_reinitialized(): + self.nodes_manager.initialize() + if is_default_node: + self.replace_default_node() + for c in attempt: + try: + # send each command individually like we + # do in the main client. + c.result = super().execute_command(*c.args, **c.options) + except RedisError as e: + c.result = e + + # turn the response back into a simple flat array that corresponds + # to the sequence of commands issued in the stack in pipeline.execute() + response = [] + for c in sorted(stack, key=lambda x: x.position): + if c.args[0] in self.cluster_response_callbacks: + c.result = self.cluster_response_callbacks[c.args[0]]( + c.result, **c.options + ) + response.append(c.result) + + if raise_on_error: + self.raise_first_error(stack) + + return response + + def _fail_on_redirect(self, allow_redirections): + """ """ + if not allow_redirections: + raise RedisClusterException( + "ASK & MOVED redirection not allowed in this pipeline" + ) + + def exists(self, *keys): + return self.execute_command("EXISTS", *keys) + + def eval(self): + """ """ + raise RedisClusterException("method eval() is not implemented") + + def multi(self): + """ """ + raise RedisClusterException("method multi() is not implemented") + + def immediate_execute_command(self, *args, **options): + """ """ + raise RedisClusterException( + "method immediate_execute_command() is not implemented" + ) + + def _execute_transaction(self, *args, **kwargs): + """ """ + raise RedisClusterException("method _execute_transaction() is not implemented") + + def load_scripts(self): + """ """ + raise RedisClusterException("method load_scripts() is not implemented") + + def watch(self, *names): + """ """ + raise RedisClusterException("method watch() is not implemented") + + def unwatch(self): + """ """ + raise RedisClusterException("method unwatch() is not implemented") + + def script_load_for_pipeline(self, *args, **kwargs): + """ """ + raise RedisClusterException( + "method script_load_for_pipeline() is not implemented" + ) + + def delete(self, *names): + """ + "Delete a key specified by ``names``" + """ + if len(names) != 1: + raise RedisClusterException( + "deleting multiple keys is not implemented in pipeline command" + ) + + return self.execute_command("DEL", names[0]) + + def unlink(self, *names): + """ + "Unlink a key specified by ``names``" + """ + if len(names) != 1: + raise RedisClusterException( + "unlinking multiple keys is not implemented in pipeline command" + ) + + return self.execute_command("UNLINK", names[0]) + + +def block_pipeline_command(name: str) -> Callable[..., Any]: + """ + Prints error because some pipelined commands should + be blocked when running in cluster-mode + """ + + def inner(*args, **kwargs): + raise RedisClusterException( + f"ERROR: Calling pipelined function {name} is blocked " + f"when running redis in cluster mode..." + ) + + return inner + + +# Blocked pipeline commands +PIPELINE_BLOCKED_COMMANDS = ( + "BGREWRITEAOF", + "BGSAVE", + "BITOP", + "BRPOPLPUSH", + "CLIENT GETNAME", + "CLIENT KILL", + "CLIENT LIST", + "CLIENT SETNAME", + "CLIENT", + "CONFIG GET", + "CONFIG RESETSTAT", + "CONFIG REWRITE", + "CONFIG SET", + "CONFIG", + "DBSIZE", + "ECHO", + "EVALSHA", + "FLUSHALL", + "FLUSHDB", + "INFO", + "KEYS", + "LASTSAVE", + "MGET", + "MGET NONATOMIC", + "MOVE", + "MSET", + "MSET NONATOMIC", + "MSETNX", + "PFCOUNT", + "PFMERGE", + "PING", + "PUBLISH", + "RANDOMKEY", + "READONLY", + "READWRITE", + "RENAME", + "RENAMENX", + "RPOPLPUSH", + "SAVE", + "SCAN", + "SCRIPT EXISTS", + "SCRIPT FLUSH", + "SCRIPT KILL", + "SCRIPT LOAD", + "SCRIPT", + "SDIFF", + "SDIFFSTORE", + "SENTINEL GET MASTER ADDR BY NAME", + "SENTINEL MASTER", + "SENTINEL MASTERS", + "SENTINEL MONITOR", + "SENTINEL REMOVE", + "SENTINEL SENTINELS", + "SENTINEL SET", + "SENTINEL SLAVES", + "SENTINEL", + "SHUTDOWN", + "SINTER", + "SINTERSTORE", + "SLAVEOF", + "SLOWLOG GET", + "SLOWLOG LEN", + "SLOWLOG RESET", + "SLOWLOG", + "SMOVE", + "SORT", + "SUNION", + "SUNIONSTORE", + "TIME", +) +for command in PIPELINE_BLOCKED_COMMANDS: + command = command.replace(" ", "_").lower() + + setattr(ClusterPipeline, command, block_pipeline_command(command)) + + +class PipelineCommand: + """ """ + + def __init__(self, args, options=None, position=None): + self.args = args + if options is None: + options = {} + self.options = options + self.position = position + self.result = None + self.node = None + self.asking = False + + +class NodeCommands: + """ """ + + def __init__(self, parse_response, connection_pool, connection): + """ """ + self.parse_response = parse_response + self.connection_pool = connection_pool + self.connection = connection + self.commands = [] + + def append(self, c): + """ """ + self.commands.append(c) + + def write(self): + """ + Code borrowed from Redis so it can be fixed + """ + connection = self.connection + commands = self.commands + + # We are going to clobber the commands with the write, so go ahead + # and ensure that nothing is sitting there from a previous run. + for c in commands: + c.result = None + + # build up all commands into a single request to increase network perf + # send all the commands and catch connection and timeout errors. + try: + connection.send_packed_command( + connection.pack_commands([c.args for c in commands]) + ) + except (ConnectionError, TimeoutError) as e: + for c in commands: + c.result = e + + def read(self): + """ """ + connection = self.connection + for c in self.commands: + # if there is a result on this command, + # it means we ran into an exception + # like a connection error. Trying to parse + # a response on a connection that + # is no longer open will result in a + # connection error raised by redis-py. + # but redis-py doesn't check in parse_response + # that the sock object is + # still set and if you try to + # read from a closed connection, it will + # result in an AttributeError because + # it will do a readline() call on None. + # This can have all kinds of nasty side-effects. + # Treating this case as a connection error + # is fine because it will dump + # the connection object back into the + # pool and on the next write, it will + # explicitly open the connection and all will be well. + if c.result is None: + try: + c.result = self.parse_response(connection, c.args[0], **c.options) + except (ConnectionError, TimeoutError) as e: + for c in self.commands: + c.result = e + return + except RedisError: + c.result = sys.exc_info()[1] diff --git a/.venv/Lib/site-packages/redis/commands/__init__.py b/.venv/Lib/site-packages/redis/commands/__init__.py new file mode 100644 index 00000000..a94d9764 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/__init__.py @@ -0,0 +1,18 @@ +from .cluster import READ_COMMANDS, AsyncRedisClusterCommands, RedisClusterCommands +from .core import AsyncCoreCommands, CoreCommands +from .helpers import list_or_args +from .redismodules import AsyncRedisModuleCommands, RedisModuleCommands +from .sentinel import AsyncSentinelCommands, SentinelCommands + +__all__ = [ + "AsyncCoreCommands", + "AsyncRedisClusterCommands", + "AsyncRedisModuleCommands", + "AsyncSentinelCommands", + "CoreCommands", + "READ_COMMANDS", + "RedisClusterCommands", + "RedisModuleCommands", + "SentinelCommands", + "list_or_args", +] diff --git a/.venv/Lib/site-packages/redis/commands/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e1bfc795d8e1ee8bb1cc2fc8db3d645bfa4d880 GIT binary patch literal 784 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/__pycache__/redismodules.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/__pycache__/redismodules.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d8ab6a78e14836307bb960c61286f97305efa77 GIT binary patch literal 4210 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 VWKFELmo%Rm`<%MJIATn#>OXy7zMTL7 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/bf/__init__.py b/.venv/Lib/site-packages/redis/commands/bf/__init__.py new file mode 100644 index 00000000..959358f8 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/bf/__init__.py @@ -0,0 +1,253 @@ +from redis._parsers.helpers import bool_ok + +from ..helpers import get_protocol_version, parse_to_list +from .commands import * # noqa +from .info import BFInfo, CFInfo, CMSInfo, TDigestInfo, TopKInfo + + +class AbstractBloom(object): + """ + The client allows to interact with RedisBloom and use all of + it's functionality. + + - BF for Bloom Filter + - CF for Cuckoo Filter + - CMS for Count-Min Sketch + - TOPK for TopK Data Structure + - TDIGEST for estimate rank statistics + """ + + @staticmethod + def append_items(params, items): + """Append ITEMS to params.""" + params.extend(["ITEMS"]) + params += items + + @staticmethod + def append_error(params, error): + """Append ERROR to params.""" + if error is not None: + params.extend(["ERROR", error]) + + @staticmethod + def append_capacity(params, capacity): + """Append CAPACITY to params.""" + if capacity is not None: + params.extend(["CAPACITY", capacity]) + + @staticmethod + def append_expansion(params, expansion): + """Append EXPANSION to params.""" + if expansion is not None: + params.extend(["EXPANSION", expansion]) + + @staticmethod + def append_no_scale(params, noScale): + """Append NONSCALING tag to params.""" + if noScale is not None: + params.extend(["NONSCALING"]) + + @staticmethod + def append_weights(params, weights): + """Append WEIGHTS to params.""" + if len(weights) > 0: + params.append("WEIGHTS") + params += weights + + @staticmethod + def append_no_create(params, noCreate): + """Append NOCREATE tag to params.""" + if noCreate is not None: + params.extend(["NOCREATE"]) + + @staticmethod + def append_items_and_increments(params, items, increments): + """Append pairs of items and increments to params.""" + for i in range(len(items)): + params.append(items[i]) + params.append(increments[i]) + + @staticmethod + def append_values_and_weights(params, items, weights): + """Append pairs of items and weights to params.""" + for i in range(len(items)): + params.append(items[i]) + params.append(weights[i]) + + @staticmethod + def append_max_iterations(params, max_iterations): + """Append MAXITERATIONS to params.""" + if max_iterations is not None: + params.extend(["MAXITERATIONS", max_iterations]) + + @staticmethod + def append_bucket_size(params, bucket_size): + """Append BUCKETSIZE to params.""" + if bucket_size is not None: + params.extend(["BUCKETSIZE", bucket_size]) + + +class CMSBloom(CMSCommands, AbstractBloom): + def __init__(self, client, **kwargs): + """Create a new RedisBloom client.""" + # Set the module commands' callbacks + _MODULE_CALLBACKS = { + CMS_INITBYDIM: bool_ok, + CMS_INITBYPROB: bool_ok, + # CMS_INCRBY: spaceHolder, + # CMS_QUERY: spaceHolder, + CMS_MERGE: bool_ok, + } + + _RESP2_MODULE_CALLBACKS = { + CMS_INFO: CMSInfo, + } + _RESP3_MODULE_CALLBACKS = {} + + self.client = client + self.commandmixin = CMSCommands + self.execute_command = client.execute_command + + if get_protocol_version(self.client) in ["3", 3]: + _MODULE_CALLBACKS.update(_RESP3_MODULE_CALLBACKS) + else: + _MODULE_CALLBACKS.update(_RESP2_MODULE_CALLBACKS) + + for k, v in _MODULE_CALLBACKS.items(): + self.client.set_response_callback(k, v) + + +class TOPKBloom(TOPKCommands, AbstractBloom): + def __init__(self, client, **kwargs): + """Create a new RedisBloom client.""" + # Set the module commands' callbacks + _MODULE_CALLBACKS = { + TOPK_RESERVE: bool_ok, + # TOPK_QUERY: spaceHolder, + # TOPK_COUNT: spaceHolder, + } + + _RESP2_MODULE_CALLBACKS = { + TOPK_ADD: parse_to_list, + TOPK_INCRBY: parse_to_list, + TOPK_INFO: TopKInfo, + TOPK_LIST: parse_to_list, + } + _RESP3_MODULE_CALLBACKS = {} + + self.client = client + self.commandmixin = TOPKCommands + self.execute_command = client.execute_command + + if get_protocol_version(self.client) in ["3", 3]: + _MODULE_CALLBACKS.update(_RESP3_MODULE_CALLBACKS) + else: + _MODULE_CALLBACKS.update(_RESP2_MODULE_CALLBACKS) + + for k, v in _MODULE_CALLBACKS.items(): + self.client.set_response_callback(k, v) + + +class CFBloom(CFCommands, AbstractBloom): + def __init__(self, client, **kwargs): + """Create a new RedisBloom client.""" + # Set the module commands' callbacks + _MODULE_CALLBACKS = { + CF_RESERVE: bool_ok, + # CF_ADD: spaceHolder, + # CF_ADDNX: spaceHolder, + # CF_INSERT: spaceHolder, + # CF_INSERTNX: spaceHolder, + # CF_EXISTS: spaceHolder, + # CF_DEL: spaceHolder, + # CF_COUNT: spaceHolder, + # CF_SCANDUMP: spaceHolder, + # CF_LOADCHUNK: spaceHolder, + } + + _RESP2_MODULE_CALLBACKS = { + CF_INFO: CFInfo, + } + _RESP3_MODULE_CALLBACKS = {} + + self.client = client + self.commandmixin = CFCommands + self.execute_command = client.execute_command + + if get_protocol_version(self.client) in ["3", 3]: + _MODULE_CALLBACKS.update(_RESP3_MODULE_CALLBACKS) + else: + _MODULE_CALLBACKS.update(_RESP2_MODULE_CALLBACKS) + + for k, v in _MODULE_CALLBACKS.items(): + self.client.set_response_callback(k, v) + + +class TDigestBloom(TDigestCommands, AbstractBloom): + def __init__(self, client, **kwargs): + """Create a new RedisBloom client.""" + # Set the module commands' callbacks + _MODULE_CALLBACKS = { + TDIGEST_CREATE: bool_ok, + # TDIGEST_RESET: bool_ok, + # TDIGEST_ADD: spaceHolder, + # TDIGEST_MERGE: spaceHolder, + } + + _RESP2_MODULE_CALLBACKS = { + TDIGEST_BYRANK: parse_to_list, + TDIGEST_BYREVRANK: parse_to_list, + TDIGEST_CDF: parse_to_list, + TDIGEST_INFO: TDigestInfo, + TDIGEST_MIN: float, + TDIGEST_MAX: float, + TDIGEST_TRIMMED_MEAN: float, + TDIGEST_QUANTILE: parse_to_list, + } + _RESP3_MODULE_CALLBACKS = {} + + self.client = client + self.commandmixin = TDigestCommands + self.execute_command = client.execute_command + + if get_protocol_version(self.client) in ["3", 3]: + _MODULE_CALLBACKS.update(_RESP3_MODULE_CALLBACKS) + else: + _MODULE_CALLBACKS.update(_RESP2_MODULE_CALLBACKS) + + for k, v in _MODULE_CALLBACKS.items(): + self.client.set_response_callback(k, v) + + +class BFBloom(BFCommands, AbstractBloom): + def __init__(self, client, **kwargs): + """Create a new RedisBloom client.""" + # Set the module commands' callbacks + _MODULE_CALLBACKS = { + BF_RESERVE: bool_ok, + # BF_ADD: spaceHolder, + # BF_MADD: spaceHolder, + # BF_INSERT: spaceHolder, + # BF_EXISTS: spaceHolder, + # BF_MEXISTS: spaceHolder, + # BF_SCANDUMP: spaceHolder, + # BF_LOADCHUNK: spaceHolder, + # BF_CARD: spaceHolder, + } + + _RESP2_MODULE_CALLBACKS = { + BF_INFO: BFInfo, + } + _RESP3_MODULE_CALLBACKS = {} + + self.client = client + self.commandmixin = BFCommands + self.execute_command = client.execute_command + + if get_protocol_version(self.client) in ["3", 3]: + _MODULE_CALLBACKS.update(_RESP3_MODULE_CALLBACKS) + else: + _MODULE_CALLBACKS.update(_RESP2_MODULE_CALLBACKS) + + for k, v in _MODULE_CALLBACKS.items(): + self.client.set_response_callback(k, v) diff --git a/.venv/Lib/site-packages/redis/commands/bf/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/bf/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..352d33c50e77c29adc1b5228493ee4af72dfdcc6 GIT binary patch literal 10763 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/bf/__pycache__/commands.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/bf/__pycache__/commands.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee4fa6bc3304ed6075b248920c181430d599d64d GIT binary patch literal 28213 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/bf/__pycache__/info.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/bf/__pycache__/info.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a90459ea5efa0c6746a272920c01161ee85fec49 GIT binary patch literal 6604 zcmeHL%WoUU8J{JW67_yqG%3kt9ya32vE%wF$%!3XY8%NxBM2oZ?n>TRe0X+c z*@RjUMT_dtgAWDdO9~xYr-F0vAqD(rP{jgWERa)AxzUvmhEDyyA@@P?(Z*9>Y8R{*Byfem;Yy%qs{5ocuuuOzaTVGz3kmvK<(OsVZev`jeF2+ zB2Pg7Q_BYQaJBF81Z+OF?Eb>FR9GM}^qzmbctUfgO1-U34cFk{OS0ozCuf|s8bycFu;eg#Ft5Q~p z$vH)$sw5tUuRSQFbBdhL#b{cUl7531<&0{$i*mtmXVV3Wo;HMxWkUfQhQF#A)EYrk z7gjnXQ{6|PZO?7+inP9J@M*fH7y^})LLMwDs52Ie9p0Wjznsa7a&B$;c7Ap7dOCAg zS^h}MN;m;Y$w;}3w0!cul)JxtOI}%4VDN9lT<@mWBxRXOqO6?CN1^fHB0z~$TyFn>9_{~IH1XGH zVs~~wn$)7nawz%gtH@}DaQ*=spxdLVM^hCyw7z=v>L3Ife$~@Yb^;UbKXMc9=FW&i zulm5>BH#cRpB=;tgpNYDJ8j9W4TCm)JGd$=9faMVBd!#;I z+>gYyNW3h>=`b`WgSeJ*>8u1U3#3xnytuKB4x6jSGuY943y?7yw`KCLM-Uy zJ>X*tLYyZ7E^mOUS+tme+qz6%JGcT(|AM$VpluFFn*+*55)U#G4>1z&FiCu-9f>c2 zx%y}Mzf0mk{6ZbQ`^|>}5`Ue9y+fcBB!M~!av8hWmJqCN2^6;wit37vePCrHb5~Lo zipnVduh@TdM-ZiT2{wdcaGLdvAcX;E`~-G;0`R&l z-jcc7(D+cioVcJ3T?B@Y=tJ?{i`vjTtX#+M`p9^B0`?Ht2sB}^%)TuAniJf&!S;*} z=`nCmBM~AO6$3SQ0u7$VUgHQ80L{nv4M>>clWDYCrC;kITJ(DkdnXYX*@o#GSbh`X zEd)lX?_kO1RW{-uVjE*veCIquv-E9jLygrXbP7udxJ@WBfP-mmlC_z(tGD!_&HyqI$>hh*AN6GWm_1n)EegrSsqv`Xhu32rc-fv*uZgV6H-EB?a)h1k*eE zcunh_1bztUEy~-0?LZr5_zy*0)Sj9Zb|0WC?64D#hTRdTAqBJdm!pBj!WRL3tDw&u zffed3UDGY7@Vw^)zNyrpeZZj3<^h8Q(IQ|l#l)cTv7mvs708o#Ls-lgZnlYj<>JEvDn}^yJkhBRkJk9xcl7isktPI(@+9n47pBbdAR`A4!qSaz(PNHj)7|Z2FNhyYJ=d#XvM@_mZ$!mAiV#E^H8oC$rYI;2er!b~g z1vO^#^kHm6fpePX>4Fh-{DbAskO?rmDK-uxyiprRt=>_SR?Qj_OI&N{R&g9DhgJnO z;y6-l9Ibe&$FV*ws#*odD4zqoE>#UDcIUL=)71kY=b6#S`0mfOktvoP=*K3@C(dfe z&S7mB&WU#O+9*pLhV-!$BsuuXqoS`l8rN%Y}DWzB^zjbJ}DT!JJNaq&VH-s zx8D59r&30(o;tCFh`qeAy@idrK4&@w@YF3|A8)19(1-8DlMaRO}vk|uMzrfa)wkY0cm<{I9 M`_. + """ # noqa + params = [key, errorRate, capacity] + self.append_expansion(params, expansion) + self.append_no_scale(params, noScale) + return self.execute_command(BF_RESERVE, *params) + + reserve = create + + def add(self, key, item): + """ + Add to a Bloom Filter `key` an `item`. + For more information see `BF.ADD `_. + """ # noqa + return self.execute_command(BF_ADD, key, item) + + def madd(self, key, *items): + """ + Add to a Bloom Filter `key` multiple `items`. + For more information see `BF.MADD `_. + """ # noqa + return self.execute_command(BF_MADD, key, *items) + + def insert( + self, + key, + items, + capacity=None, + error=None, + noCreate=None, + expansion=None, + noScale=None, + ): + """ + Add to a Bloom Filter `key` multiple `items`. + + If `nocreate` remain `None` and `key` does not exist, a new Bloom Filter + `key` will be created with desired probability of false positives `errorRate` + and expected entries to be inserted as `size`. + For more information see `BF.INSERT `_. + """ # noqa + params = [key] + self.append_capacity(params, capacity) + self.append_error(params, error) + self.append_expansion(params, expansion) + self.append_no_create(params, noCreate) + self.append_no_scale(params, noScale) + self.append_items(params, items) + + return self.execute_command(BF_INSERT, *params) + + def exists(self, key, item): + """ + Check whether an `item` exists in Bloom Filter `key`. + For more information see `BF.EXISTS `_. + """ # noqa + return self.execute_command(BF_EXISTS, key, item) + + def mexists(self, key, *items): + """ + Check whether `items` exist in Bloom Filter `key`. + For more information see `BF.MEXISTS `_. + """ # noqa + return self.execute_command(BF_MEXISTS, key, *items) + + def scandump(self, key, iter): + """ + Begin an incremental save of the bloom filter `key`. + + This is useful for large bloom filters which cannot fit into the normal SAVE and RESTORE model. + The first time this command is called, the value of `iter` should be 0. + This command will return successive (iter, data) pairs until (0, NULL) to indicate completion. + For more information see `BF.SCANDUMP `_. + """ # noqa + if HIREDIS_AVAILABLE: + raise ModuleError("This command cannot be used when hiredis is available.") + + params = [key, iter] + options = {} + options[NEVER_DECODE] = [] + return self.execute_command(BF_SCANDUMP, *params, **options) + + def loadchunk(self, key, iter, data): + """ + Restore a filter previously saved using SCANDUMP. + + See the SCANDUMP command for example usage. + This command will overwrite any bloom filter stored under key. + Ensure that the bloom filter will not be modified between invocations. + For more information see `BF.LOADCHUNK `_. + """ # noqa + return self.execute_command(BF_LOADCHUNK, key, iter, data) + + def info(self, key): + """ + Return capacity, size, number of filters, number of items inserted, and expansion rate. + For more information see `BF.INFO `_. + """ # noqa + return self.execute_command(BF_INFO, key) + + def card(self, key): + """ + Returns the cardinality of a Bloom filter - number of items that were added to a Bloom filter and detected as unique + (items that caused at least one bit to be set in at least one sub-filter). + For more information see `BF.CARD `_. + """ # noqa + return self.execute_command(BF_CARD, key) + + +class CFCommands: + """Cuckoo Filter commands.""" + + def create( + self, key, capacity, expansion=None, bucket_size=None, max_iterations=None + ): + """ + Create a new Cuckoo Filter `key` an initial `capacity` items. + For more information see `CF.RESERVE `_. + """ # noqa + params = [key, capacity] + self.append_expansion(params, expansion) + self.append_bucket_size(params, bucket_size) + self.append_max_iterations(params, max_iterations) + return self.execute_command(CF_RESERVE, *params) + + reserve = create + + def add(self, key, item): + """ + Add an `item` to a Cuckoo Filter `key`. + For more information see `CF.ADD `_. + """ # noqa + return self.execute_command(CF_ADD, key, item) + + def addnx(self, key, item): + """ + Add an `item` to a Cuckoo Filter `key` only if item does not yet exist. + Command might be slower that `add`. + For more information see `CF.ADDNX `_. + """ # noqa + return self.execute_command(CF_ADDNX, key, item) + + def insert(self, key, items, capacity=None, nocreate=None): + """ + Add multiple `items` to a Cuckoo Filter `key`, allowing the filter + to be created with a custom `capacity` if it does not yet exist. + `items` must be provided as a list. + For more information see `CF.INSERT `_. + """ # noqa + params = [key] + self.append_capacity(params, capacity) + self.append_no_create(params, nocreate) + self.append_items(params, items) + return self.execute_command(CF_INSERT, *params) + + def insertnx(self, key, items, capacity=None, nocreate=None): + """ + Add multiple `items` to a Cuckoo Filter `key` only if they do not exist yet, + allowing the filter to be created with a custom `capacity` if it does not yet exist. + `items` must be provided as a list. + For more information see `CF.INSERTNX `_. + """ # noqa + params = [key] + self.append_capacity(params, capacity) + self.append_no_create(params, nocreate) + self.append_items(params, items) + return self.execute_command(CF_INSERTNX, *params) + + def exists(self, key, item): + """ + Check whether an `item` exists in Cuckoo Filter `key`. + For more information see `CF.EXISTS `_. + """ # noqa + return self.execute_command(CF_EXISTS, key, item) + + def mexists(self, key, *items): + """ + Check whether an `items` exist in Cuckoo Filter `key`. + For more information see `CF.MEXISTS `_. + """ # noqa + return self.execute_command(CF_MEXISTS, key, *items) + + def delete(self, key, item): + """ + Delete `item` from `key`. + For more information see `CF.DEL `_. + """ # noqa + return self.execute_command(CF_DEL, key, item) + + def count(self, key, item): + """ + Return the number of times an `item` may be in the `key`. + For more information see `CF.COUNT `_. + """ # noqa + return self.execute_command(CF_COUNT, key, item) + + def scandump(self, key, iter): + """ + Begin an incremental save of the Cuckoo filter `key`. + + This is useful for large Cuckoo filters which cannot fit into the normal + SAVE and RESTORE model. + The first time this command is called, the value of `iter` should be 0. + This command will return successive (iter, data) pairs until + (0, NULL) to indicate completion. + For more information see `CF.SCANDUMP `_. + """ # noqa + return self.execute_command(CF_SCANDUMP, key, iter) + + def loadchunk(self, key, iter, data): + """ + Restore a filter previously saved using SCANDUMP. See the SCANDUMP command for example usage. + + This command will overwrite any Cuckoo filter stored under key. + Ensure that the Cuckoo filter will not be modified between invocations. + For more information see `CF.LOADCHUNK `_. + """ # noqa + return self.execute_command(CF_LOADCHUNK, key, iter, data) + + def info(self, key): + """ + Return size, number of buckets, number of filter, number of items inserted, + number of items deleted, bucket size, expansion rate, and max iteration. + For more information see `CF.INFO `_. + """ # noqa + return self.execute_command(CF_INFO, key) + + +class TOPKCommands: + """TOP-k Filter commands.""" + + def reserve(self, key, k, width, depth, decay): + """ + Create a new Top-K Filter `key` with desired probability of false + positives `errorRate` expected entries to be inserted as `size`. + For more information see `TOPK.RESERVE `_. + """ # noqa + return self.execute_command(TOPK_RESERVE, key, k, width, depth, decay) + + def add(self, key, *items): + """ + Add one `item` or more to a Top-K Filter `key`. + For more information see `TOPK.ADD `_. + """ # noqa + return self.execute_command(TOPK_ADD, key, *items) + + def incrby(self, key, items, increments): + """ + Add/increase `items` to a Top-K Sketch `key` by ''increments''. + Both `items` and `increments` are lists. + For more information see `TOPK.INCRBY `_. + + Example: + + >>> topkincrby('A', ['foo'], [1]) + """ # noqa + params = [key] + self.append_items_and_increments(params, items, increments) + return self.execute_command(TOPK_INCRBY, *params) + + def query(self, key, *items): + """ + Check whether one `item` or more is a Top-K item at `key`. + For more information see `TOPK.QUERY `_. + """ # noqa + return self.execute_command(TOPK_QUERY, key, *items) + + @deprecated_function(version="4.4.0", reason="deprecated since redisbloom 2.4.0") + def count(self, key, *items): + """ + Return count for one `item` or more from `key`. + For more information see `TOPK.COUNT `_. + """ # noqa + return self.execute_command(TOPK_COUNT, key, *items) + + def list(self, key, withcount=False): + """ + Return full list of items in Top-K list of `key`. + If `withcount` set to True, return full list of items + with probabilistic count in Top-K list of `key`. + For more information see `TOPK.LIST `_. + """ # noqa + params = [key] + if withcount: + params.append("WITHCOUNT") + return self.execute_command(TOPK_LIST, *params) + + def info(self, key): + """ + Return k, width, depth and decay values of `key`. + For more information see `TOPK.INFO `_. + """ # noqa + return self.execute_command(TOPK_INFO, key) + + +class TDigestCommands: + def create(self, key, compression=100): + """ + Allocate the memory and initialize the t-digest. + For more information see `TDIGEST.CREATE `_. + """ # noqa + return self.execute_command(TDIGEST_CREATE, key, "COMPRESSION", compression) + + def reset(self, key): + """ + Reset the sketch `key` to zero - empty out the sketch and re-initialize it. + For more information see `TDIGEST.RESET `_. + """ # noqa + return self.execute_command(TDIGEST_RESET, key) + + def add(self, key, values): + """ + Adds one or more observations to a t-digest sketch `key`. + + For more information see `TDIGEST.ADD `_. + """ # noqa + return self.execute_command(TDIGEST_ADD, key, *values) + + def merge(self, destination_key, num_keys, *keys, compression=None, override=False): + """ + Merges all of the values from `keys` to 'destination-key' sketch. + It is mandatory to provide the `num_keys` before passing the input keys and + the other (optional) arguments. + If `destination_key` already exists its values are merged with the input keys. + If you wish to override the destination key contents use the `OVERRIDE` parameter. + + For more information see `TDIGEST.MERGE `_. + """ # noqa + params = [destination_key, num_keys, *keys] + if compression is not None: + params.extend(["COMPRESSION", compression]) + if override: + params.append("OVERRIDE") + return self.execute_command(TDIGEST_MERGE, *params) + + def min(self, key): + """ + Return minimum value from the sketch `key`. Will return DBL_MAX if the sketch is empty. + For more information see `TDIGEST.MIN `_. + """ # noqa + return self.execute_command(TDIGEST_MIN, key) + + def max(self, key): + """ + Return maximum value from the sketch `key`. Will return DBL_MIN if the sketch is empty. + For more information see `TDIGEST.MAX `_. + """ # noqa + return self.execute_command(TDIGEST_MAX, key) + + def quantile(self, key, quantile, *quantiles): + """ + Returns estimates of one or more cutoffs such that a specified fraction of the + observations added to this t-digest would be less than or equal to each of the + specified cutoffs. (Multiple quantiles can be returned with one call) + For more information see `TDIGEST.QUANTILE `_. + """ # noqa + return self.execute_command(TDIGEST_QUANTILE, key, quantile, *quantiles) + + def cdf(self, key, value, *values): + """ + Return double fraction of all points added which are <= value. + For more information see `TDIGEST.CDF `_. + """ # noqa + return self.execute_command(TDIGEST_CDF, key, value, *values) + + def info(self, key): + """ + Return Compression, Capacity, Merged Nodes, Unmerged Nodes, Merged Weight, Unmerged Weight + and Total Compressions. + For more information see `TDIGEST.INFO `_. + """ # noqa + return self.execute_command(TDIGEST_INFO, key) + + def trimmed_mean(self, key, low_cut_quantile, high_cut_quantile): + """ + Return mean value from the sketch, excluding observation values outside + the low and high cutoff quantiles. + For more information see `TDIGEST.TRIMMED_MEAN `_. + """ # noqa + return self.execute_command( + TDIGEST_TRIMMED_MEAN, key, low_cut_quantile, high_cut_quantile + ) + + def rank(self, key, value, *values): + """ + Retrieve the estimated rank of value (the number of observations in the sketch + that are smaller than value + half the number of observations that are equal to value). + + For more information see `TDIGEST.RANK `_. + """ # noqa + return self.execute_command(TDIGEST_RANK, key, value, *values) + + def revrank(self, key, value, *values): + """ + Retrieve the estimated rank of value (the number of observations in the sketch + that are larger than value + half the number of observations that are equal to value). + + For more information see `TDIGEST.REVRANK `_. + """ # noqa + return self.execute_command(TDIGEST_REVRANK, key, value, *values) + + def byrank(self, key, rank, *ranks): + """ + Retrieve an estimation of the value with the given rank. + + For more information see `TDIGEST.BY_RANK `_. + """ # noqa + return self.execute_command(TDIGEST_BYRANK, key, rank, *ranks) + + def byrevrank(self, key, rank, *ranks): + """ + Retrieve an estimation of the value with the given reverse rank. + + For more information see `TDIGEST.BY_REVRANK `_. + """ # noqa + return self.execute_command(TDIGEST_BYREVRANK, key, rank, *ranks) + + +class CMSCommands: + """Count-Min Sketch Commands""" + + def initbydim(self, key, width, depth): + """ + Initialize a Count-Min Sketch `key` to dimensions (`width`, `depth`) specified by user. + For more information see `CMS.INITBYDIM `_. + """ # noqa + return self.execute_command(CMS_INITBYDIM, key, width, depth) + + def initbyprob(self, key, error, probability): + """ + Initialize a Count-Min Sketch `key` to characteristics (`error`, `probability`) specified by user. + For more information see `CMS.INITBYPROB `_. + """ # noqa + return self.execute_command(CMS_INITBYPROB, key, error, probability) + + def incrby(self, key, items, increments): + """ + Add/increase `items` to a Count-Min Sketch `key` by ''increments''. + Both `items` and `increments` are lists. + For more information see `CMS.INCRBY `_. + + Example: + + >>> cmsincrby('A', ['foo'], [1]) + """ # noqa + params = [key] + self.append_items_and_increments(params, items, increments) + return self.execute_command(CMS_INCRBY, *params) + + def query(self, key, *items): + """ + Return count for an `item` from `key`. Multiple items can be queried with one call. + For more information see `CMS.QUERY `_. + """ # noqa + return self.execute_command(CMS_QUERY, key, *items) + + def merge(self, destKey, numKeys, srcKeys, weights=[]): + """ + Merge `numKeys` of sketches into `destKey`. Sketches specified in `srcKeys`. + All sketches must have identical width and depth. + `Weights` can be used to multiply certain sketches. Default weight is 1. + Both `srcKeys` and `weights` are lists. + For more information see `CMS.MERGE `_. + """ # noqa + params = [destKey, numKeys] + params += srcKeys + self.append_weights(params, weights) + return self.execute_command(CMS_MERGE, *params) + + def info(self, key): + """ + Return width, depth and total count of the sketch. + For more information see `CMS.INFO `_. + """ # noqa + return self.execute_command(CMS_INFO, key) diff --git a/.venv/Lib/site-packages/redis/commands/bf/info.py b/.venv/Lib/site-packages/redis/commands/bf/info.py new file mode 100644 index 00000000..e1f02086 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/bf/info.py @@ -0,0 +1,120 @@ +from ..helpers import nativestr + + +class BFInfo(object): + capacity = None + size = None + filterNum = None + insertedNum = None + expansionRate = None + + def __init__(self, args): + response = dict(zip(map(nativestr, args[::2]), args[1::2])) + self.capacity = response["Capacity"] + self.size = response["Size"] + self.filterNum = response["Number of filters"] + self.insertedNum = response["Number of items inserted"] + self.expansionRate = response["Expansion rate"] + + def get(self, item): + try: + return self.__getitem__(item) + except AttributeError: + return None + + def __getitem__(self, item): + return getattr(self, item) + + +class CFInfo(object): + size = None + bucketNum = None + filterNum = None + insertedNum = None + deletedNum = None + bucketSize = None + expansionRate = None + maxIteration = None + + def __init__(self, args): + response = dict(zip(map(nativestr, args[::2]), args[1::2])) + self.size = response["Size"] + self.bucketNum = response["Number of buckets"] + self.filterNum = response["Number of filters"] + self.insertedNum = response["Number of items inserted"] + self.deletedNum = response["Number of items deleted"] + self.bucketSize = response["Bucket size"] + self.expansionRate = response["Expansion rate"] + self.maxIteration = response["Max iterations"] + + def get(self, item): + try: + return self.__getitem__(item) + except AttributeError: + return None + + def __getitem__(self, item): + return getattr(self, item) + + +class CMSInfo(object): + width = None + depth = None + count = None + + def __init__(self, args): + response = dict(zip(map(nativestr, args[::2]), args[1::2])) + self.width = response["width"] + self.depth = response["depth"] + self.count = response["count"] + + def __getitem__(self, item): + return getattr(self, item) + + +class TopKInfo(object): + k = None + width = None + depth = None + decay = None + + def __init__(self, args): + response = dict(zip(map(nativestr, args[::2]), args[1::2])) + self.k = response["k"] + self.width = response["width"] + self.depth = response["depth"] + self.decay = response["decay"] + + def __getitem__(self, item): + return getattr(self, item) + + +class TDigestInfo(object): + compression = None + capacity = None + merged_nodes = None + unmerged_nodes = None + merged_weight = None + unmerged_weight = None + total_compressions = None + memory_usage = None + + def __init__(self, args): + response = dict(zip(map(nativestr, args[::2]), args[1::2])) + self.compression = response["Compression"] + self.capacity = response["Capacity"] + self.merged_nodes = response["Merged nodes"] + self.unmerged_nodes = response["Unmerged nodes"] + self.merged_weight = response["Merged weight"] + self.unmerged_weight = response["Unmerged weight"] + self.total_compressions = response["Total compressions"] + self.memory_usage = response["Memory usage"] + + def get(self, item): + try: + return self.__getitem__(item) + except AttributeError: + return None + + def __getitem__(self, item): + return getattr(self, item) diff --git a/.venv/Lib/site-packages/redis/commands/cluster.py b/.venv/Lib/site-packages/redis/commands/cluster.py new file mode 100644 index 00000000..14b87414 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/cluster.py @@ -0,0 +1,928 @@ +import asyncio +from typing import ( + TYPE_CHECKING, + Any, + AsyncIterator, + Dict, + Iterable, + Iterator, + List, + Mapping, + NoReturn, + Optional, + Union, +) + +from redis.compat import Literal +from redis.crc import key_slot +from redis.exceptions import RedisClusterException, RedisError +from redis.typing import ( + AnyKeyT, + ClusterCommandsProtocol, + EncodableT, + KeysT, + KeyT, + PatternT, +) + +from .core import ( + ACLCommands, + AsyncACLCommands, + AsyncDataAccessCommands, + AsyncFunctionCommands, + AsyncGearsCommands, + AsyncManagementCommands, + AsyncModuleCommands, + AsyncScriptCommands, + DataAccessCommands, + FunctionCommands, + GearsCommands, + ManagementCommands, + ModuleCommands, + PubSubCommands, + ResponseT, + ScriptCommands, +) +from .helpers import list_or_args +from .redismodules import RedisModuleCommands + +if TYPE_CHECKING: + from redis.asyncio.cluster import TargetNodesT + +# Not complete, but covers the major ones +# https://redis.io/commands +READ_COMMANDS = frozenset( + [ + "BITCOUNT", + "BITPOS", + "EVAL_RO", + "EVALSHA_RO", + "EXISTS", + "GEODIST", + "GEOHASH", + "GEOPOS", + "GEORADIUS", + "GEORADIUSBYMEMBER", + "GET", + "GETBIT", + "GETRANGE", + "HEXISTS", + "HGET", + "HGETALL", + "HKEYS", + "HLEN", + "HMGET", + "HSTRLEN", + "HVALS", + "KEYS", + "LINDEX", + "LLEN", + "LRANGE", + "MGET", + "PTTL", + "RANDOMKEY", + "SCARD", + "SDIFF", + "SINTER", + "SISMEMBER", + "SMEMBERS", + "SRANDMEMBER", + "STRLEN", + "SUNION", + "TTL", + "ZCARD", + "ZCOUNT", + "ZRANGE", + "ZSCORE", + ] +) + + +class ClusterMultiKeyCommands(ClusterCommandsProtocol): + """ + A class containing commands that handle more than one key + """ + + def _partition_keys_by_slot(self, keys: Iterable[KeyT]) -> Dict[int, List[KeyT]]: + """Split keys into a dictionary that maps a slot to a list of keys.""" + + slots_to_keys = {} + for key in keys: + slot = key_slot(self.encoder.encode(key)) + slots_to_keys.setdefault(slot, []).append(key) + + return slots_to_keys + + def _partition_pairs_by_slot( + self, mapping: Mapping[AnyKeyT, EncodableT] + ) -> Dict[int, List[EncodableT]]: + """Split pairs into a dictionary that maps a slot to a list of pairs.""" + + slots_to_pairs = {} + for pair in mapping.items(): + slot = key_slot(self.encoder.encode(pair[0])) + slots_to_pairs.setdefault(slot, []).extend(pair) + + return slots_to_pairs + + def _execute_pipeline_by_slot( + self, command: str, slots_to_args: Mapping[int, Iterable[EncodableT]] + ) -> List[Any]: + read_from_replicas = self.read_from_replicas and command in READ_COMMANDS + pipe = self.pipeline() + [ + pipe.execute_command( + command, + *slot_args, + target_nodes=[ + self.nodes_manager.get_node_from_slot(slot, read_from_replicas) + ], + ) + for slot, slot_args in slots_to_args.items() + ] + return pipe.execute() + + def _reorder_keys_by_command( + self, + keys: Iterable[KeyT], + slots_to_args: Mapping[int, Iterable[EncodableT]], + responses: Iterable[Any], + ) -> List[Any]: + results = { + k: v + for slot_values, response in zip(slots_to_args.values(), responses) + for k, v in zip(slot_values, response) + } + return [results[key] for key in keys] + + def mget_nonatomic(self, keys: KeysT, *args: KeyT) -> List[Optional[Any]]: + """ + Splits the keys into different slots and then calls MGET + for the keys of every slot. This operation will not be atomic + if keys belong to more than one slot. + + Returns a list of values ordered identically to ``keys`` + + For more information see https://redis.io/commands/mget + """ + + # Concatenate all keys into a list + keys = list_or_args(keys, args) + + # Split keys into slots + slots_to_keys = self._partition_keys_by_slot(keys) + + # Execute commands using a pipeline + res = self._execute_pipeline_by_slot("MGET", slots_to_keys) + + # Reorder keys in the order the user provided & return + return self._reorder_keys_by_command(keys, slots_to_keys, res) + + def mset_nonatomic(self, mapping: Mapping[AnyKeyT, EncodableT]) -> List[bool]: + """ + Sets key/values based on a mapping. Mapping is a dictionary of + key/value pairs. Both keys and values should be strings or types that + can be cast to a string via str(). + + Splits the keys into different slots and then calls MSET + for the keys of every slot. This operation will not be atomic + if keys belong to more than one slot. + + For more information see https://redis.io/commands/mset + """ + + # Partition the keys by slot + slots_to_pairs = self._partition_pairs_by_slot(mapping) + + # Execute commands using a pipeline & return list of replies + return self._execute_pipeline_by_slot("MSET", slots_to_pairs) + + def _split_command_across_slots(self, command: str, *keys: KeyT) -> int: + """ + Runs the given command once for the keys + of each slot. Returns the sum of the return values. + """ + + # Partition the keys by slot + slots_to_keys = self._partition_keys_by_slot(keys) + + # Sum up the reply from each command + return sum(self._execute_pipeline_by_slot(command, slots_to_keys)) + + def exists(self, *keys: KeyT) -> ResponseT: + """ + Returns the number of ``names`` that exist in the + whole cluster. The keys are first split up into slots + and then an EXISTS command is sent for every slot + + For more information see https://redis.io/commands/exists + """ + return self._split_command_across_slots("EXISTS", *keys) + + def delete(self, *keys: KeyT) -> ResponseT: + """ + Deletes the given keys in the cluster. + The keys are first split up into slots + and then an DEL command is sent for every slot + + Non-existant keys are ignored. + Returns the number of keys that were deleted. + + For more information see https://redis.io/commands/del + """ + return self._split_command_across_slots("DEL", *keys) + + def touch(self, *keys: KeyT) -> ResponseT: + """ + Updates the last access time of given keys across the + cluster. + + The keys are first split up into slots + and then an TOUCH command is sent for every slot + + Non-existant keys are ignored. + Returns the number of keys that were touched. + + For more information see https://redis.io/commands/touch + """ + return self._split_command_across_slots("TOUCH", *keys) + + def unlink(self, *keys: KeyT) -> ResponseT: + """ + Remove the specified keys in a different thread. + + The keys are first split up into slots + and then an TOUCH command is sent for every slot + + Non-existant keys are ignored. + Returns the number of keys that were unlinked. + + For more information see https://redis.io/commands/unlink + """ + return self._split_command_across_slots("UNLINK", *keys) + + +class AsyncClusterMultiKeyCommands(ClusterMultiKeyCommands): + """ + A class containing commands that handle more than one key + """ + + async def mget_nonatomic(self, keys: KeysT, *args: KeyT) -> List[Optional[Any]]: + """ + Splits the keys into different slots and then calls MGET + for the keys of every slot. This operation will not be atomic + if keys belong to more than one slot. + + Returns a list of values ordered identically to ``keys`` + + For more information see https://redis.io/commands/mget + """ + + # Concatenate all keys into a list + keys = list_or_args(keys, args) + + # Split keys into slots + slots_to_keys = self._partition_keys_by_slot(keys) + + # Execute commands using a pipeline + res = await self._execute_pipeline_by_slot("MGET", slots_to_keys) + + # Reorder keys in the order the user provided & return + return self._reorder_keys_by_command(keys, slots_to_keys, res) + + async def mset_nonatomic(self, mapping: Mapping[AnyKeyT, EncodableT]) -> List[bool]: + """ + Sets key/values based on a mapping. Mapping is a dictionary of + key/value pairs. Both keys and values should be strings or types that + can be cast to a string via str(). + + Splits the keys into different slots and then calls MSET + for the keys of every slot. This operation will not be atomic + if keys belong to more than one slot. + + For more information see https://redis.io/commands/mset + """ + + # Partition the keys by slot + slots_to_pairs = self._partition_pairs_by_slot(mapping) + + # Execute commands using a pipeline & return list of replies + return await self._execute_pipeline_by_slot("MSET", slots_to_pairs) + + async def _split_command_across_slots(self, command: str, *keys: KeyT) -> int: + """ + Runs the given command once for the keys + of each slot. Returns the sum of the return values. + """ + + # Partition the keys by slot + slots_to_keys = self._partition_keys_by_slot(keys) + + # Sum up the reply from each command + return sum(await self._execute_pipeline_by_slot(command, slots_to_keys)) + + async def _execute_pipeline_by_slot( + self, command: str, slots_to_args: Mapping[int, Iterable[EncodableT]] + ) -> List[Any]: + if self._initialize: + await self.initialize() + read_from_replicas = self.read_from_replicas and command in READ_COMMANDS + pipe = self.pipeline() + [ + pipe.execute_command( + command, + *slot_args, + target_nodes=[ + self.nodes_manager.get_node_from_slot(slot, read_from_replicas) + ], + ) + for slot, slot_args in slots_to_args.items() + ] + return await pipe.execute() + + +class ClusterManagementCommands(ManagementCommands): + """ + A class for Redis Cluster management commands + + The class inherits from Redis's core ManagementCommands class and do the + required adjustments to work with cluster mode + """ + + def slaveof(self, *args, **kwargs) -> NoReturn: + """ + Make the server a replica of another instance, or promote it as master. + + For more information see https://redis.io/commands/slaveof + """ + raise RedisClusterException("SLAVEOF is not supported in cluster mode") + + def replicaof(self, *args, **kwargs) -> NoReturn: + """ + Make the server a replica of another instance, or promote it as master. + + For more information see https://redis.io/commands/replicaof + """ + raise RedisClusterException("REPLICAOF is not supported in cluster mode") + + def swapdb(self, *args, **kwargs) -> NoReturn: + """ + Swaps two Redis databases. + + For more information see https://redis.io/commands/swapdb + """ + raise RedisClusterException("SWAPDB is not supported in cluster mode") + + def cluster_myid(self, target_node: "TargetNodesT") -> ResponseT: + """ + Returns the node's id. + + :target_node: 'ClusterNode' + The node to execute the command on + + For more information check https://redis.io/commands/cluster-myid/ + """ + return self.execute_command("CLUSTER MYID", target_nodes=target_node) + + def cluster_addslots( + self, target_node: "TargetNodesT", *slots: EncodableT + ) -> ResponseT: + """ + Assign new hash slots to receiving node. Sends to specified node. + + :target_node: 'ClusterNode' + The node to execute the command on + + For more information see https://redis.io/commands/cluster-addslots + """ + return self.execute_command( + "CLUSTER ADDSLOTS", *slots, target_nodes=target_node + ) + + def cluster_addslotsrange( + self, target_node: "TargetNodesT", *slots: EncodableT + ) -> ResponseT: + """ + Similar to the CLUSTER ADDSLOTS command. + The difference between the two commands is that ADDSLOTS takes a list of slots + to assign to the node, while ADDSLOTSRANGE takes a list of slot ranges + (specified by start and end slots) to assign to the node. + + :target_node: 'ClusterNode' + The node to execute the command on + + For more information see https://redis.io/commands/cluster-addslotsrange + """ + return self.execute_command( + "CLUSTER ADDSLOTSRANGE", *slots, target_nodes=target_node + ) + + def cluster_countkeysinslot(self, slot_id: int) -> ResponseT: + """ + Return the number of local keys in the specified hash slot + Send to node based on specified slot_id + + For more information see https://redis.io/commands/cluster-countkeysinslot + """ + return self.execute_command("CLUSTER COUNTKEYSINSLOT", slot_id) + + def cluster_count_failure_report(self, node_id: str) -> ResponseT: + """ + Return the number of failure reports active for a given node + Sends to a random node + + For more information see https://redis.io/commands/cluster-count-failure-reports + """ + return self.execute_command("CLUSTER COUNT-FAILURE-REPORTS", node_id) + + def cluster_delslots(self, *slots: EncodableT) -> List[bool]: + """ + Set hash slots as unbound in the cluster. + It determines by it self what node the slot is in and sends it there + + Returns a list of the results for each processed slot. + + For more information see https://redis.io/commands/cluster-delslots + """ + return [self.execute_command("CLUSTER DELSLOTS", slot) for slot in slots] + + def cluster_delslotsrange(self, *slots: EncodableT) -> ResponseT: + """ + Similar to the CLUSTER DELSLOTS command. + The difference is that CLUSTER DELSLOTS takes a list of hash slots to remove + from the node, while CLUSTER DELSLOTSRANGE takes a list of slot ranges to remove + from the node. + + For more information see https://redis.io/commands/cluster-delslotsrange + """ + return self.execute_command("CLUSTER DELSLOTSRANGE", *slots) + + def cluster_failover( + self, target_node: "TargetNodesT", option: Optional[str] = None + ) -> ResponseT: + """ + Forces a slave to perform a manual failover of its master + Sends to specified node + + :target_node: 'ClusterNode' + The node to execute the command on + + For more information see https://redis.io/commands/cluster-failover + """ + if option: + if option.upper() not in ["FORCE", "TAKEOVER"]: + raise RedisError( + f"Invalid option for CLUSTER FAILOVER command: {option}" + ) + else: + return self.execute_command( + "CLUSTER FAILOVER", option, target_nodes=target_node + ) + else: + return self.execute_command("CLUSTER FAILOVER", target_nodes=target_node) + + def cluster_info(self, target_nodes: Optional["TargetNodesT"] = None) -> ResponseT: + """ + Provides info about Redis Cluster node state. + The command will be sent to a random node in the cluster if no target + node is specified. + + For more information see https://redis.io/commands/cluster-info + """ + return self.execute_command("CLUSTER INFO", target_nodes=target_nodes) + + def cluster_keyslot(self, key: str) -> ResponseT: + """ + Returns the hash slot of the specified key + Sends to random node in the cluster + + For more information see https://redis.io/commands/cluster-keyslot + """ + return self.execute_command("CLUSTER KEYSLOT", key) + + def cluster_meet( + self, host: str, port: int, target_nodes: Optional["TargetNodesT"] = None + ) -> ResponseT: + """ + Force a node cluster to handshake with another node. + Sends to specified node. + + For more information see https://redis.io/commands/cluster-meet + """ + return self.execute_command( + "CLUSTER MEET", host, port, target_nodes=target_nodes + ) + + def cluster_nodes(self) -> ResponseT: + """ + Get Cluster config for the node. + Sends to random node in the cluster + + For more information see https://redis.io/commands/cluster-nodes + """ + return self.execute_command("CLUSTER NODES") + + def cluster_replicate( + self, target_nodes: "TargetNodesT", node_id: str + ) -> ResponseT: + """ + Reconfigure a node as a slave of the specified master node + + For more information see https://redis.io/commands/cluster-replicate + """ + return self.execute_command( + "CLUSTER REPLICATE", node_id, target_nodes=target_nodes + ) + + def cluster_reset( + self, soft: bool = True, target_nodes: Optional["TargetNodesT"] = None + ) -> ResponseT: + """ + Reset a Redis Cluster node + + If 'soft' is True then it will send 'SOFT' argument + If 'soft' is False then it will send 'HARD' argument + + For more information see https://redis.io/commands/cluster-reset + """ + return self.execute_command( + "CLUSTER RESET", b"SOFT" if soft else b"HARD", target_nodes=target_nodes + ) + + def cluster_save_config( + self, target_nodes: Optional["TargetNodesT"] = None + ) -> ResponseT: + """ + Forces the node to save cluster state on disk + + For more information see https://redis.io/commands/cluster-saveconfig + """ + return self.execute_command("CLUSTER SAVECONFIG", target_nodes=target_nodes) + + def cluster_get_keys_in_slot(self, slot: int, num_keys: int) -> ResponseT: + """ + Returns the number of keys in the specified cluster slot + + For more information see https://redis.io/commands/cluster-getkeysinslot + """ + return self.execute_command("CLUSTER GETKEYSINSLOT", slot, num_keys) + + def cluster_set_config_epoch( + self, epoch: int, target_nodes: Optional["TargetNodesT"] = None + ) -> ResponseT: + """ + Set the configuration epoch in a new node + + For more information see https://redis.io/commands/cluster-set-config-epoch + """ + return self.execute_command( + "CLUSTER SET-CONFIG-EPOCH", epoch, target_nodes=target_nodes + ) + + def cluster_setslot( + self, target_node: "TargetNodesT", node_id: str, slot_id: int, state: str + ) -> ResponseT: + """ + Bind an hash slot to a specific node + + :target_node: 'ClusterNode' + The node to execute the command on + + For more information see https://redis.io/commands/cluster-setslot + """ + if state.upper() in ("IMPORTING", "NODE", "MIGRATING"): + return self.execute_command( + "CLUSTER SETSLOT", slot_id, state, node_id, target_nodes=target_node + ) + elif state.upper() == "STABLE": + raise RedisError('For "stable" state please use ' "cluster_setslot_stable") + else: + raise RedisError(f"Invalid slot state: {state}") + + def cluster_setslot_stable(self, slot_id: int) -> ResponseT: + """ + Clears migrating / importing state from the slot. + It determines by it self what node the slot is in and sends it there. + + For more information see https://redis.io/commands/cluster-setslot + """ + return self.execute_command("CLUSTER SETSLOT", slot_id, "STABLE") + + def cluster_replicas( + self, node_id: str, target_nodes: Optional["TargetNodesT"] = None + ) -> ResponseT: + """ + Provides a list of replica nodes replicating from the specified primary + target node. + + For more information see https://redis.io/commands/cluster-replicas + """ + return self.execute_command( + "CLUSTER REPLICAS", node_id, target_nodes=target_nodes + ) + + def cluster_slots(self, target_nodes: Optional["TargetNodesT"] = None) -> ResponseT: + """ + Get array of Cluster slot to node mappings + + For more information see https://redis.io/commands/cluster-slots + """ + return self.execute_command("CLUSTER SLOTS", target_nodes=target_nodes) + + def cluster_shards(self, target_nodes=None): + """ + Returns details about the shards of the cluster. + + For more information see https://redis.io/commands/cluster-shards + """ + return self.execute_command("CLUSTER SHARDS", target_nodes=target_nodes) + + def cluster_myshardid(self, target_nodes=None): + """ + Returns the shard ID of the node. + + For more information see https://redis.io/commands/cluster-myshardid/ + """ + return self.execute_command("CLUSTER MYSHARDID", target_nodes=target_nodes) + + def cluster_links(self, target_node: "TargetNodesT") -> ResponseT: + """ + Each node in a Redis Cluster maintains a pair of long-lived TCP link with each + peer in the cluster: One for sending outbound messages towards the peer and one + for receiving inbound messages from the peer. + + This command outputs information of all such peer links as an array. + + For more information see https://redis.io/commands/cluster-links + """ + return self.execute_command("CLUSTER LINKS", target_nodes=target_node) + + def cluster_flushslots(self, target_nodes: Optional["TargetNodesT"] = None) -> None: + raise NotImplementedError( + "CLUSTER FLUSHSLOTS is intentionally not implemented in the client." + ) + + def cluster_bumpepoch(self, target_nodes: Optional["TargetNodesT"] = None) -> None: + raise NotImplementedError( + "CLUSTER BUMPEPOCH is intentionally not implemented in the client." + ) + + def readonly(self, target_nodes: Optional["TargetNodesT"] = None) -> ResponseT: + """ + Enables read queries. + The command will be sent to the default cluster node if target_nodes is + not specified. + + For more information see https://redis.io/commands/readonly + """ + if target_nodes == "replicas" or target_nodes == "all": + # read_from_replicas will only be enabled if the READONLY command + # is sent to all replicas + self.read_from_replicas = True + return self.execute_command("READONLY", target_nodes=target_nodes) + + def readwrite(self, target_nodes: Optional["TargetNodesT"] = None) -> ResponseT: + """ + Disables read queries. + The command will be sent to the default cluster node if target_nodes is + not specified. + + For more information see https://redis.io/commands/readwrite + """ + # Reset read from replicas flag + self.read_from_replicas = False + return self.execute_command("READWRITE", target_nodes=target_nodes) + + def gears_refresh_cluster(self, **kwargs) -> ResponseT: + """ + On an OSS cluster, before executing any gears function, you must call this command. # noqa + """ + return self.execute_command("REDISGEARS_2.REFRESHCLUSTER", **kwargs) + + +class AsyncClusterManagementCommands( + ClusterManagementCommands, AsyncManagementCommands +): + """ + A class for Redis Cluster management commands + + The class inherits from Redis's core ManagementCommands class and do the + required adjustments to work with cluster mode + """ + + async def cluster_delslots(self, *slots: EncodableT) -> List[bool]: + """ + Set hash slots as unbound in the cluster. + It determines by it self what node the slot is in and sends it there + + Returns a list of the results for each processed slot. + + For more information see https://redis.io/commands/cluster-delslots + """ + return await asyncio.gather( + *( + asyncio.create_task(self.execute_command("CLUSTER DELSLOTS", slot)) + for slot in slots + ) + ) + + +class ClusterDataAccessCommands(DataAccessCommands): + """ + A class for Redis Cluster Data Access Commands + + The class inherits from Redis's core DataAccessCommand class and do the + required adjustments to work with cluster mode + """ + + def stralgo( + self, + algo: Literal["LCS"], + value1: KeyT, + value2: KeyT, + specific_argument: Union[Literal["strings"], Literal["keys"]] = "strings", + len: bool = False, + idx: bool = False, + minmatchlen: Optional[int] = None, + withmatchlen: bool = False, + **kwargs, + ) -> ResponseT: + """ + Implements complex algorithms that operate on strings. + Right now the only algorithm implemented is the LCS algorithm + (longest common substring). However new algorithms could be + implemented in the future. + + ``algo`` Right now must be LCS + ``value1`` and ``value2`` Can be two strings or two keys + ``specific_argument`` Specifying if the arguments to the algorithm + will be keys or strings. strings is the default. + ``len`` Returns just the len of the match. + ``idx`` Returns the match positions in each string. + ``minmatchlen`` Restrict the list of matches to the ones of a given + minimal length. Can be provided only when ``idx`` set to True. + ``withmatchlen`` Returns the matches with the len of the match. + Can be provided only when ``idx`` set to True. + + For more information see https://redis.io/commands/stralgo + """ + target_nodes = kwargs.pop("target_nodes", None) + if specific_argument == "strings" and target_nodes is None: + target_nodes = "default-node" + kwargs.update({"target_nodes": target_nodes}) + return super().stralgo( + algo, + value1, + value2, + specific_argument, + len, + idx, + minmatchlen, + withmatchlen, + **kwargs, + ) + + def scan_iter( + self, + match: Optional[PatternT] = None, + count: Optional[int] = None, + _type: Optional[str] = None, + **kwargs, + ) -> Iterator: + # Do the first query with cursor=0 for all nodes + cursors, data = self.scan(match=match, count=count, _type=_type, **kwargs) + yield from data + + cursors = {name: cursor for name, cursor in cursors.items() if cursor != 0} + if cursors: + # Get nodes by name + nodes = {name: self.get_node(node_name=name) for name in cursors.keys()} + + # Iterate over each node till its cursor is 0 + kwargs.pop("target_nodes", None) + while cursors: + for name, cursor in cursors.items(): + cur, data = self.scan( + cursor=cursor, + match=match, + count=count, + _type=_type, + target_nodes=nodes[name], + **kwargs, + ) + yield from data + cursors[name] = cur[name] + + cursors = { + name: cursor for name, cursor in cursors.items() if cursor != 0 + } + + +class AsyncClusterDataAccessCommands( + ClusterDataAccessCommands, AsyncDataAccessCommands +): + """ + A class for Redis Cluster Data Access Commands + + The class inherits from Redis's core DataAccessCommand class and do the + required adjustments to work with cluster mode + """ + + async def scan_iter( + self, + match: Optional[PatternT] = None, + count: Optional[int] = None, + _type: Optional[str] = None, + **kwargs, + ) -> AsyncIterator: + # Do the first query with cursor=0 for all nodes + cursors, data = await self.scan(match=match, count=count, _type=_type, **kwargs) + for value in data: + yield value + + cursors = {name: cursor for name, cursor in cursors.items() if cursor != 0} + if cursors: + # Get nodes by name + nodes = {name: self.get_node(node_name=name) for name in cursors.keys()} + + # Iterate over each node till its cursor is 0 + kwargs.pop("target_nodes", None) + while cursors: + for name, cursor in cursors.items(): + cur, data = await self.scan( + cursor=cursor, + match=match, + count=count, + _type=_type, + target_nodes=nodes[name], + **kwargs, + ) + for value in data: + yield value + cursors[name] = cur[name] + + cursors = { + name: cursor for name, cursor in cursors.items() if cursor != 0 + } + + +class RedisClusterCommands( + ClusterMultiKeyCommands, + ClusterManagementCommands, + ACLCommands, + PubSubCommands, + ClusterDataAccessCommands, + ScriptCommands, + FunctionCommands, + GearsCommands, + ModuleCommands, + RedisModuleCommands, +): + """ + A class for all Redis Cluster commands + + For key-based commands, the target node(s) will be internally determined + by the keys' hash slot. + Non-key-based commands can be executed with the 'target_nodes' argument to + target specific nodes. By default, if target_nodes is not specified, the + command will be executed on the default cluster node. + + :param :target_nodes: type can be one of the followings: + - nodes flag: ALL_NODES, PRIMARIES, REPLICAS, RANDOM + - 'ClusterNode' + - 'list(ClusterNodes)' + - 'dict(any:clusterNodes)' + + for example: + r.cluster_info(target_nodes=RedisCluster.ALL_NODES) + """ + + +class AsyncRedisClusterCommands( + AsyncClusterMultiKeyCommands, + AsyncClusterManagementCommands, + AsyncACLCommands, + AsyncClusterDataAccessCommands, + AsyncScriptCommands, + AsyncFunctionCommands, + AsyncGearsCommands, + AsyncModuleCommands, +): + """ + A class for all Redis Cluster commands + + For key-based commands, the target node(s) will be internally determined + by the keys' hash slot. + Non-key-based commands can be executed with the 'target_nodes' argument to + target specific nodes. By default, if target_nodes is not specified, the + command will be executed on the default cluster node. + + :param :target_nodes: type can be one of the followings: + - nodes flag: ALL_NODES, PRIMARIES, REPLICAS, RANDOM + - 'ClusterNode' + - 'list(ClusterNodes)' + - 'dict(any:clusterNodes)' + + for example: + r.cluster_info(target_nodes=RedisCluster.ALL_NODES) + """ diff --git a/.venv/Lib/site-packages/redis/commands/core.py b/.venv/Lib/site-packages/redis/commands/core.py new file mode 100644 index 00000000..e73553e4 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/core.py @@ -0,0 +1,6305 @@ +# from __future__ import annotations + +import datetime +import hashlib +import warnings +from typing import ( + TYPE_CHECKING, + Any, + AsyncIterator, + Awaitable, + Callable, + Dict, + Iterable, + Iterator, + List, + Mapping, + Optional, + Sequence, + Set, + Tuple, + Union, +) + +from redis.compat import Literal +from redis.exceptions import ConnectionError, DataError, NoScriptError, RedisError +from redis.typing import ( + AbsExpiryT, + AnyKeyT, + BitfieldOffsetT, + ChannelT, + CommandsProtocol, + ConsumerT, + EncodableT, + ExpiryT, + FieldT, + GroupT, + KeysT, + KeyT, + PatternT, + ScriptTextT, + StreamIdT, + TimeoutSecT, + ZScoreBoundT, +) + +from .helpers import list_or_args + +if TYPE_CHECKING: + from redis.asyncio.client import Redis as AsyncRedis + from redis.client import Redis + +ResponseT = Union[Awaitable, Any] + + +class ACLCommands(CommandsProtocol): + """ + Redis Access Control List (ACL) commands. + see: https://redis.io/topics/acl + """ + + def acl_cat(self, category: Union[str, None] = None, **kwargs) -> ResponseT: + """ + Returns a list of categories or commands within a category. + + If ``category`` is not supplied, returns a list of all categories. + If ``category`` is supplied, returns a list of all commands within + that category. + + For more information see https://redis.io/commands/acl-cat + """ + pieces: list[EncodableT] = [category] if category else [] + return self.execute_command("ACL CAT", *pieces, **kwargs) + + def acl_dryrun(self, username, *args, **kwargs): + """ + Simulate the execution of a given command by a given ``username``. + + For more information see https://redis.io/commands/acl-dryrun + """ + return self.execute_command("ACL DRYRUN", username, *args, **kwargs) + + def acl_deluser(self, *username: str, **kwargs) -> ResponseT: + """ + Delete the ACL for the specified ``username``s + + For more information see https://redis.io/commands/acl-deluser + """ + return self.execute_command("ACL DELUSER", *username, **kwargs) + + def acl_genpass(self, bits: Union[int, None] = None, **kwargs) -> ResponseT: + """Generate a random password value. + If ``bits`` is supplied then use this number of bits, rounded to + the next multiple of 4. + See: https://redis.io/commands/acl-genpass + """ + pieces = [] + if bits is not None: + try: + b = int(bits) + if b < 0 or b > 4096: + raise ValueError + except ValueError: + raise DataError( + "genpass optionally accepts a bits argument, between 0 and 4096." + ) + return self.execute_command("ACL GENPASS", *pieces, **kwargs) + + def acl_getuser(self, username: str, **kwargs) -> ResponseT: + """ + Get the ACL details for the specified ``username``. + + If ``username`` does not exist, return None + + For more information see https://redis.io/commands/acl-getuser + """ + return self.execute_command("ACL GETUSER", username, **kwargs) + + def acl_help(self, **kwargs) -> ResponseT: + """The ACL HELP command returns helpful text describing + the different subcommands. + + For more information see https://redis.io/commands/acl-help + """ + return self.execute_command("ACL HELP", **kwargs) + + def acl_list(self, **kwargs) -> ResponseT: + """ + Return a list of all ACLs on the server + + For more information see https://redis.io/commands/acl-list + """ + return self.execute_command("ACL LIST", **kwargs) + + def acl_log(self, count: Union[int, None] = None, **kwargs) -> ResponseT: + """ + Get ACL logs as a list. + :param int count: Get logs[0:count]. + :rtype: List. + + For more information see https://redis.io/commands/acl-log + """ + args = [] + if count is not None: + if not isinstance(count, int): + raise DataError("ACL LOG count must be an integer") + args.append(count) + + return self.execute_command("ACL LOG", *args, **kwargs) + + def acl_log_reset(self, **kwargs) -> ResponseT: + """ + Reset ACL logs. + :rtype: Boolean. + + For more information see https://redis.io/commands/acl-log + """ + args = [b"RESET"] + return self.execute_command("ACL LOG", *args, **kwargs) + + def acl_load(self, **kwargs) -> ResponseT: + """ + Load ACL rules from the configured ``aclfile``. + + Note that the server must be configured with the ``aclfile`` + directive to be able to load ACL rules from an aclfile. + + For more information see https://redis.io/commands/acl-load + """ + return self.execute_command("ACL LOAD", **kwargs) + + def acl_save(self, **kwargs) -> ResponseT: + """ + Save ACL rules to the configured ``aclfile``. + + Note that the server must be configured with the ``aclfile`` + directive to be able to save ACL rules to an aclfile. + + For more information see https://redis.io/commands/acl-save + """ + return self.execute_command("ACL SAVE", **kwargs) + + def acl_setuser( + self, + username: str, + enabled: bool = False, + nopass: bool = False, + passwords: Union[str, Iterable[str], None] = None, + hashed_passwords: Union[str, Iterable[str], None] = None, + categories: Optional[Iterable[str]] = None, + commands: Optional[Iterable[str]] = None, + keys: Optional[Iterable[KeyT]] = None, + channels: Optional[Iterable[ChannelT]] = None, + selectors: Optional[Iterable[Tuple[str, KeyT]]] = None, + reset: bool = False, + reset_keys: bool = False, + reset_channels: bool = False, + reset_passwords: bool = False, + **kwargs, + ) -> ResponseT: + """ + Create or update an ACL user. + + Create or update the ACL for ``username``. If the user already exists, + the existing ACL is completely overwritten and replaced with the + specified values. + + ``enabled`` is a boolean indicating whether the user should be allowed + to authenticate or not. Defaults to ``False``. + + ``nopass`` is a boolean indicating whether the can authenticate without + a password. This cannot be True if ``passwords`` are also specified. + + ``passwords`` if specified is a list of plain text passwords + to add to or remove from the user. Each password must be prefixed with + a '+' to add or a '-' to remove. For convenience, the value of + ``passwords`` can be a simple prefixed string when adding or + removing a single password. + + ``hashed_passwords`` if specified is a list of SHA-256 hashed passwords + to add to or remove from the user. Each hashed password must be + prefixed with a '+' to add or a '-' to remove. For convenience, + the value of ``hashed_passwords`` can be a simple prefixed string when + adding or removing a single password. + + ``categories`` if specified is a list of strings representing category + permissions. Each string must be prefixed with either a '+' to add the + category permission or a '-' to remove the category permission. + + ``commands`` if specified is a list of strings representing command + permissions. Each string must be prefixed with either a '+' to add the + command permission or a '-' to remove the command permission. + + ``keys`` if specified is a list of key patterns to grant the user + access to. Keys patterns allow '*' to support wildcard matching. For + example, '*' grants access to all keys while 'cache:*' grants access + to all keys that are prefixed with 'cache:'. ``keys`` should not be + prefixed with a '~'. + + ``reset`` is a boolean indicating whether the user should be fully + reset prior to applying the new ACL. Setting this to True will + remove all existing passwords, flags and privileges from the user and + then apply the specified rules. If this is False, the user's existing + passwords, flags and privileges will be kept and any new specified + rules will be applied on top. + + ``reset_keys`` is a boolean indicating whether the user's key + permissions should be reset prior to applying any new key permissions + specified in ``keys``. If this is False, the user's existing + key permissions will be kept and any new specified key permissions + will be applied on top. + + ``reset_channels`` is a boolean indicating whether the user's channel + permissions should be reset prior to applying any new channel permissions + specified in ``channels``.If this is False, the user's existing + channel permissions will be kept and any new specified channel permissions + will be applied on top. + + ``reset_passwords`` is a boolean indicating whether to remove all + existing passwords and the 'nopass' flag from the user prior to + applying any new passwords specified in 'passwords' or + 'hashed_passwords'. If this is False, the user's existing passwords + and 'nopass' status will be kept and any new specified passwords + or hashed_passwords will be applied on top. + + For more information see https://redis.io/commands/acl-setuser + """ + encoder = self.get_encoder() + pieces: List[EncodableT] = [username] + + if reset: + pieces.append(b"reset") + + if reset_keys: + pieces.append(b"resetkeys") + + if reset_channels: + pieces.append(b"resetchannels") + + if reset_passwords: + pieces.append(b"resetpass") + + if enabled: + pieces.append(b"on") + else: + pieces.append(b"off") + + if (passwords or hashed_passwords) and nopass: + raise DataError( + "Cannot set 'nopass' and supply 'passwords' or 'hashed_passwords'" + ) + + if passwords: + # as most users will have only one password, allow remove_passwords + # to be specified as a simple string or a list + passwords = list_or_args(passwords, []) + for i, password in enumerate(passwords): + password = encoder.encode(password) + if password.startswith(b"+"): + pieces.append(b">%s" % password[1:]) + elif password.startswith(b"-"): + pieces.append(b"<%s" % password[1:]) + else: + raise DataError( + f"Password {i} must be prefixed with a " + f'"+" to add or a "-" to remove' + ) + + if hashed_passwords: + # as most users will have only one password, allow remove_passwords + # to be specified as a simple string or a list + hashed_passwords = list_or_args(hashed_passwords, []) + for i, hashed_password in enumerate(hashed_passwords): + hashed_password = encoder.encode(hashed_password) + if hashed_password.startswith(b"+"): + pieces.append(b"#%s" % hashed_password[1:]) + elif hashed_password.startswith(b"-"): + pieces.append(b"!%s" % hashed_password[1:]) + else: + raise DataError( + f"Hashed password {i} must be prefixed with a " + f'"+" to add or a "-" to remove' + ) + + if nopass: + pieces.append(b"nopass") + + if categories: + for category in categories: + category = encoder.encode(category) + # categories can be prefixed with one of (+@, +, -@, -) + if category.startswith(b"+@"): + pieces.append(category) + elif category.startswith(b"+"): + pieces.append(b"+@%s" % category[1:]) + elif category.startswith(b"-@"): + pieces.append(category) + elif category.startswith(b"-"): + pieces.append(b"-@%s" % category[1:]) + else: + raise DataError( + f'Category "{encoder.decode(category, force=True)}" ' + 'must be prefixed with "+" or "-"' + ) + if commands: + for cmd in commands: + cmd = encoder.encode(cmd) + if not cmd.startswith(b"+") and not cmd.startswith(b"-"): + raise DataError( + f'Command "{encoder.decode(cmd, force=True)}" ' + 'must be prefixed with "+" or "-"' + ) + pieces.append(cmd) + + if keys: + for key in keys: + key = encoder.encode(key) + if not key.startswith(b"%") and not key.startswith(b"~"): + key = b"~%s" % key + pieces.append(key) + + if channels: + for channel in channels: + channel = encoder.encode(channel) + pieces.append(b"&%s" % channel) + + if selectors: + for cmd, key in selectors: + cmd = encoder.encode(cmd) + if not cmd.startswith(b"+") and not cmd.startswith(b"-"): + raise DataError( + f'Command "{encoder.decode(cmd, force=True)}" ' + 'must be prefixed with "+" or "-"' + ) + + key = encoder.encode(key) + if not key.startswith(b"%") and not key.startswith(b"~"): + key = b"~%s" % key + + pieces.append(b"(%s %s)" % (cmd, key)) + + return self.execute_command("ACL SETUSER", *pieces, **kwargs) + + def acl_users(self, **kwargs) -> ResponseT: + """Returns a list of all registered users on the server. + + For more information see https://redis.io/commands/acl-users + """ + return self.execute_command("ACL USERS", **kwargs) + + def acl_whoami(self, **kwargs) -> ResponseT: + """Get the username for the current connection + + For more information see https://redis.io/commands/acl-whoami + """ + return self.execute_command("ACL WHOAMI", **kwargs) + + +AsyncACLCommands = ACLCommands + + +class ManagementCommands(CommandsProtocol): + """ + Redis management commands + """ + + def auth(self, password: str, username: Optional[str] = None, **kwargs): + """ + Authenticates the user. If you do not pass username, Redis will try to + authenticate for the "default" user. If you do pass username, it will + authenticate for the given user. + For more information see https://redis.io/commands/auth + """ + pieces = [] + if username is not None: + pieces.append(username) + pieces.append(password) + return self.execute_command("AUTH", *pieces, **kwargs) + + def bgrewriteaof(self, **kwargs): + """Tell the Redis server to rewrite the AOF file from data in memory. + + For more information see https://redis.io/commands/bgrewriteaof + """ + return self.execute_command("BGREWRITEAOF", **kwargs) + + def bgsave(self, schedule: bool = True, **kwargs) -> ResponseT: + """ + Tell the Redis server to save its data to disk. Unlike save(), + this method is asynchronous and returns immediately. + + For more information see https://redis.io/commands/bgsave + """ + pieces = [] + if schedule: + pieces.append("SCHEDULE") + return self.execute_command("BGSAVE", *pieces, **kwargs) + + def role(self) -> ResponseT: + """ + Provide information on the role of a Redis instance in + the context of replication, by returning if the instance + is currently a master, slave, or sentinel. + + For more information see https://redis.io/commands/role + """ + return self.execute_command("ROLE") + + def client_kill(self, address: str, **kwargs) -> ResponseT: + """Disconnects the client at ``address`` (ip:port) + + For more information see https://redis.io/commands/client-kill + """ + return self.execute_command("CLIENT KILL", address, **kwargs) + + def client_kill_filter( + self, + _id: Union[str, None] = None, + _type: Union[str, None] = None, + addr: Union[str, None] = None, + skipme: Union[bool, None] = None, + laddr: Union[bool, None] = None, + user: str = None, + **kwargs, + ) -> ResponseT: + """ + Disconnects client(s) using a variety of filter options + :param _id: Kills a client by its unique ID field + :param _type: Kills a client by type where type is one of 'normal', + 'master', 'slave' or 'pubsub' + :param addr: Kills a client by its 'address:port' + :param skipme: If True, then the client calling the command + will not get killed even if it is identified by one of the filter + options. If skipme is not provided, the server defaults to skipme=True + :param laddr: Kills a client by its 'local (bind) address:port' + :param user: Kills a client for a specific user name + """ + args = [] + if _type is not None: + client_types = ("normal", "master", "slave", "pubsub") + if str(_type).lower() not in client_types: + raise DataError(f"CLIENT KILL type must be one of {client_types!r}") + args.extend((b"TYPE", _type)) + if skipme is not None: + if not isinstance(skipme, bool): + raise DataError("CLIENT KILL skipme must be a bool") + if skipme: + args.extend((b"SKIPME", b"YES")) + else: + args.extend((b"SKIPME", b"NO")) + if _id is not None: + args.extend((b"ID", _id)) + if addr is not None: + args.extend((b"ADDR", addr)) + if laddr is not None: + args.extend((b"LADDR", laddr)) + if user is not None: + args.extend((b"USER", user)) + if not args: + raise DataError( + "CLIENT KILL ... ... " + " must specify at least one filter" + ) + return self.execute_command("CLIENT KILL", *args, **kwargs) + + def client_info(self, **kwargs) -> ResponseT: + """ + Returns information and statistics about the current + client connection. + + For more information see https://redis.io/commands/client-info + """ + return self.execute_command("CLIENT INFO", **kwargs) + + def client_list( + self, _type: Union[str, None] = None, client_id: List[EncodableT] = [], **kwargs + ) -> ResponseT: + """ + Returns a list of currently connected clients. + If type of client specified, only that type will be returned. + + :param _type: optional. one of the client types (normal, master, + replica, pubsub) + :param client_id: optional. a list of client ids + + For more information see https://redis.io/commands/client-list + """ + args = [] + if _type is not None: + client_types = ("normal", "master", "replica", "pubsub") + if str(_type).lower() not in client_types: + raise DataError(f"CLIENT LIST _type must be one of {client_types!r}") + args.append(b"TYPE") + args.append(_type) + if not isinstance(client_id, list): + raise DataError("client_id must be a list") + if client_id: + args.append(b"ID") + args.append(" ".join(client_id)) + return self.execute_command("CLIENT LIST", *args, **kwargs) + + def client_getname(self, **kwargs) -> ResponseT: + """ + Returns the current connection name + + For more information see https://redis.io/commands/client-getname + """ + return self.execute_command("CLIENT GETNAME", **kwargs) + + def client_getredir(self, **kwargs) -> ResponseT: + """ + Returns the ID (an integer) of the client to whom we are + redirecting tracking notifications. + + see: https://redis.io/commands/client-getredir + """ + return self.execute_command("CLIENT GETREDIR", **kwargs) + + def client_reply( + self, reply: Union[Literal["ON"], Literal["OFF"], Literal["SKIP"]], **kwargs + ) -> ResponseT: + """ + Enable and disable redis server replies. + + ``reply`` Must be ON OFF or SKIP, + ON - The default most with server replies to commands + OFF - Disable server responses to commands + SKIP - Skip the response of the immediately following command. + + Note: When setting OFF or SKIP replies, you will need a client object + with a timeout specified in seconds, and will need to catch the + TimeoutError. + The test_client_reply unit test illustrates this, and + conftest.py has a client with a timeout. + + See https://redis.io/commands/client-reply + """ + replies = ["ON", "OFF", "SKIP"] + if reply not in replies: + raise DataError(f"CLIENT REPLY must be one of {replies!r}") + return self.execute_command("CLIENT REPLY", reply, **kwargs) + + def client_id(self, **kwargs) -> ResponseT: + """ + Returns the current connection id + + For more information see https://redis.io/commands/client-id + """ + return self.execute_command("CLIENT ID", **kwargs) + + def client_tracking_on( + self, + clientid: Union[int, None] = None, + prefix: Sequence[KeyT] = [], + bcast: bool = False, + optin: bool = False, + optout: bool = False, + noloop: bool = False, + ) -> ResponseT: + """ + Turn on the tracking mode. + For more information about the options look at client_tracking func. + + See https://redis.io/commands/client-tracking + """ + return self.client_tracking( + True, clientid, prefix, bcast, optin, optout, noloop + ) + + def client_tracking_off( + self, + clientid: Union[int, None] = None, + prefix: Sequence[KeyT] = [], + bcast: bool = False, + optin: bool = False, + optout: bool = False, + noloop: bool = False, + ) -> ResponseT: + """ + Turn off the tracking mode. + For more information about the options look at client_tracking func. + + See https://redis.io/commands/client-tracking + """ + return self.client_tracking( + False, clientid, prefix, bcast, optin, optout, noloop + ) + + def client_tracking( + self, + on: bool = True, + clientid: Union[int, None] = None, + prefix: Sequence[KeyT] = [], + bcast: bool = False, + optin: bool = False, + optout: bool = False, + noloop: bool = False, + **kwargs, + ) -> ResponseT: + """ + Enables the tracking feature of the Redis server, that is used + for server assisted client side caching. + + ``on`` indicate for tracking on or tracking off. The dafualt is on. + + ``clientid`` send invalidation messages to the connection with + the specified ID. + + ``bcast`` enable tracking in broadcasting mode. In this mode + invalidation messages are reported for all the prefixes + specified, regardless of the keys requested by the connection. + + ``optin`` when broadcasting is NOT active, normally don't track + keys in read only commands, unless they are called immediately + after a CLIENT CACHING yes command. + + ``optout`` when broadcasting is NOT active, normally track keys in + read only commands, unless they are called immediately after a + CLIENT CACHING no command. + + ``noloop`` don't send notifications about keys modified by this + connection itself. + + ``prefix`` for broadcasting, register a given key prefix, so that + notifications will be provided only for keys starting with this string. + + See https://redis.io/commands/client-tracking + """ + + if len(prefix) != 0 and bcast is False: + raise DataError("Prefix can only be used with bcast") + + pieces = ["ON"] if on else ["OFF"] + if clientid is not None: + pieces.extend(["REDIRECT", clientid]) + for p in prefix: + pieces.extend(["PREFIX", p]) + if bcast: + pieces.append("BCAST") + if optin: + pieces.append("OPTIN") + if optout: + pieces.append("OPTOUT") + if noloop: + pieces.append("NOLOOP") + + return self.execute_command("CLIENT TRACKING", *pieces) + + def client_trackinginfo(self, **kwargs) -> ResponseT: + """ + Returns the information about the current client connection's + use of the server assisted client side cache. + + See https://redis.io/commands/client-trackinginfo + """ + return self.execute_command("CLIENT TRACKINGINFO", **kwargs) + + def client_setname(self, name: str, **kwargs) -> ResponseT: + """ + Sets the current connection name + + For more information see https://redis.io/commands/client-setname + + .. note:: + This method sets client name only for **current** connection. + + If you want to set a common name for all connections managed + by this client, use ``client_name`` constructor argument. + """ + return self.execute_command("CLIENT SETNAME", name, **kwargs) + + def client_setinfo(self, attr: str, value: str, **kwargs) -> ResponseT: + """ + Sets the current connection library name or version + For mor information see https://redis.io/commands/client-setinfo + """ + return self.execute_command("CLIENT SETINFO", attr, value, **kwargs) + + def client_unblock( + self, client_id: int, error: bool = False, **kwargs + ) -> ResponseT: + """ + Unblocks a connection by its client id. + If ``error`` is True, unblocks the client with a special error message. + If ``error`` is False (default), the client is unblocked using the + regular timeout mechanism. + + For more information see https://redis.io/commands/client-unblock + """ + args = ["CLIENT UNBLOCK", int(client_id)] + if error: + args.append(b"ERROR") + return self.execute_command(*args, **kwargs) + + def client_pause(self, timeout: int, all: bool = True, **kwargs) -> ResponseT: + """ + Suspend all the Redis clients for the specified amount of time. + + + For more information see https://redis.io/commands/client-pause + + :param timeout: milliseconds to pause clients + :param all: If true (default) all client commands are blocked. + otherwise, clients are only blocked if they attempt to execute + a write command. + For the WRITE mode, some commands have special behavior: + EVAL/EVALSHA: Will block client for all scripts. + PUBLISH: Will block client. + PFCOUNT: Will block client. + WAIT: Acknowledgments will be delayed, so this command will + appear blocked. + """ + args = ["CLIENT PAUSE", str(timeout)] + if not isinstance(timeout, int): + raise DataError("CLIENT PAUSE timeout must be an integer") + if not all: + args.append("WRITE") + return self.execute_command(*args, **kwargs) + + def client_unpause(self, **kwargs) -> ResponseT: + """ + Unpause all redis clients + + For more information see https://redis.io/commands/client-unpause + """ + return self.execute_command("CLIENT UNPAUSE", **kwargs) + + def client_no_evict(self, mode: str) -> Union[Awaitable[str], str]: + """ + Sets the client eviction mode for the current connection. + + For more information see https://redis.io/commands/client-no-evict + """ + return self.execute_command("CLIENT NO-EVICT", mode) + + def client_no_touch(self, mode: str) -> Union[Awaitable[str], str]: + """ + # The command controls whether commands sent by the client will alter + # the LRU/LFU of the keys they access. + # When turned on, the current client will not change LFU/LRU stats, + # unless it sends the TOUCH command. + + For more information see https://redis.io/commands/client-no-touch + """ + return self.execute_command("CLIENT NO-TOUCH", mode) + + def command(self, **kwargs): + """ + Returns dict reply of details about all Redis commands. + + For more information see https://redis.io/commands/command + """ + return self.execute_command("COMMAND", **kwargs) + + def command_info(self, **kwargs) -> None: + raise NotImplementedError( + "COMMAND INFO is intentionally not implemented in the client." + ) + + def command_count(self, **kwargs) -> ResponseT: + return self.execute_command("COMMAND COUNT", **kwargs) + + def command_list( + self, + module: Optional[str] = None, + category: Optional[str] = None, + pattern: Optional[str] = None, + ) -> ResponseT: + """ + Return an array of the server's command names. + You can use one of the following filters: + ``module``: get the commands that belong to the module + ``category``: get the commands in the ACL category + ``pattern``: get the commands that match the given pattern + + For more information see https://redis.io/commands/command-list/ + """ + pieces = [] + if module is not None: + pieces.extend(["MODULE", module]) + if category is not None: + pieces.extend(["ACLCAT", category]) + if pattern is not None: + pieces.extend(["PATTERN", pattern]) + + if pieces: + pieces.insert(0, "FILTERBY") + + return self.execute_command("COMMAND LIST", *pieces) + + def command_getkeysandflags(self, *args: List[str]) -> List[Union[str, List[str]]]: + """ + Returns array of keys from a full Redis command and their usage flags. + + For more information see https://redis.io/commands/command-getkeysandflags + """ + return self.execute_command("COMMAND GETKEYSANDFLAGS", *args) + + def command_docs(self, *args): + """ + This function throws a NotImplementedError since it is intentionally + not supported. + """ + raise NotImplementedError( + "COMMAND DOCS is intentionally not implemented in the client." + ) + + def config_get( + self, pattern: PatternT = "*", *args: List[PatternT], **kwargs + ) -> ResponseT: + """ + Return a dictionary of configuration based on the ``pattern`` + + For more information see https://redis.io/commands/config-get + """ + return self.execute_command("CONFIG GET", pattern, *args, **kwargs) + + def config_set( + self, + name: KeyT, + value: EncodableT, + *args: List[Union[KeyT, EncodableT]], + **kwargs, + ) -> ResponseT: + """Set config item ``name`` with ``value`` + + For more information see https://redis.io/commands/config-set + """ + return self.execute_command("CONFIG SET", name, value, *args, **kwargs) + + def config_resetstat(self, **kwargs) -> ResponseT: + """ + Reset runtime statistics + + For more information see https://redis.io/commands/config-resetstat + """ + return self.execute_command("CONFIG RESETSTAT", **kwargs) + + def config_rewrite(self, **kwargs) -> ResponseT: + """ + Rewrite config file with the minimal change to reflect running config. + + For more information see https://redis.io/commands/config-rewrite + """ + return self.execute_command("CONFIG REWRITE", **kwargs) + + def dbsize(self, **kwargs) -> ResponseT: + """ + Returns the number of keys in the current database + + For more information see https://redis.io/commands/dbsize + """ + return self.execute_command("DBSIZE", **kwargs) + + def debug_object(self, key: KeyT, **kwargs) -> ResponseT: + """ + Returns version specific meta information about a given key + + For more information see https://redis.io/commands/debug-object + """ + return self.execute_command("DEBUG OBJECT", key, **kwargs) + + def debug_segfault(self, **kwargs) -> None: + raise NotImplementedError( + """ + DEBUG SEGFAULT is intentionally not implemented in the client. + + For more information see https://redis.io/commands/debug-segfault + """ + ) + + def echo(self, value: EncodableT, **kwargs) -> ResponseT: + """ + Echo the string back from the server + + For more information see https://redis.io/commands/echo + """ + return self.execute_command("ECHO", value, **kwargs) + + def flushall(self, asynchronous: bool = False, **kwargs) -> ResponseT: + """ + Delete all keys in all databases on the current host. + + ``asynchronous`` indicates whether the operation is + executed asynchronously by the server. + + For more information see https://redis.io/commands/flushall + """ + args = [] + if asynchronous: + args.append(b"ASYNC") + return self.execute_command("FLUSHALL", *args, **kwargs) + + def flushdb(self, asynchronous: bool = False, **kwargs) -> ResponseT: + """ + Delete all keys in the current database. + + ``asynchronous`` indicates whether the operation is + executed asynchronously by the server. + + For more information see https://redis.io/commands/flushdb + """ + args = [] + if asynchronous: + args.append(b"ASYNC") + return self.execute_command("FLUSHDB", *args, **kwargs) + + def sync(self) -> ResponseT: + """ + Initiates a replication stream from the master. + + For more information see https://redis.io/commands/sync + """ + from redis.client import NEVER_DECODE + + options = {} + options[NEVER_DECODE] = [] + return self.execute_command("SYNC", **options) + + def psync(self, replicationid: str, offset: int): + """ + Initiates a replication stream from the master. + Newer version for `sync`. + + For more information see https://redis.io/commands/sync + """ + from redis.client import NEVER_DECODE + + options = {} + options[NEVER_DECODE] = [] + return self.execute_command("PSYNC", replicationid, offset, **options) + + def swapdb(self, first: int, second: int, **kwargs) -> ResponseT: + """ + Swap two databases + + For more information see https://redis.io/commands/swapdb + """ + return self.execute_command("SWAPDB", first, second, **kwargs) + + def select(self, index: int, **kwargs) -> ResponseT: + """Select the Redis logical database at index. + + See: https://redis.io/commands/select + """ + return self.execute_command("SELECT", index, **kwargs) + + def info( + self, section: Union[str, None] = None, *args: List[str], **kwargs + ) -> ResponseT: + """ + Returns a dictionary containing information about the Redis server + + The ``section`` option can be used to select a specific section + of information + + The section option is not supported by older versions of Redis Server, + and will generate ResponseError + + For more information see https://redis.io/commands/info + """ + if section is None: + return self.execute_command("INFO", **kwargs) + else: + return self.execute_command("INFO", section, *args, **kwargs) + + def lastsave(self, **kwargs) -> ResponseT: + """ + Return a Python datetime object representing the last time the + Redis database was saved to disk + + For more information see https://redis.io/commands/lastsave + """ + return self.execute_command("LASTSAVE", **kwargs) + + def latency_doctor(self): + """Raise a NotImplementedError, as the client will not support LATENCY DOCTOR. + This funcion is best used within the redis-cli. + + For more information see https://redis.io/commands/latency-doctor + """ + raise NotImplementedError( + """ + LATENCY DOCTOR is intentionally not implemented in the client. + + For more information see https://redis.io/commands/latency-doctor + """ + ) + + def latency_graph(self): + """Raise a NotImplementedError, as the client will not support LATENCY GRAPH. + This funcion is best used within the redis-cli. + + For more information see https://redis.io/commands/latency-graph. + """ + raise NotImplementedError( + """ + LATENCY GRAPH is intentionally not implemented in the client. + + For more information see https://redis.io/commands/latency-graph + """ + ) + + def lolwut(self, *version_numbers: Union[str, float], **kwargs) -> ResponseT: + """ + Get the Redis version and a piece of generative computer art + + See: https://redis.io/commands/lolwut + """ + if version_numbers: + return self.execute_command("LOLWUT VERSION", *version_numbers, **kwargs) + else: + return self.execute_command("LOLWUT", **kwargs) + + def reset(self) -> ResponseT: + """Perform a full reset on the connection's server side contenxt. + + See: https://redis.io/commands/reset + """ + return self.execute_command("RESET") + + def migrate( + self, + host: str, + port: int, + keys: KeysT, + destination_db: int, + timeout: int, + copy: bool = False, + replace: bool = False, + auth: Union[str, None] = None, + **kwargs, + ) -> ResponseT: + """ + Migrate 1 or more keys from the current Redis server to a different + server specified by the ``host``, ``port`` and ``destination_db``. + + The ``timeout``, specified in milliseconds, indicates the maximum + time the connection between the two servers can be idle before the + command is interrupted. + + If ``copy`` is True, the specified ``keys`` are NOT deleted from + the source server. + + If ``replace`` is True, this operation will overwrite the keys + on the destination server if they exist. + + If ``auth`` is specified, authenticate to the destination server with + the password provided. + + For more information see https://redis.io/commands/migrate + """ + keys = list_or_args(keys, []) + if not keys: + raise DataError("MIGRATE requires at least one key") + pieces = [] + if copy: + pieces.append(b"COPY") + if replace: + pieces.append(b"REPLACE") + if auth: + pieces.append(b"AUTH") + pieces.append(auth) + pieces.append(b"KEYS") + pieces.extend(keys) + return self.execute_command( + "MIGRATE", host, port, "", destination_db, timeout, *pieces, **kwargs + ) + + def object(self, infotype: str, key: KeyT, **kwargs) -> ResponseT: + """ + Return the encoding, idletime, or refcount about the key + """ + return self.execute_command( + "OBJECT", infotype, key, infotype=infotype, **kwargs + ) + + def memory_doctor(self, **kwargs) -> None: + raise NotImplementedError( + """ + MEMORY DOCTOR is intentionally not implemented in the client. + + For more information see https://redis.io/commands/memory-doctor + """ + ) + + def memory_help(self, **kwargs) -> None: + raise NotImplementedError( + """ + MEMORY HELP is intentionally not implemented in the client. + + For more information see https://redis.io/commands/memory-help + """ + ) + + def memory_stats(self, **kwargs) -> ResponseT: + """ + Return a dictionary of memory stats + + For more information see https://redis.io/commands/memory-stats + """ + return self.execute_command("MEMORY STATS", **kwargs) + + def memory_malloc_stats(self, **kwargs) -> ResponseT: + """ + Return an internal statistics report from the memory allocator. + + See: https://redis.io/commands/memory-malloc-stats + """ + return self.execute_command("MEMORY MALLOC-STATS", **kwargs) + + def memory_usage( + self, key: KeyT, samples: Union[int, None] = None, **kwargs + ) -> ResponseT: + """ + Return the total memory usage for key, its value and associated + administrative overheads. + + For nested data structures, ``samples`` is the number of elements to + sample. If left unspecified, the server's default is 5. Use 0 to sample + all elements. + + For more information see https://redis.io/commands/memory-usage + """ + args = [] + if isinstance(samples, int): + args.extend([b"SAMPLES", samples]) + return self.execute_command("MEMORY USAGE", key, *args, **kwargs) + + def memory_purge(self, **kwargs) -> ResponseT: + """ + Attempts to purge dirty pages for reclamation by allocator + + For more information see https://redis.io/commands/memory-purge + """ + return self.execute_command("MEMORY PURGE", **kwargs) + + def latency_histogram(self, *args): + """ + This function throws a NotImplementedError since it is intentionally + not supported. + """ + raise NotImplementedError( + "LATENCY HISTOGRAM is intentionally not implemented in the client." + ) + + def latency_history(self, event: str) -> ResponseT: + """ + Returns the raw data of the ``event``'s latency spikes time series. + + For more information see https://redis.io/commands/latency-history + """ + return self.execute_command("LATENCY HISTORY", event) + + def latency_latest(self) -> ResponseT: + """ + Reports the latest latency events logged. + + For more information see https://redis.io/commands/latency-latest + """ + return self.execute_command("LATENCY LATEST") + + def latency_reset(self, *events: str) -> ResponseT: + """ + Resets the latency spikes time series of all, or only some, events. + + For more information see https://redis.io/commands/latency-reset + """ + return self.execute_command("LATENCY RESET", *events) + + def ping(self, **kwargs) -> ResponseT: + """ + Ping the Redis server + + For more information see https://redis.io/commands/ping + """ + return self.execute_command("PING", **kwargs) + + def quit(self, **kwargs) -> ResponseT: + """ + Ask the server to close the connection. + + For more information see https://redis.io/commands/quit + """ + return self.execute_command("QUIT", **kwargs) + + def replicaof(self, *args, **kwargs) -> ResponseT: + """ + Update the replication settings of a redis replica, on the fly. + + Examples of valid arguments include: + + NO ONE (set no replication) + host port (set to the host and port of a redis server) + + For more information see https://redis.io/commands/replicaof + """ + return self.execute_command("REPLICAOF", *args, **kwargs) + + def save(self, **kwargs) -> ResponseT: + """ + Tell the Redis server to save its data to disk, + blocking until the save is complete + + For more information see https://redis.io/commands/save + """ + return self.execute_command("SAVE", **kwargs) + + def shutdown( + self, + save: bool = False, + nosave: bool = False, + now: bool = False, + force: bool = False, + abort: bool = False, + **kwargs, + ) -> None: + """Shutdown the Redis server. If Redis has persistence configured, + data will be flushed before shutdown. + It is possible to specify modifiers to alter the behavior of the command: + ``save`` will force a DB saving operation even if no save points are configured. + ``nosave`` will prevent a DB saving operation even if one or more save points + are configured. + ``now`` skips waiting for lagging replicas, i.e. it bypasses the first step in + the shutdown sequence. + ``force`` ignores any errors that would normally prevent the server from exiting + ``abort`` cancels an ongoing shutdown and cannot be combined with other flags. + + For more information see https://redis.io/commands/shutdown + """ + if save and nosave: + raise DataError("SHUTDOWN save and nosave cannot both be set") + args = ["SHUTDOWN"] + if save: + args.append("SAVE") + if nosave: + args.append("NOSAVE") + if now: + args.append("NOW") + if force: + args.append("FORCE") + if abort: + args.append("ABORT") + try: + self.execute_command(*args, **kwargs) + except ConnectionError: + # a ConnectionError here is expected + return + raise RedisError("SHUTDOWN seems to have failed.") + + def slaveof( + self, host: Union[str, None] = None, port: Union[int, None] = None, **kwargs + ) -> ResponseT: + """ + Set the server to be a replicated slave of the instance identified + by the ``host`` and ``port``. If called without arguments, the + instance is promoted to a master instead. + + For more information see https://redis.io/commands/slaveof + """ + if host is None and port is None: + return self.execute_command("SLAVEOF", b"NO", b"ONE", **kwargs) + return self.execute_command("SLAVEOF", host, port, **kwargs) + + def slowlog_get(self, num: Union[int, None] = None, **kwargs) -> ResponseT: + """ + Get the entries from the slowlog. If ``num`` is specified, get the + most recent ``num`` items. + + For more information see https://redis.io/commands/slowlog-get + """ + from redis.client import NEVER_DECODE + + args = ["SLOWLOG GET"] + if num is not None: + args.append(num) + decode_responses = self.get_connection_kwargs().get("decode_responses", False) + if decode_responses is True: + kwargs[NEVER_DECODE] = [] + return self.execute_command(*args, **kwargs) + + def slowlog_len(self, **kwargs) -> ResponseT: + """ + Get the number of items in the slowlog + + For more information see https://redis.io/commands/slowlog-len + """ + return self.execute_command("SLOWLOG LEN", **kwargs) + + def slowlog_reset(self, **kwargs) -> ResponseT: + """ + Remove all items in the slowlog + + For more information see https://redis.io/commands/slowlog-reset + """ + return self.execute_command("SLOWLOG RESET", **kwargs) + + def time(self, **kwargs) -> ResponseT: + """ + Returns the server time as a 2-item tuple of ints: + (seconds since epoch, microseconds into this second). + + For more information see https://redis.io/commands/time + """ + return self.execute_command("TIME", **kwargs) + + def wait(self, num_replicas: int, timeout: int, **kwargs) -> ResponseT: + """ + Redis synchronous replication + That returns the number of replicas that processed the query when + we finally have at least ``num_replicas``, or when the ``timeout`` was + reached. + + For more information see https://redis.io/commands/wait + """ + return self.execute_command("WAIT", num_replicas, timeout, **kwargs) + + def waitaof( + self, num_local: int, num_replicas: int, timeout: int, **kwargs + ) -> ResponseT: + """ + This command blocks the current client until all previous write + commands by that client are acknowledged as having been fsynced + to the AOF of the local Redis and/or at least the specified number + of replicas. + + For more information see https://redis.io/commands/waitaof + """ + return self.execute_command( + "WAITAOF", num_local, num_replicas, timeout, **kwargs + ) + + def hello(self): + """ + This function throws a NotImplementedError since it is intentionally + not supported. + """ + raise NotImplementedError( + "HELLO is intentionally not implemented in the client." + ) + + def failover(self): + """ + This function throws a NotImplementedError since it is intentionally + not supported. + """ + raise NotImplementedError( + "FAILOVER is intentionally not implemented in the client." + ) + + +AsyncManagementCommands = ManagementCommands + + +class AsyncManagementCommands(ManagementCommands): + async def command_info(self, **kwargs) -> None: + return super().command_info(**kwargs) + + async def debug_segfault(self, **kwargs) -> None: + return super().debug_segfault(**kwargs) + + async def memory_doctor(self, **kwargs) -> None: + return super().memory_doctor(**kwargs) + + async def memory_help(self, **kwargs) -> None: + return super().memory_help(**kwargs) + + async def shutdown( + self, + save: bool = False, + nosave: bool = False, + now: bool = False, + force: bool = False, + abort: bool = False, + **kwargs, + ) -> None: + """Shutdown the Redis server. If Redis has persistence configured, + data will be flushed before shutdown. If the "save" option is set, + a data flush will be attempted even if there is no persistence + configured. If the "nosave" option is set, no data flush will be + attempted. The "save" and "nosave" options cannot both be set. + + For more information see https://redis.io/commands/shutdown + """ + if save and nosave: + raise DataError("SHUTDOWN save and nosave cannot both be set") + args = ["SHUTDOWN"] + if save: + args.append("SAVE") + if nosave: + args.append("NOSAVE") + if now: + args.append("NOW") + if force: + args.append("FORCE") + if abort: + args.append("ABORT") + try: + await self.execute_command(*args, **kwargs) + except ConnectionError: + # a ConnectionError here is expected + return + raise RedisError("SHUTDOWN seems to have failed.") + + +class BitFieldOperation: + """ + Command builder for BITFIELD commands. + """ + + def __init__( + self, + client: Union["Redis", "AsyncRedis"], + key: str, + default_overflow: Union[str, None] = None, + ): + self.client = client + self.key = key + self._default_overflow = default_overflow + # for typing purposes, run the following in constructor and in reset() + self.operations: list[tuple[EncodableT, ...]] = [] + self._last_overflow = "WRAP" + self.reset() + + def reset(self): + """ + Reset the state of the instance to when it was constructed + """ + self.operations = [] + self._last_overflow = "WRAP" + self.overflow(self._default_overflow or self._last_overflow) + + def overflow(self, overflow: str): + """ + Update the overflow algorithm of successive INCRBY operations + :param overflow: Overflow algorithm, one of WRAP, SAT, FAIL. See the + Redis docs for descriptions of these algorithmsself. + :returns: a :py:class:`BitFieldOperation` instance. + """ + overflow = overflow.upper() + if overflow != self._last_overflow: + self._last_overflow = overflow + self.operations.append(("OVERFLOW", overflow)) + return self + + def incrby( + self, + fmt: str, + offset: BitfieldOffsetT, + increment: int, + overflow: Union[str, None] = None, + ): + """ + Increment a bitfield by a given amount. + :param fmt: format-string for the bitfield being updated, e.g. 'u8' + for an unsigned 8-bit integer. + :param offset: offset (in number of bits). If prefixed with a + '#', this is an offset multiplier, e.g. given the arguments + fmt='u8', offset='#2', the offset will be 16. + :param int increment: value to increment the bitfield by. + :param str overflow: overflow algorithm. Defaults to WRAP, but other + acceptable values are SAT and FAIL. See the Redis docs for + descriptions of these algorithms. + :returns: a :py:class:`BitFieldOperation` instance. + """ + if overflow is not None: + self.overflow(overflow) + + self.operations.append(("INCRBY", fmt, offset, increment)) + return self + + def get(self, fmt: str, offset: BitfieldOffsetT): + """ + Get the value of a given bitfield. + :param fmt: format-string for the bitfield being read, e.g. 'u8' for + an unsigned 8-bit integer. + :param offset: offset (in number of bits). If prefixed with a + '#', this is an offset multiplier, e.g. given the arguments + fmt='u8', offset='#2', the offset will be 16. + :returns: a :py:class:`BitFieldOperation` instance. + """ + self.operations.append(("GET", fmt, offset)) + return self + + def set(self, fmt: str, offset: BitfieldOffsetT, value: int): + """ + Set the value of a given bitfield. + :param fmt: format-string for the bitfield being read, e.g. 'u8' for + an unsigned 8-bit integer. + :param offset: offset (in number of bits). If prefixed with a + '#', this is an offset multiplier, e.g. given the arguments + fmt='u8', offset='#2', the offset will be 16. + :param int value: value to set at the given position. + :returns: a :py:class:`BitFieldOperation` instance. + """ + self.operations.append(("SET", fmt, offset, value)) + return self + + @property + def command(self): + cmd = ["BITFIELD", self.key] + for ops in self.operations: + cmd.extend(ops) + return cmd + + def execute(self) -> ResponseT: + """ + Execute the operation(s) in a single BITFIELD command. The return value + is a list of values corresponding to each operation. If the client + used to create this instance was a pipeline, the list of values + will be present within the pipeline's execute. + """ + command = self.command + self.reset() + return self.client.execute_command(*command) + + +class BasicKeyCommands(CommandsProtocol): + """ + Redis basic key-based commands + """ + + def append(self, key: KeyT, value: EncodableT) -> ResponseT: + """ + Appends the string ``value`` to the value at ``key``. If ``key`` + doesn't already exist, create it with a value of ``value``. + Returns the new length of the value at ``key``. + + For more information see https://redis.io/commands/append + """ + return self.execute_command("APPEND", key, value) + + def bitcount( + self, + key: KeyT, + start: Union[int, None] = None, + end: Union[int, None] = None, + mode: Optional[str] = None, + ) -> ResponseT: + """ + Returns the count of set bits in the value of ``key``. Optional + ``start`` and ``end`` parameters indicate which bytes to consider + + For more information see https://redis.io/commands/bitcount + """ + params = [key] + if start is not None and end is not None: + params.append(start) + params.append(end) + elif (start is not None and end is None) or (end is not None and start is None): + raise DataError("Both start and end must be specified") + if mode is not None: + params.append(mode) + return self.execute_command("BITCOUNT", *params) + + def bitfield( + self: Union["Redis", "AsyncRedis"], + key: KeyT, + default_overflow: Union[str, None] = None, + ) -> BitFieldOperation: + """ + Return a BitFieldOperation instance to conveniently construct one or + more bitfield operations on ``key``. + + For more information see https://redis.io/commands/bitfield + """ + return BitFieldOperation(self, key, default_overflow=default_overflow) + + def bitfield_ro( + self: Union["Redis", "AsyncRedis"], + key: KeyT, + encoding: str, + offset: BitfieldOffsetT, + items: Optional[list] = None, + ) -> ResponseT: + """ + Return an array of the specified bitfield values + where the first value is found using ``encoding`` and ``offset`` + parameters and remaining values are result of corresponding + encoding/offset pairs in optional list ``items`` + Read-only variant of the BITFIELD command. + + For more information see https://redis.io/commands/bitfield_ro + """ + params = [key, "GET", encoding, offset] + + items = items or [] + for encoding, offset in items: + params.extend(["GET", encoding, offset]) + return self.execute_command("BITFIELD_RO", *params) + + def bitop(self, operation: str, dest: KeyT, *keys: KeyT) -> ResponseT: + """ + Perform a bitwise operation using ``operation`` between ``keys`` and + store the result in ``dest``. + + For more information see https://redis.io/commands/bitop + """ + return self.execute_command("BITOP", operation, dest, *keys) + + def bitpos( + self, + key: KeyT, + bit: int, + start: Union[int, None] = None, + end: Union[int, None] = None, + mode: Optional[str] = None, + ) -> ResponseT: + """ + Return the position of the first bit set to 1 or 0 in a string. + ``start`` and ``end`` defines search range. The range is interpreted + as a range of bytes and not a range of bits, so start=0 and end=2 + means to look at the first three bytes. + + For more information see https://redis.io/commands/bitpos + """ + if bit not in (0, 1): + raise DataError("bit must be 0 or 1") + params = [key, bit] + + start is not None and params.append(start) + + if start is not None and end is not None: + params.append(end) + elif start is None and end is not None: + raise DataError("start argument is not set, when end is specified") + + if mode is not None: + params.append(mode) + return self.execute_command("BITPOS", *params) + + def copy( + self, + source: str, + destination: str, + destination_db: Union[str, None] = None, + replace: bool = False, + ) -> ResponseT: + """ + Copy the value stored in the ``source`` key to the ``destination`` key. + + ``destination_db`` an alternative destination database. By default, + the ``destination`` key is created in the source Redis database. + + ``replace`` whether the ``destination`` key should be removed before + copying the value to it. By default, the value is not copied if + the ``destination`` key already exists. + + For more information see https://redis.io/commands/copy + """ + params = [source, destination] + if destination_db is not None: + params.extend(["DB", destination_db]) + if replace: + params.append("REPLACE") + return self.execute_command("COPY", *params) + + def decrby(self, name: KeyT, amount: int = 1) -> ResponseT: + """ + Decrements the value of ``key`` by ``amount``. If no key exists, + the value will be initialized as 0 - ``amount`` + + For more information see https://redis.io/commands/decrby + """ + return self.execute_command("DECRBY", name, amount) + + decr = decrby + + def delete(self, *names: KeyT) -> ResponseT: + """ + Delete one or more keys specified by ``names`` + """ + return self.execute_command("DEL", *names) + + def __delitem__(self, name: KeyT): + self.delete(name) + + def dump(self, name: KeyT) -> ResponseT: + """ + Return a serialized version of the value stored at the specified key. + If key does not exist a nil bulk reply is returned. + + For more information see https://redis.io/commands/dump + """ + from redis.client import NEVER_DECODE + + options = {} + options[NEVER_DECODE] = [] + return self.execute_command("DUMP", name, **options) + + def exists(self, *names: KeyT) -> ResponseT: + """ + Returns the number of ``names`` that exist + + For more information see https://redis.io/commands/exists + """ + return self.execute_command("EXISTS", *names) + + __contains__ = exists + + def expire( + self, + name: KeyT, + time: ExpiryT, + nx: bool = False, + xx: bool = False, + gt: bool = False, + lt: bool = False, + ) -> ResponseT: + """ + Set an expire flag on key ``name`` for ``time`` seconds with given + ``option``. ``time`` can be represented by an integer or a Python timedelta + object. + + Valid options are: + NX -> Set expiry only when the key has no expiry + XX -> Set expiry only when the key has an existing expiry + GT -> Set expiry only when the new expiry is greater than current one + LT -> Set expiry only when the new expiry is less than current one + + For more information see https://redis.io/commands/expire + """ + if isinstance(time, datetime.timedelta): + time = int(time.total_seconds()) + + exp_option = list() + if nx: + exp_option.append("NX") + if xx: + exp_option.append("XX") + if gt: + exp_option.append("GT") + if lt: + exp_option.append("LT") + + return self.execute_command("EXPIRE", name, time, *exp_option) + + def expireat( + self, + name: KeyT, + when: AbsExpiryT, + nx: bool = False, + xx: bool = False, + gt: bool = False, + lt: bool = False, + ) -> ResponseT: + """ + Set an expire flag on key ``name`` with given ``option``. ``when`` + can be represented as an integer indicating unix time or a Python + datetime object. + + Valid options are: + -> NX -- Set expiry only when the key has no expiry + -> XX -- Set expiry only when the key has an existing expiry + -> GT -- Set expiry only when the new expiry is greater than current one + -> LT -- Set expiry only when the new expiry is less than current one + + For more information see https://redis.io/commands/expireat + """ + if isinstance(when, datetime.datetime): + when = int(when.timestamp()) + + exp_option = list() + if nx: + exp_option.append("NX") + if xx: + exp_option.append("XX") + if gt: + exp_option.append("GT") + if lt: + exp_option.append("LT") + + return self.execute_command("EXPIREAT", name, when, *exp_option) + + def expiretime(self, key: str) -> int: + """ + Returns the absolute Unix timestamp (since January 1, 1970) in seconds + at which the given key will expire. + + For more information see https://redis.io/commands/expiretime + """ + return self.execute_command("EXPIRETIME", key) + + def get(self, name: KeyT) -> ResponseT: + """ + Return the value at key ``name``, or None if the key doesn't exist + + For more information see https://redis.io/commands/get + """ + return self.execute_command("GET", name) + + def getdel(self, name: KeyT) -> ResponseT: + """ + Get the value at key ``name`` and delete the key. This command + is similar to GET, except for the fact that it also deletes + the key on success (if and only if the key's value type + is a string). + + For more information see https://redis.io/commands/getdel + """ + return self.execute_command("GETDEL", name) + + def getex( + self, + name: KeyT, + ex: Union[ExpiryT, None] = None, + px: Union[ExpiryT, None] = None, + exat: Union[AbsExpiryT, None] = None, + pxat: Union[AbsExpiryT, None] = None, + persist: bool = False, + ) -> ResponseT: + """ + Get the value of key and optionally set its expiration. + GETEX is similar to GET, but is a write command with + additional options. All time parameters can be given as + datetime.timedelta or integers. + + ``ex`` sets an expire flag on key ``name`` for ``ex`` seconds. + + ``px`` sets an expire flag on key ``name`` for ``px`` milliseconds. + + ``exat`` sets an expire flag on key ``name`` for ``ex`` seconds, + specified in unix time. + + ``pxat`` sets an expire flag on key ``name`` for ``ex`` milliseconds, + specified in unix time. + + ``persist`` remove the time to live associated with ``name``. + + For more information see https://redis.io/commands/getex + """ + + opset = {ex, px, exat, pxat} + if len(opset) > 2 or len(opset) > 1 and persist: + raise DataError( + "``ex``, ``px``, ``exat``, ``pxat``, " + "and ``persist`` are mutually exclusive." + ) + + pieces: list[EncodableT] = [] + # similar to set command + if ex is not None: + pieces.append("EX") + if isinstance(ex, datetime.timedelta): + ex = int(ex.total_seconds()) + pieces.append(ex) + if px is not None: + pieces.append("PX") + if isinstance(px, datetime.timedelta): + px = int(px.total_seconds() * 1000) + pieces.append(px) + # similar to pexpireat command + if exat is not None: + pieces.append("EXAT") + if isinstance(exat, datetime.datetime): + exat = int(exat.timestamp()) + pieces.append(exat) + if pxat is not None: + pieces.append("PXAT") + if isinstance(pxat, datetime.datetime): + pxat = int(pxat.timestamp() * 1000) + pieces.append(pxat) + if persist: + pieces.append("PERSIST") + + return self.execute_command("GETEX", name, *pieces) + + def __getitem__(self, name: KeyT): + """ + Return the value at key ``name``, raises a KeyError if the key + doesn't exist. + """ + value = self.get(name) + if value is not None: + return value + raise KeyError(name) + + def getbit(self, name: KeyT, offset: int) -> ResponseT: + """ + Returns an integer indicating the value of ``offset`` in ``name`` + + For more information see https://redis.io/commands/getbit + """ + return self.execute_command("GETBIT", name, offset) + + def getrange(self, key: KeyT, start: int, end: int) -> ResponseT: + """ + Returns the substring of the string value stored at ``key``, + determined by the offsets ``start`` and ``end`` (both are inclusive) + + For more information see https://redis.io/commands/getrange + """ + return self.execute_command("GETRANGE", key, start, end) + + def getset(self, name: KeyT, value: EncodableT) -> ResponseT: + """ + Sets the value at key ``name`` to ``value`` + and returns the old value at key ``name`` atomically. + + As per Redis 6.2, GETSET is considered deprecated. + Please use SET with GET parameter in new code. + + For more information see https://redis.io/commands/getset + """ + return self.execute_command("GETSET", name, value) + + def incrby(self, name: KeyT, amount: int = 1) -> ResponseT: + """ + Increments the value of ``key`` by ``amount``. If no key exists, + the value will be initialized as ``amount`` + + For more information see https://redis.io/commands/incrby + """ + return self.execute_command("INCRBY", name, amount) + + incr = incrby + + def incrbyfloat(self, name: KeyT, amount: float = 1.0) -> ResponseT: + """ + Increments the value at key ``name`` by floating ``amount``. + If no key exists, the value will be initialized as ``amount`` + + For more information see https://redis.io/commands/incrbyfloat + """ + return self.execute_command("INCRBYFLOAT", name, amount) + + def keys(self, pattern: PatternT = "*", **kwargs) -> ResponseT: + """ + Returns a list of keys matching ``pattern`` + + For more information see https://redis.io/commands/keys + """ + return self.execute_command("KEYS", pattern, **kwargs) + + def lmove( + self, first_list: str, second_list: str, src: str = "LEFT", dest: str = "RIGHT" + ) -> ResponseT: + """ + Atomically returns and removes the first/last element of a list, + pushing it as the first/last element on the destination list. + Returns the element being popped and pushed. + + For more information see https://redis.io/commands/lmove + """ + params = [first_list, second_list, src, dest] + return self.execute_command("LMOVE", *params) + + def blmove( + self, + first_list: str, + second_list: str, + timeout: int, + src: str = "LEFT", + dest: str = "RIGHT", + ) -> ResponseT: + """ + Blocking version of lmove. + + For more information see https://redis.io/commands/blmove + """ + params = [first_list, second_list, src, dest, timeout] + return self.execute_command("BLMOVE", *params) + + def mget(self, keys: KeysT, *args: EncodableT) -> ResponseT: + """ + Returns a list of values ordered identically to ``keys`` + + For more information see https://redis.io/commands/mget + """ + from redis.client import EMPTY_RESPONSE + + args = list_or_args(keys, args) + options = {} + if not args: + options[EMPTY_RESPONSE] = [] + return self.execute_command("MGET", *args, **options) + + def mset(self, mapping: Mapping[AnyKeyT, EncodableT]) -> ResponseT: + """ + Sets key/values based on a mapping. Mapping is a dictionary of + key/value pairs. Both keys and values should be strings or types that + can be cast to a string via str(). + + For more information see https://redis.io/commands/mset + """ + items = [] + for pair in mapping.items(): + items.extend(pair) + return self.execute_command("MSET", *items) + + def msetnx(self, mapping: Mapping[AnyKeyT, EncodableT]) -> ResponseT: + """ + Sets key/values based on a mapping if none of the keys are already set. + Mapping is a dictionary of key/value pairs. Both keys and values + should be strings or types that can be cast to a string via str(). + Returns a boolean indicating if the operation was successful. + + For more information see https://redis.io/commands/msetnx + """ + items = [] + for pair in mapping.items(): + items.extend(pair) + return self.execute_command("MSETNX", *items) + + def move(self, name: KeyT, db: int) -> ResponseT: + """ + Moves the key ``name`` to a different Redis database ``db`` + + For more information see https://redis.io/commands/move + """ + return self.execute_command("MOVE", name, db) + + def persist(self, name: KeyT) -> ResponseT: + """ + Removes an expiration on ``name`` + + For more information see https://redis.io/commands/persist + """ + return self.execute_command("PERSIST", name) + + def pexpire( + self, + name: KeyT, + time: ExpiryT, + nx: bool = False, + xx: bool = False, + gt: bool = False, + lt: bool = False, + ) -> ResponseT: + """ + Set an expire flag on key ``name`` for ``time`` milliseconds + with given ``option``. ``time`` can be represented by an + integer or a Python timedelta object. + + Valid options are: + NX -> Set expiry only when the key has no expiry + XX -> Set expiry only when the key has an existing expiry + GT -> Set expiry only when the new expiry is greater than current one + LT -> Set expiry only when the new expiry is less than current one + + For more information see https://redis.io/commands/pexpire + """ + if isinstance(time, datetime.timedelta): + time = int(time.total_seconds() * 1000) + + exp_option = list() + if nx: + exp_option.append("NX") + if xx: + exp_option.append("XX") + if gt: + exp_option.append("GT") + if lt: + exp_option.append("LT") + return self.execute_command("PEXPIRE", name, time, *exp_option) + + def pexpireat( + self, + name: KeyT, + when: AbsExpiryT, + nx: bool = False, + xx: bool = False, + gt: bool = False, + lt: bool = False, + ) -> ResponseT: + """ + Set an expire flag on key ``name`` with given ``option``. ``when`` + can be represented as an integer representing unix time in + milliseconds (unix time * 1000) or a Python datetime object. + + Valid options are: + NX -> Set expiry only when the key has no expiry + XX -> Set expiry only when the key has an existing expiry + GT -> Set expiry only when the new expiry is greater than current one + LT -> Set expiry only when the new expiry is less than current one + + For more information see https://redis.io/commands/pexpireat + """ + if isinstance(when, datetime.datetime): + when = int(when.timestamp() * 1000) + exp_option = list() + if nx: + exp_option.append("NX") + if xx: + exp_option.append("XX") + if gt: + exp_option.append("GT") + if lt: + exp_option.append("LT") + return self.execute_command("PEXPIREAT", name, when, *exp_option) + + def pexpiretime(self, key: str) -> int: + """ + Returns the absolute Unix timestamp (since January 1, 1970) in milliseconds + at which the given key will expire. + + For more information see https://redis.io/commands/pexpiretime + """ + return self.execute_command("PEXPIRETIME", key) + + def psetex(self, name: KeyT, time_ms: ExpiryT, value: EncodableT): + """ + Set the value of key ``name`` to ``value`` that expires in ``time_ms`` + milliseconds. ``time_ms`` can be represented by an integer or a Python + timedelta object + + For more information see https://redis.io/commands/psetex + """ + if isinstance(time_ms, datetime.timedelta): + time_ms = int(time_ms.total_seconds() * 1000) + return self.execute_command("PSETEX", name, time_ms, value) + + def pttl(self, name: KeyT) -> ResponseT: + """ + Returns the number of milliseconds until the key ``name`` will expire + + For more information see https://redis.io/commands/pttl + """ + return self.execute_command("PTTL", name) + + def hrandfield( + self, key: str, count: int = None, withvalues: bool = False + ) -> ResponseT: + """ + Return a random field from the hash value stored at key. + + count: if the argument is positive, return an array of distinct fields. + If called with a negative count, the behavior changes and the command + is allowed to return the same field multiple times. In this case, + the number of returned fields is the absolute value of the + specified count. + withvalues: The optional WITHVALUES modifier changes the reply so it + includes the respective values of the randomly selected hash fields. + + For more information see https://redis.io/commands/hrandfield + """ + params = [] + if count is not None: + params.append(count) + if withvalues: + params.append("WITHVALUES") + + return self.execute_command("HRANDFIELD", key, *params) + + def randomkey(self, **kwargs) -> ResponseT: + """ + Returns the name of a random key + + For more information see https://redis.io/commands/randomkey + """ + return self.execute_command("RANDOMKEY", **kwargs) + + def rename(self, src: KeyT, dst: KeyT) -> ResponseT: + """ + Rename key ``src`` to ``dst`` + + For more information see https://redis.io/commands/rename + """ + return self.execute_command("RENAME", src, dst) + + def renamenx(self, src: KeyT, dst: KeyT): + """ + Rename key ``src`` to ``dst`` if ``dst`` doesn't already exist + + For more information see https://redis.io/commands/renamenx + """ + return self.execute_command("RENAMENX", src, dst) + + def restore( + self, + name: KeyT, + ttl: float, + value: EncodableT, + replace: bool = False, + absttl: bool = False, + idletime: Union[int, None] = None, + frequency: Union[int, None] = None, + ) -> ResponseT: + """ + Create a key using the provided serialized value, previously obtained + using DUMP. + + ``replace`` allows an existing key on ``name`` to be overridden. If + it's not specified an error is raised on collision. + + ``absttl`` if True, specified ``ttl`` should represent an absolute Unix + timestamp in milliseconds in which the key will expire. (Redis 5.0 or + greater). + + ``idletime`` Used for eviction, this is the number of seconds the + key must be idle, prior to execution. + + ``frequency`` Used for eviction, this is the frequency counter of + the object stored at the key, prior to execution. + + For more information see https://redis.io/commands/restore + """ + params = [name, ttl, value] + if replace: + params.append("REPLACE") + if absttl: + params.append("ABSTTL") + if idletime is not None: + params.append("IDLETIME") + try: + params.append(int(idletime)) + except ValueError: + raise DataError("idletimemust be an integer") + + if frequency is not None: + params.append("FREQ") + try: + params.append(int(frequency)) + except ValueError: + raise DataError("frequency must be an integer") + + return self.execute_command("RESTORE", *params) + + def set( + self, + name: KeyT, + value: EncodableT, + ex: Union[ExpiryT, None] = None, + px: Union[ExpiryT, None] = None, + nx: bool = False, + xx: bool = False, + keepttl: bool = False, + get: bool = False, + exat: Union[AbsExpiryT, None] = None, + pxat: Union[AbsExpiryT, None] = None, + ) -> ResponseT: + """ + Set the value at key ``name`` to ``value`` + + ``ex`` sets an expire flag on key ``name`` for ``ex`` seconds. + + ``px`` sets an expire flag on key ``name`` for ``px`` milliseconds. + + ``nx`` if set to True, set the value at key ``name`` to ``value`` only + if it does not exist. + + ``xx`` if set to True, set the value at key ``name`` to ``value`` only + if it already exists. + + ``keepttl`` if True, retain the time to live associated with the key. + (Available since Redis 6.0) + + ``get`` if True, set the value at key ``name`` to ``value`` and return + the old value stored at key, or None if the key did not exist. + (Available since Redis 6.2) + + ``exat`` sets an expire flag on key ``name`` for ``ex`` seconds, + specified in unix time. + + ``pxat`` sets an expire flag on key ``name`` for ``ex`` milliseconds, + specified in unix time. + + For more information see https://redis.io/commands/set + """ + pieces: list[EncodableT] = [name, value] + options = {} + if ex is not None: + pieces.append("EX") + if isinstance(ex, datetime.timedelta): + pieces.append(int(ex.total_seconds())) + elif isinstance(ex, int): + pieces.append(ex) + elif isinstance(ex, str) and ex.isdigit(): + pieces.append(int(ex)) + else: + raise DataError("ex must be datetime.timedelta or int") + if px is not None: + pieces.append("PX") + if isinstance(px, datetime.timedelta): + pieces.append(int(px.total_seconds() * 1000)) + elif isinstance(px, int): + pieces.append(px) + else: + raise DataError("px must be datetime.timedelta or int") + if exat is not None: + pieces.append("EXAT") + if isinstance(exat, datetime.datetime): + exat = int(exat.timestamp()) + pieces.append(exat) + if pxat is not None: + pieces.append("PXAT") + if isinstance(pxat, datetime.datetime): + pxat = int(pxat.timestamp() * 1000) + pieces.append(pxat) + if keepttl: + pieces.append("KEEPTTL") + + if nx: + pieces.append("NX") + if xx: + pieces.append("XX") + + if get: + pieces.append("GET") + options["get"] = True + + return self.execute_command("SET", *pieces, **options) + + def __setitem__(self, name: KeyT, value: EncodableT): + self.set(name, value) + + def setbit(self, name: KeyT, offset: int, value: int) -> ResponseT: + """ + Flag the ``offset`` in ``name`` as ``value``. Returns an integer + indicating the previous value of ``offset``. + + For more information see https://redis.io/commands/setbit + """ + value = value and 1 or 0 + return self.execute_command("SETBIT", name, offset, value) + + def setex(self, name: KeyT, time: ExpiryT, value: EncodableT) -> ResponseT: + """ + Set the value of key ``name`` to ``value`` that expires in ``time`` + seconds. ``time`` can be represented by an integer or a Python + timedelta object. + + For more information see https://redis.io/commands/setex + """ + if isinstance(time, datetime.timedelta): + time = int(time.total_seconds()) + return self.execute_command("SETEX", name, time, value) + + def setnx(self, name: KeyT, value: EncodableT) -> ResponseT: + """ + Set the value of key ``name`` to ``value`` if key doesn't exist + + For more information see https://redis.io/commands/setnx + """ + return self.execute_command("SETNX", name, value) + + def setrange(self, name: KeyT, offset: int, value: EncodableT) -> ResponseT: + """ + Overwrite bytes in the value of ``name`` starting at ``offset`` with + ``value``. If ``offset`` plus the length of ``value`` exceeds the + length of the original value, the new value will be larger than before. + If ``offset`` exceeds the length of the original value, null bytes + will be used to pad between the end of the previous value and the start + of what's being injected. + + Returns the length of the new string. + + For more information see https://redis.io/commands/setrange + """ + return self.execute_command("SETRANGE", name, offset, value) + + def stralgo( + self, + algo: Literal["LCS"], + value1: KeyT, + value2: KeyT, + specific_argument: Union[Literal["strings"], Literal["keys"]] = "strings", + len: bool = False, + idx: bool = False, + minmatchlen: Union[int, None] = None, + withmatchlen: bool = False, + **kwargs, + ) -> ResponseT: + """ + Implements complex algorithms that operate on strings. + Right now the only algorithm implemented is the LCS algorithm + (longest common substring). However new algorithms could be + implemented in the future. + + ``algo`` Right now must be LCS + ``value1`` and ``value2`` Can be two strings or two keys + ``specific_argument`` Specifying if the arguments to the algorithm + will be keys or strings. strings is the default. + ``len`` Returns just the len of the match. + ``idx`` Returns the match positions in each string. + ``minmatchlen`` Restrict the list of matches to the ones of a given + minimal length. Can be provided only when ``idx`` set to True. + ``withmatchlen`` Returns the matches with the len of the match. + Can be provided only when ``idx`` set to True. + + For more information see https://redis.io/commands/stralgo + """ + # check validity + supported_algo = ["LCS"] + if algo not in supported_algo: + supported_algos_str = ", ".join(supported_algo) + raise DataError(f"The supported algorithms are: {supported_algos_str}") + if specific_argument not in ["keys", "strings"]: + raise DataError("specific_argument can be only keys or strings") + if len and idx: + raise DataError("len and idx cannot be provided together.") + + pieces: list[EncodableT] = [algo, specific_argument.upper(), value1, value2] + if len: + pieces.append(b"LEN") + if idx: + pieces.append(b"IDX") + try: + int(minmatchlen) + pieces.extend([b"MINMATCHLEN", minmatchlen]) + except TypeError: + pass + if withmatchlen: + pieces.append(b"WITHMATCHLEN") + + return self.execute_command( + "STRALGO", + *pieces, + len=len, + idx=idx, + minmatchlen=minmatchlen, + withmatchlen=withmatchlen, + **kwargs, + ) + + def strlen(self, name: KeyT) -> ResponseT: + """ + Return the number of bytes stored in the value of ``name`` + + For more information see https://redis.io/commands/strlen + """ + return self.execute_command("STRLEN", name) + + def substr(self, name: KeyT, start: int, end: int = -1) -> ResponseT: + """ + Return a substring of the string at key ``name``. ``start`` and ``end`` + are 0-based integers specifying the portion of the string to return. + """ + return self.execute_command("SUBSTR", name, start, end) + + def touch(self, *args: KeyT) -> ResponseT: + """ + Alters the last access time of a key(s) ``*args``. A key is ignored + if it does not exist. + + For more information see https://redis.io/commands/touch + """ + return self.execute_command("TOUCH", *args) + + def ttl(self, name: KeyT) -> ResponseT: + """ + Returns the number of seconds until the key ``name`` will expire + + For more information see https://redis.io/commands/ttl + """ + return self.execute_command("TTL", name) + + def type(self, name: KeyT) -> ResponseT: + """ + Returns the type of key ``name`` + + For more information see https://redis.io/commands/type + """ + return self.execute_command("TYPE", name) + + def watch(self, *names: KeyT) -> None: + """ + Watches the values at keys ``names``, or None if the key doesn't exist + + For more information see https://redis.io/commands/watch + """ + warnings.warn(DeprecationWarning("Call WATCH from a Pipeline object")) + + def unwatch(self) -> None: + """ + Unwatches the value at key ``name``, or None of the key doesn't exist + + For more information see https://redis.io/commands/unwatch + """ + warnings.warn(DeprecationWarning("Call UNWATCH from a Pipeline object")) + + def unlink(self, *names: KeyT) -> ResponseT: + """ + Unlink one or more keys specified by ``names`` + + For more information see https://redis.io/commands/unlink + """ + return self.execute_command("UNLINK", *names) + + def lcs( + self, + key1: str, + key2: str, + len: Optional[bool] = False, + idx: Optional[bool] = False, + minmatchlen: Optional[int] = 0, + withmatchlen: Optional[bool] = False, + ) -> Union[str, int, list]: + """ + Find the longest common subsequence between ``key1`` and ``key2``. + If ``len`` is true the length of the match will will be returned. + If ``idx`` is true the match position in each strings will be returned. + ``minmatchlen`` restrict the list of matches to the ones of + the given ``minmatchlen``. + If ``withmatchlen`` the length of the match also will be returned. + For more information see https://redis.io/commands/lcs + """ + pieces = [key1, key2] + if len: + pieces.append("LEN") + if idx: + pieces.append("IDX") + if minmatchlen != 0: + pieces.extend(["MINMATCHLEN", minmatchlen]) + if withmatchlen: + pieces.append("WITHMATCHLEN") + return self.execute_command("LCS", *pieces) + + +class AsyncBasicKeyCommands(BasicKeyCommands): + def __delitem__(self, name: KeyT): + raise TypeError("Async Redis client does not support class deletion") + + def __contains__(self, name: KeyT): + raise TypeError("Async Redis client does not support class inclusion") + + def __getitem__(self, name: KeyT): + raise TypeError("Async Redis client does not support class retrieval") + + def __setitem__(self, name: KeyT, value: EncodableT): + raise TypeError("Async Redis client does not support class assignment") + + async def watch(self, *names: KeyT) -> None: + return super().watch(*names) + + async def unwatch(self) -> None: + return super().unwatch() + + +class ListCommands(CommandsProtocol): + """ + Redis commands for List data type. + see: https://redis.io/topics/data-types#lists + """ + + def blpop( + self, keys: List, timeout: Optional[int] = 0 + ) -> Union[Awaitable[list], list]: + """ + LPOP a value off of the first non-empty list + named in the ``keys`` list. + + If none of the lists in ``keys`` has a value to LPOP, then block + for ``timeout`` seconds, or until a value gets pushed on to one + of the lists. + + If timeout is 0, then block indefinitely. + + For more information see https://redis.io/commands/blpop + """ + if timeout is None: + timeout = 0 + keys = list_or_args(keys, None) + keys.append(timeout) + return self.execute_command("BLPOP", *keys) + + def brpop( + self, keys: List, timeout: Optional[int] = 0 + ) -> Union[Awaitable[list], list]: + """ + RPOP a value off of the first non-empty list + named in the ``keys`` list. + + If none of the lists in ``keys`` has a value to RPOP, then block + for ``timeout`` seconds, or until a value gets pushed on to one + of the lists. + + If timeout is 0, then block indefinitely. + + For more information see https://redis.io/commands/brpop + """ + if timeout is None: + timeout = 0 + keys = list_or_args(keys, None) + keys.append(timeout) + return self.execute_command("BRPOP", *keys) + + def brpoplpush( + self, src: str, dst: str, timeout: Optional[int] = 0 + ) -> Union[Awaitable[Optional[str]], Optional[str]]: + """ + Pop a value off the tail of ``src``, push it on the head of ``dst`` + and then return it. + + This command blocks until a value is in ``src`` or until ``timeout`` + seconds elapse, whichever is first. A ``timeout`` value of 0 blocks + forever. + + For more information see https://redis.io/commands/brpoplpush + """ + if timeout is None: + timeout = 0 + return self.execute_command("BRPOPLPUSH", src, dst, timeout) + + def blmpop( + self, + timeout: float, + numkeys: int, + *args: List[str], + direction: str, + count: Optional[int] = 1, + ) -> Optional[list]: + """ + Pop ``count`` values (default 1) from first non-empty in the list + of provided key names. + + When all lists are empty this command blocks the connection until another + client pushes to it or until the timeout, timeout of 0 blocks indefinitely + + For more information see https://redis.io/commands/blmpop + """ + args = [timeout, numkeys, *args, direction, "COUNT", count] + + return self.execute_command("BLMPOP", *args) + + def lmpop( + self, + num_keys: int, + *args: List[str], + direction: str, + count: Optional[int] = 1, + ) -> Union[Awaitable[list], list]: + """ + Pop ``count`` values (default 1) first non-empty list key from the list + of args provided key names. + + For more information see https://redis.io/commands/lmpop + """ + args = [num_keys] + list(args) + [direction] + if count != 1: + args.extend(["COUNT", count]) + + return self.execute_command("LMPOP", *args) + + def lindex( + self, name: str, index: int + ) -> Union[Awaitable[Optional[str]], Optional[str]]: + """ + Return the item from list ``name`` at position ``index`` + + Negative indexes are supported and will return an item at the + end of the list + + For more information see https://redis.io/commands/lindex + """ + return self.execute_command("LINDEX", name, index) + + def linsert( + self, name: str, where: str, refvalue: str, value: str + ) -> Union[Awaitable[int], int]: + """ + Insert ``value`` in list ``name`` either immediately before or after + [``where``] ``refvalue`` + + Returns the new length of the list on success or -1 if ``refvalue`` + is not in the list. + + For more information see https://redis.io/commands/linsert + """ + return self.execute_command("LINSERT", name, where, refvalue, value) + + def llen(self, name: str) -> Union[Awaitable[int], int]: + """ + Return the length of the list ``name`` + + For more information see https://redis.io/commands/llen + """ + return self.execute_command("LLEN", name) + + def lpop( + self, + name: str, + count: Optional[int] = None, + ) -> Union[Awaitable[Union[str, List, None]], Union[str, List, None]]: + """ + Removes and returns the first elements of the list ``name``. + + By default, the command pops a single element from the beginning of + the list. When provided with the optional ``count`` argument, the reply + will consist of up to count elements, depending on the list's length. + + For more information see https://redis.io/commands/lpop + """ + if count is not None: + return self.execute_command("LPOP", name, count) + else: + return self.execute_command("LPOP", name) + + def lpush(self, name: str, *values: FieldT) -> Union[Awaitable[int], int]: + """ + Push ``values`` onto the head of the list ``name`` + + For more information see https://redis.io/commands/lpush + """ + return self.execute_command("LPUSH", name, *values) + + def lpushx(self, name: str, *values: FieldT) -> Union[Awaitable[int], int]: + """ + Push ``value`` onto the head of the list ``name`` if ``name`` exists + + For more information see https://redis.io/commands/lpushx + """ + return self.execute_command("LPUSHX", name, *values) + + def lrange(self, name: str, start: int, end: int) -> Union[Awaitable[list], list]: + """ + Return a slice of the list ``name`` between + position ``start`` and ``end`` + + ``start`` and ``end`` can be negative numbers just like + Python slicing notation + + For more information see https://redis.io/commands/lrange + """ + return self.execute_command("LRANGE", name, start, end) + + def lrem(self, name: str, count: int, value: str) -> Union[Awaitable[int], int]: + """ + Remove the first ``count`` occurrences of elements equal to ``value`` + from the list stored at ``name``. + + The count argument influences the operation in the following ways: + count > 0: Remove elements equal to value moving from head to tail. + count < 0: Remove elements equal to value moving from tail to head. + count = 0: Remove all elements equal to value. + + For more information see https://redis.io/commands/lrem + """ + return self.execute_command("LREM", name, count, value) + + def lset(self, name: str, index: int, value: str) -> Union[Awaitable[str], str]: + """ + Set element at ``index`` of list ``name`` to ``value`` + + For more information see https://redis.io/commands/lset + """ + return self.execute_command("LSET", name, index, value) + + def ltrim(self, name: str, start: int, end: int) -> Union[Awaitable[str], str]: + """ + Trim the list ``name``, removing all values not within the slice + between ``start`` and ``end`` + + ``start`` and ``end`` can be negative numbers just like + Python slicing notation + + For more information see https://redis.io/commands/ltrim + """ + return self.execute_command("LTRIM", name, start, end) + + def rpop( + self, + name: str, + count: Optional[int] = None, + ) -> Union[Awaitable[Union[str, List, None]], Union[str, List, None]]: + """ + Removes and returns the last elements of the list ``name``. + + By default, the command pops a single element from the end of the list. + When provided with the optional ``count`` argument, the reply will + consist of up to count elements, depending on the list's length. + + For more information see https://redis.io/commands/rpop + """ + if count is not None: + return self.execute_command("RPOP", name, count) + else: + return self.execute_command("RPOP", name) + + def rpoplpush(self, src: str, dst: str) -> Union[Awaitable[str], str]: + """ + RPOP a value off of the ``src`` list and atomically LPUSH it + on to the ``dst`` list. Returns the value. + + For more information see https://redis.io/commands/rpoplpush + """ + return self.execute_command("RPOPLPUSH", src, dst) + + def rpush(self, name: str, *values: FieldT) -> Union[Awaitable[int], int]: + """ + Push ``values`` onto the tail of the list ``name`` + + For more information see https://redis.io/commands/rpush + """ + return self.execute_command("RPUSH", name, *values) + + def rpushx(self, name: str, *values: str) -> Union[Awaitable[int], int]: + """ + Push ``value`` onto the tail of the list ``name`` if ``name`` exists + + For more information see https://redis.io/commands/rpushx + """ + return self.execute_command("RPUSHX", name, *values) + + def lpos( + self, + name: str, + value: str, + rank: Optional[int] = None, + count: Optional[int] = None, + maxlen: Optional[int] = None, + ) -> Union[str, List, None]: + """ + Get position of ``value`` within the list ``name`` + + If specified, ``rank`` indicates the "rank" of the first element to + return in case there are multiple copies of ``value`` in the list. + By default, LPOS returns the position of the first occurrence of + ``value`` in the list. When ``rank`` 2, LPOS returns the position of + the second ``value`` in the list. If ``rank`` is negative, LPOS + searches the list in reverse. For example, -1 would return the + position of the last occurrence of ``value`` and -2 would return the + position of the next to last occurrence of ``value``. + + If specified, ``count`` indicates that LPOS should return a list of + up to ``count`` positions. A ``count`` of 2 would return a list of + up to 2 positions. A ``count`` of 0 returns a list of all positions + matching ``value``. When ``count`` is specified and but ``value`` + does not exist in the list, an empty list is returned. + + If specified, ``maxlen`` indicates the maximum number of list + elements to scan. A ``maxlen`` of 1000 will only return the + position(s) of items within the first 1000 entries in the list. + A ``maxlen`` of 0 (the default) will scan the entire list. + + For more information see https://redis.io/commands/lpos + """ + pieces: list[EncodableT] = [name, value] + if rank is not None: + pieces.extend(["RANK", rank]) + + if count is not None: + pieces.extend(["COUNT", count]) + + if maxlen is not None: + pieces.extend(["MAXLEN", maxlen]) + + return self.execute_command("LPOS", *pieces) + + def sort( + self, + name: str, + start: Optional[int] = None, + num: Optional[int] = None, + by: Optional[str] = None, + get: Optional[List[str]] = None, + desc: bool = False, + alpha: bool = False, + store: Optional[str] = None, + groups: Optional[bool] = False, + ) -> Union[List, int]: + """ + Sort and return the list, set or sorted set at ``name``. + + ``start`` and ``num`` allow for paging through the sorted data + + ``by`` allows using an external key to weight and sort the items. + Use an "*" to indicate where in the key the item value is located + + ``get`` allows for returning items from external keys rather than the + sorted data itself. Use an "*" to indicate where in the key + the item value is located + + ``desc`` allows for reversing the sort + + ``alpha`` allows for sorting lexicographically rather than numerically + + ``store`` allows for storing the result of the sort into + the key ``store`` + + ``groups`` if set to True and if ``get`` contains at least two + elements, sort will return a list of tuples, each containing the + values fetched from the arguments to ``get``. + + For more information see https://redis.io/commands/sort + """ + if (start is not None and num is None) or (num is not None and start is None): + raise DataError("``start`` and ``num`` must both be specified") + + pieces: list[EncodableT] = [name] + if by is not None: + pieces.extend([b"BY", by]) + if start is not None and num is not None: + pieces.extend([b"LIMIT", start, num]) + if get is not None: + # If get is a string assume we want to get a single value. + # Otherwise assume it's an interable and we want to get multiple + # values. We can't just iterate blindly because strings are + # iterable. + if isinstance(get, (bytes, str)): + pieces.extend([b"GET", get]) + else: + for g in get: + pieces.extend([b"GET", g]) + if desc: + pieces.append(b"DESC") + if alpha: + pieces.append(b"ALPHA") + if store is not None: + pieces.extend([b"STORE", store]) + if groups: + if not get or isinstance(get, (bytes, str)) or len(get) < 2: + raise DataError( + 'when using "groups" the "get" argument ' + "must be specified and contain at least " + "two keys" + ) + + options = {"groups": len(get) if groups else None} + return self.execute_command("SORT", *pieces, **options) + + def sort_ro( + self, + key: str, + start: Optional[int] = None, + num: Optional[int] = None, + by: Optional[str] = None, + get: Optional[List[str]] = None, + desc: bool = False, + alpha: bool = False, + ) -> list: + """ + Returns the elements contained in the list, set or sorted set at key. + (read-only variant of the SORT command) + + ``start`` and ``num`` allow for paging through the sorted data + + ``by`` allows using an external key to weight and sort the items. + Use an "*" to indicate where in the key the item value is located + + ``get`` allows for returning items from external keys rather than the + sorted data itself. Use an "*" to indicate where in the key + the item value is located + + ``desc`` allows for reversing the sort + + ``alpha`` allows for sorting lexicographically rather than numerically + + For more information see https://redis.io/commands/sort_ro + """ + return self.sort( + key, start=start, num=num, by=by, get=get, desc=desc, alpha=alpha + ) + + +AsyncListCommands = ListCommands + + +class ScanCommands(CommandsProtocol): + """ + Redis SCAN commands. + see: https://redis.io/commands/scan + """ + + def scan( + self, + cursor: int = 0, + match: Union[PatternT, None] = None, + count: Union[int, None] = None, + _type: Union[str, None] = None, + **kwargs, + ) -> ResponseT: + """ + Incrementally return lists of key names. Also return a cursor + indicating the scan position. + + ``match`` allows for filtering the keys by pattern + + ``count`` provides a hint to Redis about the number of keys to + return per batch. + + ``_type`` filters the returned values by a particular Redis type. + Stock Redis instances allow for the following types: + HASH, LIST, SET, STREAM, STRING, ZSET + Additionally, Redis modules can expose other types as well. + + For more information see https://redis.io/commands/scan + """ + pieces: list[EncodableT] = [cursor] + if match is not None: + pieces.extend([b"MATCH", match]) + if count is not None: + pieces.extend([b"COUNT", count]) + if _type is not None: + pieces.extend([b"TYPE", _type]) + return self.execute_command("SCAN", *pieces, **kwargs) + + def scan_iter( + self, + match: Union[PatternT, None] = None, + count: Union[int, None] = None, + _type: Union[str, None] = None, + **kwargs, + ) -> Iterator: + """ + Make an iterator using the SCAN command so that the client doesn't + need to remember the cursor position. + + ``match`` allows for filtering the keys by pattern + + ``count`` provides a hint to Redis about the number of keys to + return per batch. + + ``_type`` filters the returned values by a particular Redis type. + Stock Redis instances allow for the following types: + HASH, LIST, SET, STREAM, STRING, ZSET + Additionally, Redis modules can expose other types as well. + """ + cursor = "0" + while cursor != 0: + cursor, data = self.scan( + cursor=cursor, match=match, count=count, _type=_type, **kwargs + ) + yield from data + + def sscan( + self, + name: KeyT, + cursor: int = 0, + match: Union[PatternT, None] = None, + count: Union[int, None] = None, + ) -> ResponseT: + """ + Incrementally return lists of elements in a set. Also return a cursor + indicating the scan position. + + ``match`` allows for filtering the keys by pattern + + ``count`` allows for hint the minimum number of returns + + For more information see https://redis.io/commands/sscan + """ + pieces: list[EncodableT] = [name, cursor] + if match is not None: + pieces.extend([b"MATCH", match]) + if count is not None: + pieces.extend([b"COUNT", count]) + return self.execute_command("SSCAN", *pieces) + + def sscan_iter( + self, + name: KeyT, + match: Union[PatternT, None] = None, + count: Union[int, None] = None, + ) -> Iterator: + """ + Make an iterator using the SSCAN command so that the client doesn't + need to remember the cursor position. + + ``match`` allows for filtering the keys by pattern + + ``count`` allows for hint the minimum number of returns + """ + cursor = "0" + while cursor != 0: + cursor, data = self.sscan(name, cursor=cursor, match=match, count=count) + yield from data + + def hscan( + self, + name: KeyT, + cursor: int = 0, + match: Union[PatternT, None] = None, + count: Union[int, None] = None, + ) -> ResponseT: + """ + Incrementally return key/value slices in a hash. Also return a cursor + indicating the scan position. + + ``match`` allows for filtering the keys by pattern + + ``count`` allows for hint the minimum number of returns + + For more information see https://redis.io/commands/hscan + """ + pieces: list[EncodableT] = [name, cursor] + if match is not None: + pieces.extend([b"MATCH", match]) + if count is not None: + pieces.extend([b"COUNT", count]) + return self.execute_command("HSCAN", *pieces) + + def hscan_iter( + self, + name: str, + match: Union[PatternT, None] = None, + count: Union[int, None] = None, + ) -> Iterator: + """ + Make an iterator using the HSCAN command so that the client doesn't + need to remember the cursor position. + + ``match`` allows for filtering the keys by pattern + + ``count`` allows for hint the minimum number of returns + """ + cursor = "0" + while cursor != 0: + cursor, data = self.hscan(name, cursor=cursor, match=match, count=count) + yield from data.items() + + def zscan( + self, + name: KeyT, + cursor: int = 0, + match: Union[PatternT, None] = None, + count: Union[int, None] = None, + score_cast_func: Union[type, Callable] = float, + ) -> ResponseT: + """ + Incrementally return lists of elements in a sorted set. Also return a + cursor indicating the scan position. + + ``match`` allows for filtering the keys by pattern + + ``count`` allows for hint the minimum number of returns + + ``score_cast_func`` a callable used to cast the score return value + + For more information see https://redis.io/commands/zscan + """ + pieces = [name, cursor] + if match is not None: + pieces.extend([b"MATCH", match]) + if count is not None: + pieces.extend([b"COUNT", count]) + options = {"score_cast_func": score_cast_func} + return self.execute_command("ZSCAN", *pieces, **options) + + def zscan_iter( + self, + name: KeyT, + match: Union[PatternT, None] = None, + count: Union[int, None] = None, + score_cast_func: Union[type, Callable] = float, + ) -> Iterator: + """ + Make an iterator using the ZSCAN command so that the client doesn't + need to remember the cursor position. + + ``match`` allows for filtering the keys by pattern + + ``count`` allows for hint the minimum number of returns + + ``score_cast_func`` a callable used to cast the score return value + """ + cursor = "0" + while cursor != 0: + cursor, data = self.zscan( + name, + cursor=cursor, + match=match, + count=count, + score_cast_func=score_cast_func, + ) + yield from data + + +class AsyncScanCommands(ScanCommands): + async def scan_iter( + self, + match: Union[PatternT, None] = None, + count: Union[int, None] = None, + _type: Union[str, None] = None, + **kwargs, + ) -> AsyncIterator: + """ + Make an iterator using the SCAN command so that the client doesn't + need to remember the cursor position. + + ``match`` allows for filtering the keys by pattern + + ``count`` provides a hint to Redis about the number of keys to + return per batch. + + ``_type`` filters the returned values by a particular Redis type. + Stock Redis instances allow for the following types: + HASH, LIST, SET, STREAM, STRING, ZSET + Additionally, Redis modules can expose other types as well. + """ + cursor = "0" + while cursor != 0: + cursor, data = await self.scan( + cursor=cursor, match=match, count=count, _type=_type, **kwargs + ) + for d in data: + yield d + + async def sscan_iter( + self, + name: KeyT, + match: Union[PatternT, None] = None, + count: Union[int, None] = None, + ) -> AsyncIterator: + """ + Make an iterator using the SSCAN command so that the client doesn't + need to remember the cursor position. + + ``match`` allows for filtering the keys by pattern + + ``count`` allows for hint the minimum number of returns + """ + cursor = "0" + while cursor != 0: + cursor, data = await self.sscan( + name, cursor=cursor, match=match, count=count + ) + for d in data: + yield d + + async def hscan_iter( + self, + name: str, + match: Union[PatternT, None] = None, + count: Union[int, None] = None, + ) -> AsyncIterator: + """ + Make an iterator using the HSCAN command so that the client doesn't + need to remember the cursor position. + + ``match`` allows for filtering the keys by pattern + + ``count`` allows for hint the minimum number of returns + """ + cursor = "0" + while cursor != 0: + cursor, data = await self.hscan( + name, cursor=cursor, match=match, count=count + ) + for it in data.items(): + yield it + + async def zscan_iter( + self, + name: KeyT, + match: Union[PatternT, None] = None, + count: Union[int, None] = None, + score_cast_func: Union[type, Callable] = float, + ) -> AsyncIterator: + """ + Make an iterator using the ZSCAN command so that the client doesn't + need to remember the cursor position. + + ``match`` allows for filtering the keys by pattern + + ``count`` allows for hint the minimum number of returns + + ``score_cast_func`` a callable used to cast the score return value + """ + cursor = "0" + while cursor != 0: + cursor, data = await self.zscan( + name, + cursor=cursor, + match=match, + count=count, + score_cast_func=score_cast_func, + ) + for d in data: + yield d + + +class SetCommands(CommandsProtocol): + """ + Redis commands for Set data type. + see: https://redis.io/topics/data-types#sets + """ + + def sadd(self, name: str, *values: FieldT) -> Union[Awaitable[int], int]: + """ + Add ``value(s)`` to set ``name`` + + For more information see https://redis.io/commands/sadd + """ + return self.execute_command("SADD", name, *values) + + def scard(self, name: str) -> Union[Awaitable[int], int]: + """ + Return the number of elements in set ``name`` + + For more information see https://redis.io/commands/scard + """ + return self.execute_command("SCARD", name) + + def sdiff(self, keys: List, *args: List) -> Union[Awaitable[list], list]: + """ + Return the difference of sets specified by ``keys`` + + For more information see https://redis.io/commands/sdiff + """ + args = list_or_args(keys, args) + return self.execute_command("SDIFF", *args) + + def sdiffstore( + self, dest: str, keys: List, *args: List + ) -> Union[Awaitable[int], int]: + """ + Store the difference of sets specified by ``keys`` into a new + set named ``dest``. Returns the number of keys in the new set. + + For more information see https://redis.io/commands/sdiffstore + """ + args = list_or_args(keys, args) + return self.execute_command("SDIFFSTORE", dest, *args) + + def sinter(self, keys: List, *args: List) -> Union[Awaitable[list], list]: + """ + Return the intersection of sets specified by ``keys`` + + For more information see https://redis.io/commands/sinter + """ + args = list_or_args(keys, args) + return self.execute_command("SINTER", *args) + + def sintercard( + self, numkeys: int, keys: List[str], limit: int = 0 + ) -> Union[Awaitable[int], int]: + """ + Return the cardinality of the intersect of multiple sets specified by ``keys`. + + When LIMIT provided (defaults to 0 and means unlimited), if the intersection + cardinality reaches limit partway through the computation, the algorithm will + exit and yield limit as the cardinality + + For more information see https://redis.io/commands/sintercard + """ + args = [numkeys, *keys, "LIMIT", limit] + return self.execute_command("SINTERCARD", *args) + + def sinterstore( + self, dest: str, keys: List, *args: List + ) -> Union[Awaitable[int], int]: + """ + Store the intersection of sets specified by ``keys`` into a new + set named ``dest``. Returns the number of keys in the new set. + + For more information see https://redis.io/commands/sinterstore + """ + args = list_or_args(keys, args) + return self.execute_command("SINTERSTORE", dest, *args) + + def sismember( + self, name: str, value: str + ) -> Union[Awaitable[Union[Literal[0], Literal[1]]], Union[Literal[0], Literal[1]]]: + """ + Return whether ``value`` is a member of set ``name``: + - 1 if the value is a member of the set. + - 0 if the value is not a member of the set or if key does not exist. + + For more information see https://redis.io/commands/sismember + """ + return self.execute_command("SISMEMBER", name, value) + + def smembers(self, name: str) -> Union[Awaitable[Set], Set]: + """ + Return all members of the set ``name`` + + For more information see https://redis.io/commands/smembers + """ + return self.execute_command("SMEMBERS", name) + + def smismember( + self, name: str, values: List, *args: List + ) -> Union[ + Awaitable[List[Union[Literal[0], Literal[1]]]], + List[Union[Literal[0], Literal[1]]], + ]: + """ + Return whether each value in ``values`` is a member of the set ``name`` + as a list of ``int`` in the order of ``values``: + - 1 if the value is a member of the set. + - 0 if the value is not a member of the set or if key does not exist. + + For more information see https://redis.io/commands/smismember + """ + args = list_or_args(values, args) + return self.execute_command("SMISMEMBER", name, *args) + + def smove(self, src: str, dst: str, value: str) -> Union[Awaitable[bool], bool]: + """ + Move ``value`` from set ``src`` to set ``dst`` atomically + + For more information see https://redis.io/commands/smove + """ + return self.execute_command("SMOVE", src, dst, value) + + def spop(self, name: str, count: Optional[int] = None) -> Union[str, List, None]: + """ + Remove and return a random member of set ``name`` + + For more information see https://redis.io/commands/spop + """ + args = (count is not None) and [count] or [] + return self.execute_command("SPOP", name, *args) + + def srandmember( + self, name: str, number: Optional[int] = None + ) -> Union[str, List, None]: + """ + If ``number`` is None, returns a random member of set ``name``. + + If ``number`` is supplied, returns a list of ``number`` random + members of set ``name``. Note this is only available when running + Redis 2.6+. + + For more information see https://redis.io/commands/srandmember + """ + args = (number is not None) and [number] or [] + return self.execute_command("SRANDMEMBER", name, *args) + + def srem(self, name: str, *values: FieldT) -> Union[Awaitable[int], int]: + """ + Remove ``values`` from set ``name`` + + For more information see https://redis.io/commands/srem + """ + return self.execute_command("SREM", name, *values) + + def sunion(self, keys: List, *args: List) -> Union[Awaitable[List], List]: + """ + Return the union of sets specified by ``keys`` + + For more information see https://redis.io/commands/sunion + """ + args = list_or_args(keys, args) + return self.execute_command("SUNION", *args) + + def sunionstore( + self, dest: str, keys: List, *args: List + ) -> Union[Awaitable[int], int]: + """ + Store the union of sets specified by ``keys`` into a new + set named ``dest``. Returns the number of keys in the new set. + + For more information see https://redis.io/commands/sunionstore + """ + args = list_or_args(keys, args) + return self.execute_command("SUNIONSTORE", dest, *args) + + +AsyncSetCommands = SetCommands + + +class StreamCommands(CommandsProtocol): + """ + Redis commands for Stream data type. + see: https://redis.io/topics/streams-intro + """ + + def xack(self, name: KeyT, groupname: GroupT, *ids: StreamIdT) -> ResponseT: + """ + Acknowledges the successful processing of one or more messages. + name: name of the stream. + groupname: name of the consumer group. + *ids: message ids to acknowledge. + + For more information see https://redis.io/commands/xack + """ + return self.execute_command("XACK", name, groupname, *ids) + + def xadd( + self, + name: KeyT, + fields: Dict[FieldT, EncodableT], + id: StreamIdT = "*", + maxlen: Union[int, None] = None, + approximate: bool = True, + nomkstream: bool = False, + minid: Union[StreamIdT, None] = None, + limit: Union[int, None] = None, + ) -> ResponseT: + """ + Add to a stream. + name: name of the stream + fields: dict of field/value pairs to insert into the stream + id: Location to insert this record. By default it is appended. + maxlen: truncate old stream members beyond this size. + Can't be specified with minid. + approximate: actual stream length may be slightly more than maxlen + nomkstream: When set to true, do not make a stream + minid: the minimum id in the stream to query. + Can't be specified with maxlen. + limit: specifies the maximum number of entries to retrieve + + For more information see https://redis.io/commands/xadd + """ + pieces: list[EncodableT] = [] + if maxlen is not None and minid is not None: + raise DataError("Only one of ```maxlen``` or ```minid``` may be specified") + + if maxlen is not None: + if not isinstance(maxlen, int) or maxlen < 0: + raise DataError("XADD maxlen must be non-negative integer") + pieces.append(b"MAXLEN") + if approximate: + pieces.append(b"~") + pieces.append(str(maxlen)) + if minid is not None: + pieces.append(b"MINID") + if approximate: + pieces.append(b"~") + pieces.append(minid) + if limit is not None: + pieces.extend([b"LIMIT", limit]) + if nomkstream: + pieces.append(b"NOMKSTREAM") + pieces.append(id) + if not isinstance(fields, dict) or len(fields) == 0: + raise DataError("XADD fields must be a non-empty dict") + for pair in fields.items(): + pieces.extend(pair) + return self.execute_command("XADD", name, *pieces) + + def xautoclaim( + self, + name: KeyT, + groupname: GroupT, + consumername: ConsumerT, + min_idle_time: int, + start_id: StreamIdT = "0-0", + count: Union[int, None] = None, + justid: bool = False, + ) -> ResponseT: + """ + Transfers ownership of pending stream entries that match the specified + criteria. Conceptually, equivalent to calling XPENDING and then XCLAIM, + but provides a more straightforward way to deal with message delivery + failures via SCAN-like semantics. + name: name of the stream. + groupname: name of the consumer group. + consumername: name of a consumer that claims the message. + min_idle_time: filter messages that were idle less than this amount of + milliseconds. + start_id: filter messages with equal or greater ID. + count: optional integer, upper limit of the number of entries that the + command attempts to claim. Set to 100 by default. + justid: optional boolean, false by default. Return just an array of IDs + of messages successfully claimed, without returning the actual message + + For more information see https://redis.io/commands/xautoclaim + """ + try: + if int(min_idle_time) < 0: + raise DataError( + "XAUTOCLAIM min_idle_time must be a nonnegative integer" + ) + except TypeError: + pass + + kwargs = {} + pieces = [name, groupname, consumername, min_idle_time, start_id] + + try: + if int(count) < 0: + raise DataError("XPENDING count must be a integer >= 0") + pieces.extend([b"COUNT", count]) + except TypeError: + pass + if justid: + pieces.append(b"JUSTID") + kwargs["parse_justid"] = True + + return self.execute_command("XAUTOCLAIM", *pieces, **kwargs) + + def xclaim( + self, + name: KeyT, + groupname: GroupT, + consumername: ConsumerT, + min_idle_time: int, + message_ids: Union[List[StreamIdT], Tuple[StreamIdT]], + idle: Union[int, None] = None, + time: Union[int, None] = None, + retrycount: Union[int, None] = None, + force: bool = False, + justid: bool = False, + ) -> ResponseT: + """ + Changes the ownership of a pending message. + + name: name of the stream. + + groupname: name of the consumer group. + + consumername: name of a consumer that claims the message. + + min_idle_time: filter messages that were idle less than this amount of + milliseconds + + message_ids: non-empty list or tuple of message IDs to claim + + idle: optional. Set the idle time (last time it was delivered) of the + message in ms + + time: optional integer. This is the same as idle but instead of a + relative amount of milliseconds, it sets the idle time to a specific + Unix time (in milliseconds). + + retrycount: optional integer. set the retry counter to the specified + value. This counter is incremented every time a message is delivered + again. + + force: optional boolean, false by default. Creates the pending message + entry in the PEL even if certain specified IDs are not already in the + PEL assigned to a different client. + + justid: optional boolean, false by default. Return just an array of IDs + of messages successfully claimed, without returning the actual message + + For more information see https://redis.io/commands/xclaim + """ + if not isinstance(min_idle_time, int) or min_idle_time < 0: + raise DataError("XCLAIM min_idle_time must be a non negative integer") + if not isinstance(message_ids, (list, tuple)) or not message_ids: + raise DataError( + "XCLAIM message_ids must be a non empty list or " + "tuple of message IDs to claim" + ) + + kwargs = {} + pieces: list[EncodableT] = [name, groupname, consumername, str(min_idle_time)] + pieces.extend(list(message_ids)) + + if idle is not None: + if not isinstance(idle, int): + raise DataError("XCLAIM idle must be an integer") + pieces.extend((b"IDLE", str(idle))) + if time is not None: + if not isinstance(time, int): + raise DataError("XCLAIM time must be an integer") + pieces.extend((b"TIME", str(time))) + if retrycount is not None: + if not isinstance(retrycount, int): + raise DataError("XCLAIM retrycount must be an integer") + pieces.extend((b"RETRYCOUNT", str(retrycount))) + + if force: + if not isinstance(force, bool): + raise DataError("XCLAIM force must be a boolean") + pieces.append(b"FORCE") + if justid: + if not isinstance(justid, bool): + raise DataError("XCLAIM justid must be a boolean") + pieces.append(b"JUSTID") + kwargs["parse_justid"] = True + return self.execute_command("XCLAIM", *pieces, **kwargs) + + def xdel(self, name: KeyT, *ids: StreamIdT) -> ResponseT: + """ + Deletes one or more messages from a stream. + name: name of the stream. + *ids: message ids to delete. + + For more information see https://redis.io/commands/xdel + """ + return self.execute_command("XDEL", name, *ids) + + def xgroup_create( + self, + name: KeyT, + groupname: GroupT, + id: StreamIdT = "$", + mkstream: bool = False, + entries_read: Optional[int] = None, + ) -> ResponseT: + """ + Create a new consumer group associated with a stream. + name: name of the stream. + groupname: name of the consumer group. + id: ID of the last item in the stream to consider already delivered. + + For more information see https://redis.io/commands/xgroup-create + """ + pieces: list[EncodableT] = ["XGROUP CREATE", name, groupname, id] + if mkstream: + pieces.append(b"MKSTREAM") + if entries_read is not None: + pieces.extend(["ENTRIESREAD", entries_read]) + + return self.execute_command(*pieces) + + def xgroup_delconsumer( + self, name: KeyT, groupname: GroupT, consumername: ConsumerT + ) -> ResponseT: + """ + Remove a specific consumer from a consumer group. + Returns the number of pending messages that the consumer had before it + was deleted. + name: name of the stream. + groupname: name of the consumer group. + consumername: name of consumer to delete + + For more information see https://redis.io/commands/xgroup-delconsumer + """ + return self.execute_command("XGROUP DELCONSUMER", name, groupname, consumername) + + def xgroup_destroy(self, name: KeyT, groupname: GroupT) -> ResponseT: + """ + Destroy a consumer group. + name: name of the stream. + groupname: name of the consumer group. + + For more information see https://redis.io/commands/xgroup-destroy + """ + return self.execute_command("XGROUP DESTROY", name, groupname) + + def xgroup_createconsumer( + self, name: KeyT, groupname: GroupT, consumername: ConsumerT + ) -> ResponseT: + """ + Consumers in a consumer group are auto-created every time a new + consumer name is mentioned by some command. + They can be explicitly created by using this command. + name: name of the stream. + groupname: name of the consumer group. + consumername: name of consumer to create. + + See: https://redis.io/commands/xgroup-createconsumer + """ + return self.execute_command( + "XGROUP CREATECONSUMER", name, groupname, consumername + ) + + def xgroup_setid( + self, + name: KeyT, + groupname: GroupT, + id: StreamIdT, + entries_read: Optional[int] = None, + ) -> ResponseT: + """ + Set the consumer group last delivered ID to something else. + name: name of the stream. + groupname: name of the consumer group. + id: ID of the last item in the stream to consider already delivered. + + For more information see https://redis.io/commands/xgroup-setid + """ + pieces = [name, groupname, id] + if entries_read is not None: + pieces.extend(["ENTRIESREAD", entries_read]) + return self.execute_command("XGROUP SETID", *pieces) + + def xinfo_consumers(self, name: KeyT, groupname: GroupT) -> ResponseT: + """ + Returns general information about the consumers in the group. + name: name of the stream. + groupname: name of the consumer group. + + For more information see https://redis.io/commands/xinfo-consumers + """ + return self.execute_command("XINFO CONSUMERS", name, groupname) + + def xinfo_groups(self, name: KeyT) -> ResponseT: + """ + Returns general information about the consumer groups of the stream. + name: name of the stream. + + For more information see https://redis.io/commands/xinfo-groups + """ + return self.execute_command("XINFO GROUPS", name) + + def xinfo_stream(self, name: KeyT, full: bool = False) -> ResponseT: + """ + Returns general information about the stream. + name: name of the stream. + full: optional boolean, false by default. Return full summary + + For more information see https://redis.io/commands/xinfo-stream + """ + pieces = [name] + options = {} + if full: + pieces.append(b"FULL") + options = {"full": full} + return self.execute_command("XINFO STREAM", *pieces, **options) + + def xlen(self, name: KeyT) -> ResponseT: + """ + Returns the number of elements in a given stream. + + For more information see https://redis.io/commands/xlen + """ + return self.execute_command("XLEN", name) + + def xpending(self, name: KeyT, groupname: GroupT) -> ResponseT: + """ + Returns information about pending messages of a group. + name: name of the stream. + groupname: name of the consumer group. + + For more information see https://redis.io/commands/xpending + """ + return self.execute_command("XPENDING", name, groupname) + + def xpending_range( + self, + name: KeyT, + groupname: GroupT, + min: StreamIdT, + max: StreamIdT, + count: int, + consumername: Union[ConsumerT, None] = None, + idle: Union[int, None] = None, + ) -> ResponseT: + """ + Returns information about pending messages, in a range. + + name: name of the stream. + groupname: name of the consumer group. + idle: available from version 6.2. filter entries by their + idle-time, given in milliseconds (optional). + min: minimum stream ID. + max: maximum stream ID. + count: number of messages to return + consumername: name of a consumer to filter by (optional). + """ + if {min, max, count} == {None}: + if idle is not None or consumername is not None: + raise DataError( + "if XPENDING is provided with idle time" + " or consumername, it must be provided" + " with min, max and count parameters" + ) + return self.xpending(name, groupname) + + pieces = [name, groupname] + if min is None or max is None or count is None: + raise DataError( + "XPENDING must be provided with min, max " + "and count parameters, or none of them." + ) + # idle + try: + if int(idle) < 0: + raise DataError("XPENDING idle must be a integer >= 0") + pieces.extend(["IDLE", idle]) + except TypeError: + pass + # count + try: + if int(count) < 0: + raise DataError("XPENDING count must be a integer >= 0") + pieces.extend([min, max, count]) + except TypeError: + pass + # consumername + if consumername: + pieces.append(consumername) + + return self.execute_command("XPENDING", *pieces, parse_detail=True) + + def xrange( + self, + name: KeyT, + min: StreamIdT = "-", + max: StreamIdT = "+", + count: Union[int, None] = None, + ) -> ResponseT: + """ + Read stream values within an interval. + + name: name of the stream. + + start: first stream ID. defaults to '-', + meaning the earliest available. + + finish: last stream ID. defaults to '+', + meaning the latest available. + + count: if set, only return this many items, beginning with the + earliest available. + + For more information see https://redis.io/commands/xrange + """ + pieces = [min, max] + if count is not None: + if not isinstance(count, int) or count < 1: + raise DataError("XRANGE count must be a positive integer") + pieces.append(b"COUNT") + pieces.append(str(count)) + + return self.execute_command("XRANGE", name, *pieces) + + def xread( + self, + streams: Dict[KeyT, StreamIdT], + count: Union[int, None] = None, + block: Union[int, None] = None, + ) -> ResponseT: + """ + Block and monitor multiple streams for new data. + + streams: a dict of stream names to stream IDs, where + IDs indicate the last ID already seen. + + count: if set, only return this many items, beginning with the + earliest available. + + block: number of milliseconds to wait, if nothing already present. + + For more information see https://redis.io/commands/xread + """ + pieces = [] + if block is not None: + if not isinstance(block, int) or block < 0: + raise DataError("XREAD block must be a non-negative integer") + pieces.append(b"BLOCK") + pieces.append(str(block)) + if count is not None: + if not isinstance(count, int) or count < 1: + raise DataError("XREAD count must be a positive integer") + pieces.append(b"COUNT") + pieces.append(str(count)) + if not isinstance(streams, dict) or len(streams) == 0: + raise DataError("XREAD streams must be a non empty dict") + pieces.append(b"STREAMS") + keys, values = zip(*streams.items()) + pieces.extend(keys) + pieces.extend(values) + return self.execute_command("XREAD", *pieces) + + def xreadgroup( + self, + groupname: str, + consumername: str, + streams: Dict[KeyT, StreamIdT], + count: Union[int, None] = None, + block: Union[int, None] = None, + noack: bool = False, + ) -> ResponseT: + """ + Read from a stream via a consumer group. + + groupname: name of the consumer group. + + consumername: name of the requesting consumer. + + streams: a dict of stream names to stream IDs, where + IDs indicate the last ID already seen. + + count: if set, only return this many items, beginning with the + earliest available. + + block: number of milliseconds to wait, if nothing already present. + noack: do not add messages to the PEL + + For more information see https://redis.io/commands/xreadgroup + """ + pieces: list[EncodableT] = [b"GROUP", groupname, consumername] + if count is not None: + if not isinstance(count, int) or count < 1: + raise DataError("XREADGROUP count must be a positive integer") + pieces.append(b"COUNT") + pieces.append(str(count)) + if block is not None: + if not isinstance(block, int) or block < 0: + raise DataError("XREADGROUP block must be a non-negative integer") + pieces.append(b"BLOCK") + pieces.append(str(block)) + if noack: + pieces.append(b"NOACK") + if not isinstance(streams, dict) or len(streams) == 0: + raise DataError("XREADGROUP streams must be a non empty dict") + pieces.append(b"STREAMS") + pieces.extend(streams.keys()) + pieces.extend(streams.values()) + return self.execute_command("XREADGROUP", *pieces) + + def xrevrange( + self, + name: KeyT, + max: StreamIdT = "+", + min: StreamIdT = "-", + count: Union[int, None] = None, + ) -> ResponseT: + """ + Read stream values within an interval, in reverse order. + + name: name of the stream + + start: first stream ID. defaults to '+', + meaning the latest available. + + finish: last stream ID. defaults to '-', + meaning the earliest available. + + count: if set, only return this many items, beginning with the + latest available. + + For more information see https://redis.io/commands/xrevrange + """ + pieces: list[EncodableT] = [max, min] + if count is not None: + if not isinstance(count, int) or count < 1: + raise DataError("XREVRANGE count must be a positive integer") + pieces.append(b"COUNT") + pieces.append(str(count)) + + return self.execute_command("XREVRANGE", name, *pieces) + + def xtrim( + self, + name: KeyT, + maxlen: Union[int, None] = None, + approximate: bool = True, + minid: Union[StreamIdT, None] = None, + limit: Union[int, None] = None, + ) -> ResponseT: + """ + Trims old messages from a stream. + name: name of the stream. + maxlen: truncate old stream messages beyond this size + Can't be specified with minid. + approximate: actual stream length may be slightly more than maxlen + minid: the minimum id in the stream to query + Can't be specified with maxlen. + limit: specifies the maximum number of entries to retrieve + + For more information see https://redis.io/commands/xtrim + """ + pieces: list[EncodableT] = [] + if maxlen is not None and minid is not None: + raise DataError("Only one of ``maxlen`` or ``minid`` may be specified") + + if maxlen is None and minid is None: + raise DataError("One of ``maxlen`` or ``minid`` must be specified") + + if maxlen is not None: + pieces.append(b"MAXLEN") + if minid is not None: + pieces.append(b"MINID") + if approximate: + pieces.append(b"~") + if maxlen is not None: + pieces.append(maxlen) + if minid is not None: + pieces.append(minid) + if limit is not None: + pieces.append(b"LIMIT") + pieces.append(limit) + + return self.execute_command("XTRIM", name, *pieces) + + +AsyncStreamCommands = StreamCommands + + +class SortedSetCommands(CommandsProtocol): + """ + Redis commands for Sorted Sets data type. + see: https://redis.io/topics/data-types-intro#redis-sorted-sets + """ + + def zadd( + self, + name: KeyT, + mapping: Mapping[AnyKeyT, EncodableT], + nx: bool = False, + xx: bool = False, + ch: bool = False, + incr: bool = False, + gt: bool = False, + lt: bool = False, + ) -> ResponseT: + """ + Set any number of element-name, score pairs to the key ``name``. Pairs + are specified as a dict of element-names keys to score values. + + ``nx`` forces ZADD to only create new elements and not to update + scores for elements that already exist. + + ``xx`` forces ZADD to only update scores of elements that already + exist. New elements will not be added. + + ``ch`` modifies the return value to be the numbers of elements changed. + Changed elements include new elements that were added and elements + whose scores changed. + + ``incr`` modifies ZADD to behave like ZINCRBY. In this mode only a + single element/score pair can be specified and the score is the amount + the existing score will be incremented by. When using this mode the + return value of ZADD will be the new score of the element. + + ``LT`` Only update existing elements if the new score is less than + the current score. This flag doesn't prevent adding new elements. + + ``GT`` Only update existing elements if the new score is greater than + the current score. This flag doesn't prevent adding new elements. + + The return value of ZADD varies based on the mode specified. With no + options, ZADD returns the number of new elements added to the sorted + set. + + ``NX``, ``LT``, and ``GT`` are mutually exclusive options. + + See: https://redis.io/commands/ZADD + """ + if not mapping: + raise DataError("ZADD requires at least one element/score pair") + if nx and xx: + raise DataError("ZADD allows either 'nx' or 'xx', not both") + if gt and lt: + raise DataError("ZADD allows either 'gt' or 'lt', not both") + if incr and len(mapping) != 1: + raise DataError( + "ZADD option 'incr' only works when passing a " + "single element/score pair" + ) + if nx and (gt or lt): + raise DataError("Only one of 'nx', 'lt', or 'gr' may be defined.") + + pieces: list[EncodableT] = [] + options = {} + if nx: + pieces.append(b"NX") + if xx: + pieces.append(b"XX") + if ch: + pieces.append(b"CH") + if incr: + pieces.append(b"INCR") + options["as_score"] = True + if gt: + pieces.append(b"GT") + if lt: + pieces.append(b"LT") + for pair in mapping.items(): + pieces.append(pair[1]) + pieces.append(pair[0]) + return self.execute_command("ZADD", name, *pieces, **options) + + def zcard(self, name: KeyT) -> ResponseT: + """ + Return the number of elements in the sorted set ``name`` + + For more information see https://redis.io/commands/zcard + """ + return self.execute_command("ZCARD", name) + + def zcount(self, name: KeyT, min: ZScoreBoundT, max: ZScoreBoundT) -> ResponseT: + """ + Returns the number of elements in the sorted set at key ``name`` with + a score between ``min`` and ``max``. + + For more information see https://redis.io/commands/zcount + """ + return self.execute_command("ZCOUNT", name, min, max) + + def zdiff(self, keys: KeysT, withscores: bool = False) -> ResponseT: + """ + Returns the difference between the first and all successive input + sorted sets provided in ``keys``. + + For more information see https://redis.io/commands/zdiff + """ + pieces = [len(keys), *keys] + if withscores: + pieces.append("WITHSCORES") + return self.execute_command("ZDIFF", *pieces) + + def zdiffstore(self, dest: KeyT, keys: KeysT) -> ResponseT: + """ + Computes the difference between the first and all successive input + sorted sets provided in ``keys`` and stores the result in ``dest``. + + For more information see https://redis.io/commands/zdiffstore + """ + pieces = [len(keys), *keys] + return self.execute_command("ZDIFFSTORE", dest, *pieces) + + def zincrby(self, name: KeyT, amount: float, value: EncodableT) -> ResponseT: + """ + Increment the score of ``value`` in sorted set ``name`` by ``amount`` + + For more information see https://redis.io/commands/zincrby + """ + return self.execute_command("ZINCRBY", name, amount, value) + + def zinter( + self, keys: KeysT, aggregate: Union[str, None] = None, withscores: bool = False + ) -> ResponseT: + """ + Return the intersect of multiple sorted sets specified by ``keys``. + With the ``aggregate`` option, it is possible to specify how the + results of the union are aggregated. This option defaults to SUM, + where the score of an element is summed across the inputs where it + exists. When this option is set to either MIN or MAX, the resulting + set will contain the minimum or maximum score of an element across + the inputs where it exists. + + For more information see https://redis.io/commands/zinter + """ + return self._zaggregate("ZINTER", None, keys, aggregate, withscores=withscores) + + def zinterstore( + self, + dest: KeyT, + keys: Union[Sequence[KeyT], Mapping[AnyKeyT, float]], + aggregate: Union[str, None] = None, + ) -> ResponseT: + """ + Intersect multiple sorted sets specified by ``keys`` into a new + sorted set, ``dest``. Scores in the destination will be aggregated + based on the ``aggregate``. This option defaults to SUM, where the + score of an element is summed across the inputs where it exists. + When this option is set to either MIN or MAX, the resulting set will + contain the minimum or maximum score of an element across the inputs + where it exists. + + For more information see https://redis.io/commands/zinterstore + """ + return self._zaggregate("ZINTERSTORE", dest, keys, aggregate) + + def zintercard( + self, numkeys: int, keys: List[str], limit: int = 0 + ) -> Union[Awaitable[int], int]: + """ + Return the cardinality of the intersect of multiple sorted sets + specified by ``keys`. + When LIMIT provided (defaults to 0 and means unlimited), if the intersection + cardinality reaches limit partway through the computation, the algorithm will + exit and yield limit as the cardinality + + For more information see https://redis.io/commands/zintercard + """ + args = [numkeys, *keys, "LIMIT", limit] + return self.execute_command("ZINTERCARD", *args) + + def zlexcount(self, name, min, max): + """ + Return the number of items in the sorted set ``name`` between the + lexicographical range ``min`` and ``max``. + + For more information see https://redis.io/commands/zlexcount + """ + return self.execute_command("ZLEXCOUNT", name, min, max) + + def zpopmax(self, name: KeyT, count: Union[int, None] = None) -> ResponseT: + """ + Remove and return up to ``count`` members with the highest scores + from the sorted set ``name``. + + For more information see https://redis.io/commands/zpopmax + """ + args = (count is not None) and [count] or [] + options = {"withscores": True} + return self.execute_command("ZPOPMAX", name, *args, **options) + + def zpopmin(self, name: KeyT, count: Union[int, None] = None) -> ResponseT: + """ + Remove and return up to ``count`` members with the lowest scores + from the sorted set ``name``. + + For more information see https://redis.io/commands/zpopmin + """ + args = (count is not None) and [count] or [] + options = {"withscores": True} + return self.execute_command("ZPOPMIN", name, *args, **options) + + def zrandmember( + self, key: KeyT, count: int = None, withscores: bool = False + ) -> ResponseT: + """ + Return a random element from the sorted set value stored at key. + + ``count`` if the argument is positive, return an array of distinct + fields. If called with a negative count, the behavior changes and + the command is allowed to return the same field multiple times. + In this case, the number of returned fields is the absolute value + of the specified count. + + ``withscores`` The optional WITHSCORES modifier changes the reply so it + includes the respective scores of the randomly selected elements from + the sorted set. + + For more information see https://redis.io/commands/zrandmember + """ + params = [] + if count is not None: + params.append(count) + if withscores: + params.append("WITHSCORES") + + return self.execute_command("ZRANDMEMBER", key, *params) + + def bzpopmax(self, keys: KeysT, timeout: TimeoutSecT = 0) -> ResponseT: + """ + ZPOPMAX a value off of the first non-empty sorted set + named in the ``keys`` list. + + If none of the sorted sets in ``keys`` has a value to ZPOPMAX, + then block for ``timeout`` seconds, or until a member gets added + to one of the sorted sets. + + If timeout is 0, then block indefinitely. + + For more information see https://redis.io/commands/bzpopmax + """ + if timeout is None: + timeout = 0 + keys = list_or_args(keys, None) + keys.append(timeout) + return self.execute_command("BZPOPMAX", *keys) + + def bzpopmin(self, keys: KeysT, timeout: TimeoutSecT = 0) -> ResponseT: + """ + ZPOPMIN a value off of the first non-empty sorted set + named in the ``keys`` list. + + If none of the sorted sets in ``keys`` has a value to ZPOPMIN, + then block for ``timeout`` seconds, or until a member gets added + to one of the sorted sets. + + If timeout is 0, then block indefinitely. + + For more information see https://redis.io/commands/bzpopmin + """ + if timeout is None: + timeout = 0 + keys: list[EncodableT] = list_or_args(keys, None) + keys.append(timeout) + return self.execute_command("BZPOPMIN", *keys) + + def zmpop( + self, + num_keys: int, + keys: List[str], + min: Optional[bool] = False, + max: Optional[bool] = False, + count: Optional[int] = 1, + ) -> Union[Awaitable[list], list]: + """ + Pop ``count`` values (default 1) off of the first non-empty sorted set + named in the ``keys`` list. + For more information see https://redis.io/commands/zmpop + """ + args = [num_keys] + keys + if (min and max) or (not min and not max): + raise DataError + elif min: + args.append("MIN") + else: + args.append("MAX") + if count != 1: + args.extend(["COUNT", count]) + + return self.execute_command("ZMPOP", *args) + + def bzmpop( + self, + timeout: float, + numkeys: int, + keys: List[str], + min: Optional[bool] = False, + max: Optional[bool] = False, + count: Optional[int] = 1, + ) -> Optional[list]: + """ + Pop ``count`` values (default 1) off of the first non-empty sorted set + named in the ``keys`` list. + + If none of the sorted sets in ``keys`` has a value to pop, + then block for ``timeout`` seconds, or until a member gets added + to one of the sorted sets. + + If timeout is 0, then block indefinitely. + + For more information see https://redis.io/commands/bzmpop + """ + args = [timeout, numkeys, *keys] + if (min and max) or (not min and not max): + raise DataError("Either min or max, but not both must be set") + elif min: + args.append("MIN") + else: + args.append("MAX") + args.extend(["COUNT", count]) + + return self.execute_command("BZMPOP", *args) + + def _zrange( + self, + command, + dest: Union[KeyT, None], + name: KeyT, + start: int, + end: int, + desc: bool = False, + byscore: bool = False, + bylex: bool = False, + withscores: bool = False, + score_cast_func: Union[type, Callable, None] = float, + offset: Union[int, None] = None, + num: Union[int, None] = None, + ) -> ResponseT: + if byscore and bylex: + raise DataError("``byscore`` and ``bylex`` can not be specified together.") + if (offset is not None and num is None) or (num is not None and offset is None): + raise DataError("``offset`` and ``num`` must both be specified.") + if bylex and withscores: + raise DataError( + "``withscores`` not supported in combination with ``bylex``." + ) + pieces = [command] + if dest: + pieces.append(dest) + pieces.extend([name, start, end]) + if byscore: + pieces.append("BYSCORE") + if bylex: + pieces.append("BYLEX") + if desc: + pieces.append("REV") + if offset is not None and num is not None: + pieces.extend(["LIMIT", offset, num]) + if withscores: + pieces.append("WITHSCORES") + options = {"withscores": withscores, "score_cast_func": score_cast_func} + return self.execute_command(*pieces, **options) + + def zrange( + self, + name: KeyT, + start: int, + end: int, + desc: bool = False, + withscores: bool = False, + score_cast_func: Union[type, Callable] = float, + byscore: bool = False, + bylex: bool = False, + offset: int = None, + num: int = None, + ) -> ResponseT: + """ + Return a range of values from sorted set ``name`` between + ``start`` and ``end`` sorted in ascending order. + + ``start`` and ``end`` can be negative, indicating the end of the range. + + ``desc`` a boolean indicating whether to sort the results in reversed + order. + + ``withscores`` indicates to return the scores along with the values. + The return type is a list of (value, score) pairs. + + ``score_cast_func`` a callable used to cast the score return value. + + ``byscore`` when set to True, returns the range of elements from the + sorted set having scores equal or between ``start`` and ``end``. + + ``bylex`` when set to True, returns the range of elements from the + sorted set between the ``start`` and ``end`` lexicographical closed + range intervals. + Valid ``start`` and ``end`` must start with ( or [, in order to specify + whether the range interval is exclusive or inclusive, respectively. + + ``offset`` and ``num`` are specified, then return a slice of the range. + Can't be provided when using ``bylex``. + + For more information see https://redis.io/commands/zrange + """ + # Need to support ``desc`` also when using old redis version + # because it was supported in 3.5.3 (of redis-py) + if not byscore and not bylex and (offset is None and num is None) and desc: + return self.zrevrange(name, start, end, withscores, score_cast_func) + + return self._zrange( + "ZRANGE", + None, + name, + start, + end, + desc, + byscore, + bylex, + withscores, + score_cast_func, + offset, + num, + ) + + def zrevrange( + self, + name: KeyT, + start: int, + end: int, + withscores: bool = False, + score_cast_func: Union[type, Callable] = float, + ) -> ResponseT: + """ + Return a range of values from sorted set ``name`` between + ``start`` and ``end`` sorted in descending order. + + ``start`` and ``end`` can be negative, indicating the end of the range. + + ``withscores`` indicates to return the scores along with the values + The return type is a list of (value, score) pairs + + ``score_cast_func`` a callable used to cast the score return value + + For more information see https://redis.io/commands/zrevrange + """ + pieces = ["ZREVRANGE", name, start, end] + if withscores: + pieces.append(b"WITHSCORES") + options = {"withscores": withscores, "score_cast_func": score_cast_func} + return self.execute_command(*pieces, **options) + + def zrangestore( + self, + dest: KeyT, + name: KeyT, + start: int, + end: int, + byscore: bool = False, + bylex: bool = False, + desc: bool = False, + offset: Union[int, None] = None, + num: Union[int, None] = None, + ) -> ResponseT: + """ + Stores in ``dest`` the result of a range of values from sorted set + ``name`` between ``start`` and ``end`` sorted in ascending order. + + ``start`` and ``end`` can be negative, indicating the end of the range. + + ``byscore`` when set to True, returns the range of elements from the + sorted set having scores equal or between ``start`` and ``end``. + + ``bylex`` when set to True, returns the range of elements from the + sorted set between the ``start`` and ``end`` lexicographical closed + range intervals. + Valid ``start`` and ``end`` must start with ( or [, in order to specify + whether the range interval is exclusive or inclusive, respectively. + + ``desc`` a boolean indicating whether to sort the results in reversed + order. + + ``offset`` and ``num`` are specified, then return a slice of the range. + Can't be provided when using ``bylex``. + + For more information see https://redis.io/commands/zrangestore + """ + return self._zrange( + "ZRANGESTORE", + dest, + name, + start, + end, + desc, + byscore, + bylex, + False, + None, + offset, + num, + ) + + def zrangebylex( + self, + name: KeyT, + min: EncodableT, + max: EncodableT, + start: Union[int, None] = None, + num: Union[int, None] = None, + ) -> ResponseT: + """ + Return the lexicographical range of values from sorted set ``name`` + between ``min`` and ``max``. + + If ``start`` and ``num`` are specified, then return a slice of the + range. + + For more information see https://redis.io/commands/zrangebylex + """ + if (start is not None and num is None) or (num is not None and start is None): + raise DataError("``start`` and ``num`` must both be specified") + pieces = ["ZRANGEBYLEX", name, min, max] + if start is not None and num is not None: + pieces.extend([b"LIMIT", start, num]) + return self.execute_command(*pieces) + + def zrevrangebylex( + self, + name: KeyT, + max: EncodableT, + min: EncodableT, + start: Union[int, None] = None, + num: Union[int, None] = None, + ) -> ResponseT: + """ + Return the reversed lexicographical range of values from sorted set + ``name`` between ``max`` and ``min``. + + If ``start`` and ``num`` are specified, then return a slice of the + range. + + For more information see https://redis.io/commands/zrevrangebylex + """ + if (start is not None and num is None) or (num is not None and start is None): + raise DataError("``start`` and ``num`` must both be specified") + pieces = ["ZREVRANGEBYLEX", name, max, min] + if start is not None and num is not None: + pieces.extend(["LIMIT", start, num]) + return self.execute_command(*pieces) + + def zrangebyscore( + self, + name: KeyT, + min: ZScoreBoundT, + max: ZScoreBoundT, + start: Union[int, None] = None, + num: Union[int, None] = None, + withscores: bool = False, + score_cast_func: Union[type, Callable] = float, + ) -> ResponseT: + """ + Return a range of values from the sorted set ``name`` with scores + between ``min`` and ``max``. + + If ``start`` and ``num`` are specified, then return a slice + of the range. + + ``withscores`` indicates to return the scores along with the values. + The return type is a list of (value, score) pairs + + `score_cast_func`` a callable used to cast the score return value + + For more information see https://redis.io/commands/zrangebyscore + """ + if (start is not None and num is None) or (num is not None and start is None): + raise DataError("``start`` and ``num`` must both be specified") + pieces = ["ZRANGEBYSCORE", name, min, max] + if start is not None and num is not None: + pieces.extend(["LIMIT", start, num]) + if withscores: + pieces.append("WITHSCORES") + options = {"withscores": withscores, "score_cast_func": score_cast_func} + return self.execute_command(*pieces, **options) + + def zrevrangebyscore( + self, + name: KeyT, + max: ZScoreBoundT, + min: ZScoreBoundT, + start: Union[int, None] = None, + num: Union[int, None] = None, + withscores: bool = False, + score_cast_func: Union[type, Callable] = float, + ): + """ + Return a range of values from the sorted set ``name`` with scores + between ``min`` and ``max`` in descending order. + + If ``start`` and ``num`` are specified, then return a slice + of the range. + + ``withscores`` indicates to return the scores along with the values. + The return type is a list of (value, score) pairs + + ``score_cast_func`` a callable used to cast the score return value + + For more information see https://redis.io/commands/zrevrangebyscore + """ + if (start is not None and num is None) or (num is not None and start is None): + raise DataError("``start`` and ``num`` must both be specified") + pieces = ["ZREVRANGEBYSCORE", name, max, min] + if start is not None and num is not None: + pieces.extend(["LIMIT", start, num]) + if withscores: + pieces.append("WITHSCORES") + options = {"withscores": withscores, "score_cast_func": score_cast_func} + return self.execute_command(*pieces, **options) + + def zrank( + self, + name: KeyT, + value: EncodableT, + withscore: bool = False, + ) -> ResponseT: + """ + Returns a 0-based value indicating the rank of ``value`` in sorted set + ``name``. + The optional WITHSCORE argument supplements the command's + reply with the score of the element returned. + + For more information see https://redis.io/commands/zrank + """ + if withscore: + return self.execute_command("ZRANK", name, value, "WITHSCORE") + return self.execute_command("ZRANK", name, value) + + def zrem(self, name: KeyT, *values: FieldT) -> ResponseT: + """ + Remove member ``values`` from sorted set ``name`` + + For more information see https://redis.io/commands/zrem + """ + return self.execute_command("ZREM", name, *values) + + def zremrangebylex(self, name: KeyT, min: EncodableT, max: EncodableT) -> ResponseT: + """ + Remove all elements in the sorted set ``name`` between the + lexicographical range specified by ``min`` and ``max``. + + Returns the number of elements removed. + + For more information see https://redis.io/commands/zremrangebylex + """ + return self.execute_command("ZREMRANGEBYLEX", name, min, max) + + def zremrangebyrank(self, name: KeyT, min: int, max: int) -> ResponseT: + """ + Remove all elements in the sorted set ``name`` with ranks between + ``min`` and ``max``. Values are 0-based, ordered from smallest score + to largest. Values can be negative indicating the highest scores. + Returns the number of elements removed + + For more information see https://redis.io/commands/zremrangebyrank + """ + return self.execute_command("ZREMRANGEBYRANK", name, min, max) + + def zremrangebyscore( + self, name: KeyT, min: ZScoreBoundT, max: ZScoreBoundT + ) -> ResponseT: + """ + Remove all elements in the sorted set ``name`` with scores + between ``min`` and ``max``. Returns the number of elements removed. + + For more information see https://redis.io/commands/zremrangebyscore + """ + return self.execute_command("ZREMRANGEBYSCORE", name, min, max) + + def zrevrank( + self, + name: KeyT, + value: EncodableT, + withscore: bool = False, + ) -> ResponseT: + """ + Returns a 0-based value indicating the descending rank of + ``value`` in sorted set ``name``. + The optional ``withscore`` argument supplements the command's + reply with the score of the element returned. + + For more information see https://redis.io/commands/zrevrank + """ + if withscore: + return self.execute_command("ZREVRANK", name, value, "WITHSCORE") + return self.execute_command("ZREVRANK", name, value) + + def zscore(self, name: KeyT, value: EncodableT) -> ResponseT: + """ + Return the score of element ``value`` in sorted set ``name`` + + For more information see https://redis.io/commands/zscore + """ + return self.execute_command("ZSCORE", name, value) + + def zunion( + self, + keys: Union[Sequence[KeyT], Mapping[AnyKeyT, float]], + aggregate: Union[str, None] = None, + withscores: bool = False, + ) -> ResponseT: + """ + Return the union of multiple sorted sets specified by ``keys``. + ``keys`` can be provided as dictionary of keys and their weights. + Scores will be aggregated based on the ``aggregate``, or SUM if + none is provided. + + For more information see https://redis.io/commands/zunion + """ + return self._zaggregate("ZUNION", None, keys, aggregate, withscores=withscores) + + def zunionstore( + self, + dest: KeyT, + keys: Union[Sequence[KeyT], Mapping[AnyKeyT, float]], + aggregate: Union[str, None] = None, + ) -> ResponseT: + """ + Union multiple sorted sets specified by ``keys`` into + a new sorted set, ``dest``. Scores in the destination will be + aggregated based on the ``aggregate``, or SUM if none is provided. + + For more information see https://redis.io/commands/zunionstore + """ + return self._zaggregate("ZUNIONSTORE", dest, keys, aggregate) + + def zmscore(self, key: KeyT, members: List[str]) -> ResponseT: + """ + Returns the scores associated with the specified members + in the sorted set stored at key. + ``members`` should be a list of the member name. + Return type is a list of score. + If the member does not exist, a None will be returned + in corresponding position. + + For more information see https://redis.io/commands/zmscore + """ + if not members: + raise DataError("ZMSCORE members must be a non-empty list") + pieces = [key] + members + return self.execute_command("ZMSCORE", *pieces) + + def _zaggregate( + self, + command: str, + dest: Union[KeyT, None], + keys: Union[Sequence[KeyT], Mapping[AnyKeyT, float]], + aggregate: Union[str, None] = None, + **options, + ) -> ResponseT: + pieces: list[EncodableT] = [command] + if dest is not None: + pieces.append(dest) + pieces.append(len(keys)) + if isinstance(keys, dict): + keys, weights = keys.keys(), keys.values() + else: + weights = None + pieces.extend(keys) + if weights: + pieces.append(b"WEIGHTS") + pieces.extend(weights) + if aggregate: + if aggregate.upper() in ["SUM", "MIN", "MAX"]: + pieces.append(b"AGGREGATE") + pieces.append(aggregate) + else: + raise DataError("aggregate can be sum, min or max.") + if options.get("withscores", False): + pieces.append(b"WITHSCORES") + return self.execute_command(*pieces, **options) + + +AsyncSortedSetCommands = SortedSetCommands + + +class HyperlogCommands(CommandsProtocol): + """ + Redis commands of HyperLogLogs data type. + see: https://redis.io/topics/data-types-intro#hyperloglogs + """ + + def pfadd(self, name: KeyT, *values: FieldT) -> ResponseT: + """ + Adds the specified elements to the specified HyperLogLog. + + For more information see https://redis.io/commands/pfadd + """ + return self.execute_command("PFADD", name, *values) + + def pfcount(self, *sources: KeyT) -> ResponseT: + """ + Return the approximated cardinality of + the set observed by the HyperLogLog at key(s). + + For more information see https://redis.io/commands/pfcount + """ + return self.execute_command("PFCOUNT", *sources) + + def pfmerge(self, dest: KeyT, *sources: KeyT) -> ResponseT: + """ + Merge N different HyperLogLogs into a single one. + + For more information see https://redis.io/commands/pfmerge + """ + return self.execute_command("PFMERGE", dest, *sources) + + +AsyncHyperlogCommands = HyperlogCommands + + +class HashCommands(CommandsProtocol): + """ + Redis commands for Hash data type. + see: https://redis.io/topics/data-types-intro#redis-hashes + """ + + def hdel(self, name: str, *keys: List) -> Union[Awaitable[int], int]: + """ + Delete ``keys`` from hash ``name`` + + For more information see https://redis.io/commands/hdel + """ + return self.execute_command("HDEL", name, *keys) + + def hexists(self, name: str, key: str) -> Union[Awaitable[bool], bool]: + """ + Returns a boolean indicating if ``key`` exists within hash ``name`` + + For more information see https://redis.io/commands/hexists + """ + return self.execute_command("HEXISTS", name, key) + + def hget( + self, name: str, key: str + ) -> Union[Awaitable[Optional[str]], Optional[str]]: + """ + Return the value of ``key`` within the hash ``name`` + + For more information see https://redis.io/commands/hget + """ + return self.execute_command("HGET", name, key) + + def hgetall(self, name: str) -> Union[Awaitable[dict], dict]: + """ + Return a Python dict of the hash's name/value pairs + + For more information see https://redis.io/commands/hgetall + """ + return self.execute_command("HGETALL", name) + + def hincrby( + self, name: str, key: str, amount: int = 1 + ) -> Union[Awaitable[int], int]: + """ + Increment the value of ``key`` in hash ``name`` by ``amount`` + + For more information see https://redis.io/commands/hincrby + """ + return self.execute_command("HINCRBY", name, key, amount) + + def hincrbyfloat( + self, name: str, key: str, amount: float = 1.0 + ) -> Union[Awaitable[float], float]: + """ + Increment the value of ``key`` in hash ``name`` by floating ``amount`` + + For more information see https://redis.io/commands/hincrbyfloat + """ + return self.execute_command("HINCRBYFLOAT", name, key, amount) + + def hkeys(self, name: str) -> Union[Awaitable[List], List]: + """ + Return the list of keys within hash ``name`` + + For more information see https://redis.io/commands/hkeys + """ + return self.execute_command("HKEYS", name) + + def hlen(self, name: str) -> Union[Awaitable[int], int]: + """ + Return the number of elements in hash ``name`` + + For more information see https://redis.io/commands/hlen + """ + return self.execute_command("HLEN", name) + + def hset( + self, + name: str, + key: Optional[str] = None, + value: Optional[str] = None, + mapping: Optional[dict] = None, + items: Optional[list] = None, + ) -> Union[Awaitable[int], int]: + """ + Set ``key`` to ``value`` within hash ``name``, + ``mapping`` accepts a dict of key/value pairs that will be + added to hash ``name``. + ``items`` accepts a list of key/value pairs that will be + added to hash ``name``. + Returns the number of fields that were added. + + For more information see https://redis.io/commands/hset + """ + if key is None and not mapping and not items: + raise DataError("'hset' with no key value pairs") + items = items or [] + if key is not None: + items.extend((key, value)) + if mapping: + for pair in mapping.items(): + items.extend(pair) + + return self.execute_command("HSET", name, *items) + + def hsetnx(self, name: str, key: str, value: str) -> Union[Awaitable[bool], bool]: + """ + Set ``key`` to ``value`` within hash ``name`` if ``key`` does not + exist. Returns 1 if HSETNX created a field, otherwise 0. + + For more information see https://redis.io/commands/hsetnx + """ + return self.execute_command("HSETNX", name, key, value) + + def hmset(self, name: str, mapping: dict) -> Union[Awaitable[str], str]: + """ + Set key to value within hash ``name`` for each corresponding + key and value from the ``mapping`` dict. + + For more information see https://redis.io/commands/hmset + """ + warnings.warn( + f"{self.__class__.__name__}.hmset() is deprecated. " + f"Use {self.__class__.__name__}.hset() instead.", + DeprecationWarning, + stacklevel=2, + ) + if not mapping: + raise DataError("'hmset' with 'mapping' of length 0") + items = [] + for pair in mapping.items(): + items.extend(pair) + return self.execute_command("HMSET", name, *items) + + def hmget(self, name: str, keys: List, *args: List) -> Union[Awaitable[List], List]: + """ + Returns a list of values ordered identically to ``keys`` + + For more information see https://redis.io/commands/hmget + """ + args = list_or_args(keys, args) + return self.execute_command("HMGET", name, *args) + + def hvals(self, name: str) -> Union[Awaitable[List], List]: + """ + Return the list of values within hash ``name`` + + For more information see https://redis.io/commands/hvals + """ + return self.execute_command("HVALS", name) + + def hstrlen(self, name: str, key: str) -> Union[Awaitable[int], int]: + """ + Return the number of bytes stored in the value of ``key`` + within hash ``name`` + + For more information see https://redis.io/commands/hstrlen + """ + return self.execute_command("HSTRLEN", name, key) + + +AsyncHashCommands = HashCommands + + +class Script: + """ + An executable Lua script object returned by ``register_script`` + """ + + def __init__(self, registered_client: "Redis", script: ScriptTextT): + self.registered_client = registered_client + self.script = script + # Precalculate and store the SHA1 hex digest of the script. + + if isinstance(script, str): + # We need the encoding from the client in order to generate an + # accurate byte representation of the script + try: + encoder = registered_client.connection_pool.get_encoder() + except AttributeError: + # Cluster + encoder = registered_client.get_encoder() + script = encoder.encode(script) + self.sha = hashlib.sha1(script).hexdigest() + + def __call__( + self, + keys: Union[Sequence[KeyT], None] = None, + args: Union[Iterable[EncodableT], None] = None, + client: Union["Redis", None] = None, + ): + """Execute the script, passing any required ``args``""" + keys = keys or [] + args = args or [] + if client is None: + client = self.registered_client + args = tuple(keys) + tuple(args) + # make sure the Redis server knows about the script + from redis.client import Pipeline + + if isinstance(client, Pipeline): + # Make sure the pipeline can register the script before executing. + client.scripts.add(self) + try: + return client.evalsha(self.sha, len(keys), *args) + except NoScriptError: + # Maybe the client is pointed to a different server than the client + # that created this instance? + # Overwrite the sha just in case there was a discrepancy. + self.sha = client.script_load(self.script) + return client.evalsha(self.sha, len(keys), *args) + + +class AsyncScript: + """ + An executable Lua script object returned by ``register_script`` + """ + + def __init__(self, registered_client: "AsyncRedis", script: ScriptTextT): + self.registered_client = registered_client + self.script = script + # Precalculate and store the SHA1 hex digest of the script. + + if isinstance(script, str): + # We need the encoding from the client in order to generate an + # accurate byte representation of the script + try: + encoder = registered_client.connection_pool.get_encoder() + except AttributeError: + # Cluster + encoder = registered_client.get_encoder() + script = encoder.encode(script) + self.sha = hashlib.sha1(script).hexdigest() + + async def __call__( + self, + keys: Union[Sequence[KeyT], None] = None, + args: Union[Iterable[EncodableT], None] = None, + client: Union["AsyncRedis", None] = None, + ): + """Execute the script, passing any required ``args``""" + keys = keys or [] + args = args or [] + if client is None: + client = self.registered_client + args = tuple(keys) + tuple(args) + # make sure the Redis server knows about the script + from redis.asyncio.client import Pipeline + + if isinstance(client, Pipeline): + # Make sure the pipeline can register the script before executing. + client.scripts.add(self) + try: + return await client.evalsha(self.sha, len(keys), *args) + except NoScriptError: + # Maybe the client is pointed to a different server than the client + # that created this instance? + # Overwrite the sha just in case there was a discrepancy. + self.sha = await client.script_load(self.script) + return await client.evalsha(self.sha, len(keys), *args) + + +class PubSubCommands(CommandsProtocol): + """ + Redis PubSub commands. + see https://redis.io/topics/pubsub + """ + + def publish(self, channel: ChannelT, message: EncodableT, **kwargs) -> ResponseT: + """ + Publish ``message`` on ``channel``. + Returns the number of subscribers the message was delivered to. + + For more information see https://redis.io/commands/publish + """ + return self.execute_command("PUBLISH", channel, message, **kwargs) + + def spublish(self, shard_channel: ChannelT, message: EncodableT) -> ResponseT: + """ + Posts a message to the given shard channel. + Returns the number of clients that received the message + + For more information see https://redis.io/commands/spublish + """ + return self.execute_command("SPUBLISH", shard_channel, message) + + def pubsub_channels(self, pattern: PatternT = "*", **kwargs) -> ResponseT: + """ + Return a list of channels that have at least one subscriber + + For more information see https://redis.io/commands/pubsub-channels + """ + return self.execute_command("PUBSUB CHANNELS", pattern, **kwargs) + + def pubsub_shardchannels(self, pattern: PatternT = "*", **kwargs) -> ResponseT: + """ + Return a list of shard_channels that have at least one subscriber + + For more information see https://redis.io/commands/pubsub-shardchannels + """ + return self.execute_command("PUBSUB SHARDCHANNELS", pattern, **kwargs) + + def pubsub_numpat(self, **kwargs) -> ResponseT: + """ + Returns the number of subscriptions to patterns + + For more information see https://redis.io/commands/pubsub-numpat + """ + return self.execute_command("PUBSUB NUMPAT", **kwargs) + + def pubsub_numsub(self, *args: ChannelT, **kwargs) -> ResponseT: + """ + Return a list of (channel, number of subscribers) tuples + for each channel given in ``*args`` + + For more information see https://redis.io/commands/pubsub-numsub + """ + return self.execute_command("PUBSUB NUMSUB", *args, **kwargs) + + def pubsub_shardnumsub(self, *args: ChannelT, **kwargs) -> ResponseT: + """ + Return a list of (shard_channel, number of subscribers) tuples + for each channel given in ``*args`` + + For more information see https://redis.io/commands/pubsub-shardnumsub + """ + return self.execute_command("PUBSUB SHARDNUMSUB", *args, **kwargs) + + +AsyncPubSubCommands = PubSubCommands + + +class ScriptCommands(CommandsProtocol): + """ + Redis Lua script commands. see: + https://redis.com/ebook/part-3-next-steps/chapter-11-scripting-redis-with-lua/ + """ + + def _eval( + self, command: str, script: str, numkeys: int, *keys_and_args: list + ) -> Union[Awaitable[str], str]: + return self.execute_command(command, script, numkeys, *keys_and_args) + + def eval( + self, script: str, numkeys: int, *keys_and_args: list + ) -> Union[Awaitable[str], str]: + """ + Execute the Lua ``script``, specifying the ``numkeys`` the script + will touch and the key names and argument values in ``keys_and_args``. + Returns the result of the script. + + In practice, use the object returned by ``register_script``. This + function exists purely for Redis API completion. + + For more information see https://redis.io/commands/eval + """ + return self._eval("EVAL", script, numkeys, *keys_and_args) + + def eval_ro( + self, script: str, numkeys: int, *keys_and_args: list + ) -> Union[Awaitable[str], str]: + """ + The read-only variant of the EVAL command + + Execute the read-only Lua ``script`` specifying the ``numkeys`` the script + will touch and the key names and argument values in ``keys_and_args``. + Returns the result of the script. + + For more information see https://redis.io/commands/eval_ro + """ + return self._eval("EVAL_RO", script, numkeys, *keys_and_args) + + def _evalsha( + self, command: str, sha: str, numkeys: int, *keys_and_args: list + ) -> Union[Awaitable[str], str]: + return self.execute_command(command, sha, numkeys, *keys_and_args) + + def evalsha( + self, sha: str, numkeys: int, *keys_and_args: list + ) -> Union[Awaitable[str], str]: + """ + Use the ``sha`` to execute a Lua script already registered via EVAL + or SCRIPT LOAD. Specify the ``numkeys`` the script will touch and the + key names and argument values in ``keys_and_args``. Returns the result + of the script. + + In practice, use the object returned by ``register_script``. This + function exists purely for Redis API completion. + + For more information see https://redis.io/commands/evalsha + """ + return self._evalsha("EVALSHA", sha, numkeys, *keys_and_args) + + def evalsha_ro( + self, sha: str, numkeys: int, *keys_and_args: list + ) -> Union[Awaitable[str], str]: + """ + The read-only variant of the EVALSHA command + + Use the ``sha`` to execute a read-only Lua script already registered via EVAL + or SCRIPT LOAD. Specify the ``numkeys`` the script will touch and the + key names and argument values in ``keys_and_args``. Returns the result + of the script. + + For more information see https://redis.io/commands/evalsha_ro + """ + return self._evalsha("EVALSHA_RO", sha, numkeys, *keys_and_args) + + def script_exists(self, *args: str) -> ResponseT: + """ + Check if a script exists in the script cache by specifying the SHAs of + each script as ``args``. Returns a list of boolean values indicating if + if each already script exists in the cache. + + For more information see https://redis.io/commands/script-exists + """ + return self.execute_command("SCRIPT EXISTS", *args) + + def script_debug(self, *args) -> None: + raise NotImplementedError( + "SCRIPT DEBUG is intentionally not implemented in the client." + ) + + def script_flush( + self, sync_type: Union[Literal["SYNC"], Literal["ASYNC"]] = None + ) -> ResponseT: + """Flush all scripts from the script cache. + + ``sync_type`` is by default SYNC (synchronous) but it can also be + ASYNC. + + For more information see https://redis.io/commands/script-flush + """ + + # Redis pre 6 had no sync_type. + if sync_type not in ["SYNC", "ASYNC", None]: + raise DataError( + "SCRIPT FLUSH defaults to SYNC in redis > 6.2, or " + "accepts SYNC/ASYNC. For older versions, " + "of redis leave as None." + ) + if sync_type is None: + pieces = [] + else: + pieces = [sync_type] + return self.execute_command("SCRIPT FLUSH", *pieces) + + def script_kill(self) -> ResponseT: + """ + Kill the currently executing Lua script + + For more information see https://redis.io/commands/script-kill + """ + return self.execute_command("SCRIPT KILL") + + def script_load(self, script: ScriptTextT) -> ResponseT: + """ + Load a Lua ``script`` into the script cache. Returns the SHA. + + For more information see https://redis.io/commands/script-load + """ + return self.execute_command("SCRIPT LOAD", script) + + def register_script(self: "Redis", script: ScriptTextT) -> Script: + """ + Register a Lua ``script`` specifying the ``keys`` it will touch. + Returns a Script object that is callable and hides the complexity of + deal with scripts, keys, and shas. This is the preferred way to work + with Lua scripts. + """ + return Script(self, script) + + +class AsyncScriptCommands(ScriptCommands): + async def script_debug(self, *args) -> None: + return super().script_debug() + + def register_script(self: "AsyncRedis", script: ScriptTextT) -> AsyncScript: + """ + Register a Lua ``script`` specifying the ``keys`` it will touch. + Returns a Script object that is callable and hides the complexity of + deal with scripts, keys, and shas. This is the preferred way to work + with Lua scripts. + """ + return AsyncScript(self, script) + + +class GeoCommands(CommandsProtocol): + """ + Redis Geospatial commands. + see: https://redis.com/redis-best-practices/indexing-patterns/geospatial/ + """ + + def geoadd( + self, + name: KeyT, + values: Sequence[EncodableT], + nx: bool = False, + xx: bool = False, + ch: bool = False, + ) -> ResponseT: + """ + Add the specified geospatial items to the specified key identified + by the ``name`` argument. The Geospatial items are given as ordered + members of the ``values`` argument, each item or place is formed by + the triad longitude, latitude and name. + + Note: You can use ZREM to remove elements. + + ``nx`` forces ZADD to only create new elements and not to update + scores for elements that already exist. + + ``xx`` forces ZADD to only update scores of elements that already + exist. New elements will not be added. + + ``ch`` modifies the return value to be the numbers of elements changed. + Changed elements include new elements that were added and elements + whose scores changed. + + For more information see https://redis.io/commands/geoadd + """ + if nx and xx: + raise DataError("GEOADD allows either 'nx' or 'xx', not both") + if len(values) % 3 != 0: + raise DataError("GEOADD requires places with lon, lat and name values") + pieces = [name] + if nx: + pieces.append("NX") + if xx: + pieces.append("XX") + if ch: + pieces.append("CH") + pieces.extend(values) + return self.execute_command("GEOADD", *pieces) + + def geodist( + self, name: KeyT, place1: FieldT, place2: FieldT, unit: Union[str, None] = None + ) -> ResponseT: + """ + Return the distance between ``place1`` and ``place2`` members of the + ``name`` key. + The units must be one of the following : m, km mi, ft. By default + meters are used. + + For more information see https://redis.io/commands/geodist + """ + pieces: list[EncodableT] = [name, place1, place2] + if unit and unit not in ("m", "km", "mi", "ft"): + raise DataError("GEODIST invalid unit") + elif unit: + pieces.append(unit) + return self.execute_command("GEODIST", *pieces) + + def geohash(self, name: KeyT, *values: FieldT) -> ResponseT: + """ + Return the geo hash string for each item of ``values`` members of + the specified key identified by the ``name`` argument. + + For more information see https://redis.io/commands/geohash + """ + return self.execute_command("GEOHASH", name, *values) + + def geopos(self, name: KeyT, *values: FieldT) -> ResponseT: + """ + Return the positions of each item of ``values`` as members of + the specified key identified by the ``name`` argument. Each position + is represented by the pairs lon and lat. + + For more information see https://redis.io/commands/geopos + """ + return self.execute_command("GEOPOS", name, *values) + + def georadius( + self, + name: KeyT, + longitude: float, + latitude: float, + radius: float, + unit: Union[str, None] = None, + withdist: bool = False, + withcoord: bool = False, + withhash: bool = False, + count: Union[int, None] = None, + sort: Union[str, None] = None, + store: Union[KeyT, None] = None, + store_dist: Union[KeyT, None] = None, + any: bool = False, + ) -> ResponseT: + """ + Return the members of the specified key identified by the + ``name`` argument which are within the borders of the area specified + with the ``latitude`` and ``longitude`` location and the maximum + distance from the center specified by the ``radius`` value. + + The units must be one of the following : m, km mi, ft. By default + + ``withdist`` indicates to return the distances of each place. + + ``withcoord`` indicates to return the latitude and longitude of + each place. + + ``withhash`` indicates to return the geohash string of each place. + + ``count`` indicates to return the number of elements up to N. + + ``sort`` indicates to return the places in a sorted way, ASC for + nearest to fairest and DESC for fairest to nearest. + + ``store`` indicates to save the places names in a sorted set named + with a specific key, each element of the destination sorted set is + populated with the score got from the original geo sorted set. + + ``store_dist`` indicates to save the places names in a sorted set + named with a specific key, instead of ``store`` the sorted set + destination score is set with the distance. + + For more information see https://redis.io/commands/georadius + """ + return self._georadiusgeneric( + "GEORADIUS", + name, + longitude, + latitude, + radius, + unit=unit, + withdist=withdist, + withcoord=withcoord, + withhash=withhash, + count=count, + sort=sort, + store=store, + store_dist=store_dist, + any=any, + ) + + def georadiusbymember( + self, + name: KeyT, + member: FieldT, + radius: float, + unit: Union[str, None] = None, + withdist: bool = False, + withcoord: bool = False, + withhash: bool = False, + count: Union[int, None] = None, + sort: Union[str, None] = None, + store: Union[KeyT, None] = None, + store_dist: Union[KeyT, None] = None, + any: bool = False, + ) -> ResponseT: + """ + This command is exactly like ``georadius`` with the sole difference + that instead of taking, as the center of the area to query, a longitude + and latitude value, it takes the name of a member already existing + inside the geospatial index represented by the sorted set. + + For more information see https://redis.io/commands/georadiusbymember + """ + return self._georadiusgeneric( + "GEORADIUSBYMEMBER", + name, + member, + radius, + unit=unit, + withdist=withdist, + withcoord=withcoord, + withhash=withhash, + count=count, + sort=sort, + store=store, + store_dist=store_dist, + any=any, + ) + + def _georadiusgeneric( + self, command: str, *args: EncodableT, **kwargs: Union[EncodableT, None] + ) -> ResponseT: + pieces = list(args) + if kwargs["unit"] and kwargs["unit"] not in ("m", "km", "mi", "ft"): + raise DataError("GEORADIUS invalid unit") + elif kwargs["unit"]: + pieces.append(kwargs["unit"]) + else: + pieces.append("m") + + if kwargs["any"] and kwargs["count"] is None: + raise DataError("``any`` can't be provided without ``count``") + + for arg_name, byte_repr in ( + ("withdist", "WITHDIST"), + ("withcoord", "WITHCOORD"), + ("withhash", "WITHHASH"), + ): + if kwargs[arg_name]: + pieces.append(byte_repr) + + if kwargs["count"] is not None: + pieces.extend(["COUNT", kwargs["count"]]) + if kwargs["any"]: + pieces.append("ANY") + + if kwargs["sort"]: + if kwargs["sort"] == "ASC": + pieces.append("ASC") + elif kwargs["sort"] == "DESC": + pieces.append("DESC") + else: + raise DataError("GEORADIUS invalid sort") + + if kwargs["store"] and kwargs["store_dist"]: + raise DataError("GEORADIUS store and store_dist cant be set together") + + if kwargs["store"]: + pieces.extend([b"STORE", kwargs["store"]]) + + if kwargs["store_dist"]: + pieces.extend([b"STOREDIST", kwargs["store_dist"]]) + + return self.execute_command(command, *pieces, **kwargs) + + def geosearch( + self, + name: KeyT, + member: Union[FieldT, None] = None, + longitude: Union[float, None] = None, + latitude: Union[float, None] = None, + unit: str = "m", + radius: Union[float, None] = None, + width: Union[float, None] = None, + height: Union[float, None] = None, + sort: Union[str, None] = None, + count: Union[int, None] = None, + any: bool = False, + withcoord: bool = False, + withdist: bool = False, + withhash: bool = False, + ) -> ResponseT: + """ + Return the members of specified key identified by the + ``name`` argument, which are within the borders of the + area specified by a given shape. This command extends the + GEORADIUS command, so in addition to searching within circular + areas, it supports searching within rectangular areas. + + This command should be used in place of the deprecated + GEORADIUS and GEORADIUSBYMEMBER commands. + + ``member`` Use the position of the given existing + member in the sorted set. Can't be given with ``longitude`` + and ``latitude``. + + ``longitude`` and ``latitude`` Use the position given by + this coordinates. Can't be given with ``member`` + ``radius`` Similar to GEORADIUS, search inside circular + area according the given radius. Can't be given with + ``height`` and ``width``. + ``height`` and ``width`` Search inside an axis-aligned + rectangle, determined by the given height and width. + Can't be given with ``radius`` + + ``unit`` must be one of the following : m, km, mi, ft. + `m` for meters (the default value), `km` for kilometers, + `mi` for miles and `ft` for feet. + + ``sort`` indicates to return the places in a sorted way, + ASC for nearest to furthest and DESC for furthest to nearest. + + ``count`` limit the results to the first count matching items. + + ``any`` is set to True, the command will return as soon as + enough matches are found. Can't be provided without ``count`` + + ``withdist`` indicates to return the distances of each place. + ``withcoord`` indicates to return the latitude and longitude of + each place. + + ``withhash`` indicates to return the geohash string of each place. + + For more information see https://redis.io/commands/geosearch + """ + + return self._geosearchgeneric( + "GEOSEARCH", + name, + member=member, + longitude=longitude, + latitude=latitude, + unit=unit, + radius=radius, + width=width, + height=height, + sort=sort, + count=count, + any=any, + withcoord=withcoord, + withdist=withdist, + withhash=withhash, + store=None, + store_dist=None, + ) + + def geosearchstore( + self, + dest: KeyT, + name: KeyT, + member: Union[FieldT, None] = None, + longitude: Union[float, None] = None, + latitude: Union[float, None] = None, + unit: str = "m", + radius: Union[float, None] = None, + width: Union[float, None] = None, + height: Union[float, None] = None, + sort: Union[str, None] = None, + count: Union[int, None] = None, + any: bool = False, + storedist: bool = False, + ) -> ResponseT: + """ + This command is like GEOSEARCH, but stores the result in + ``dest``. By default, it stores the results in the destination + sorted set with their geospatial information. + if ``store_dist`` set to True, the command will stores the + items in a sorted set populated with their distance from the + center of the circle or box, as a floating-point number. + + For more information see https://redis.io/commands/geosearchstore + """ + return self._geosearchgeneric( + "GEOSEARCHSTORE", + dest, + name, + member=member, + longitude=longitude, + latitude=latitude, + unit=unit, + radius=radius, + width=width, + height=height, + sort=sort, + count=count, + any=any, + withcoord=None, + withdist=None, + withhash=None, + store=None, + store_dist=storedist, + ) + + def _geosearchgeneric( + self, command: str, *args: EncodableT, **kwargs: Union[EncodableT, None] + ) -> ResponseT: + pieces = list(args) + + # FROMMEMBER or FROMLONLAT + if kwargs["member"] is None: + if kwargs["longitude"] is None or kwargs["latitude"] is None: + raise DataError("GEOSEARCH must have member or longitude and latitude") + if kwargs["member"]: + if kwargs["longitude"] or kwargs["latitude"]: + raise DataError( + "GEOSEARCH member and longitude or latitude cant be set together" + ) + pieces.extend([b"FROMMEMBER", kwargs["member"]]) + if kwargs["longitude"] is not None and kwargs["latitude"] is not None: + pieces.extend([b"FROMLONLAT", kwargs["longitude"], kwargs["latitude"]]) + + # BYRADIUS or BYBOX + if kwargs["radius"] is None: + if kwargs["width"] is None or kwargs["height"] is None: + raise DataError("GEOSEARCH must have radius or width and height") + if kwargs["unit"] is None: + raise DataError("GEOSEARCH must have unit") + if kwargs["unit"].lower() not in ("m", "km", "mi", "ft"): + raise DataError("GEOSEARCH invalid unit") + if kwargs["radius"]: + if kwargs["width"] or kwargs["height"]: + raise DataError( + "GEOSEARCH radius and width or height cant be set together" + ) + pieces.extend([b"BYRADIUS", kwargs["radius"], kwargs["unit"]]) + if kwargs["width"] and kwargs["height"]: + pieces.extend([b"BYBOX", kwargs["width"], kwargs["height"], kwargs["unit"]]) + + # sort + if kwargs["sort"]: + if kwargs["sort"].upper() == "ASC": + pieces.append(b"ASC") + elif kwargs["sort"].upper() == "DESC": + pieces.append(b"DESC") + else: + raise DataError("GEOSEARCH invalid sort") + + # count any + if kwargs["count"]: + pieces.extend([b"COUNT", kwargs["count"]]) + if kwargs["any"]: + pieces.append(b"ANY") + elif kwargs["any"]: + raise DataError("GEOSEARCH ``any`` can't be provided without count") + + # other properties + for arg_name, byte_repr in ( + ("withdist", b"WITHDIST"), + ("withcoord", b"WITHCOORD"), + ("withhash", b"WITHHASH"), + ("store_dist", b"STOREDIST"), + ): + if kwargs[arg_name]: + pieces.append(byte_repr) + + return self.execute_command(command, *pieces, **kwargs) + + +AsyncGeoCommands = GeoCommands + + +class ModuleCommands(CommandsProtocol): + """ + Redis Module commands. + see: https://redis.io/topics/modules-intro + """ + + def module_load(self, path, *args) -> ResponseT: + """ + Loads the module from ``path``. + Passes all ``*args`` to the module, during loading. + Raises ``ModuleError`` if a module is not found at ``path``. + + For more information see https://redis.io/commands/module-load + """ + return self.execute_command("MODULE LOAD", path, *args) + + def module_loadex( + self, + path: str, + options: Optional[List[str]] = None, + args: Optional[List[str]] = None, + ) -> ResponseT: + """ + Loads a module from a dynamic library at runtime with configuration directives. + + For more information see https://redis.io/commands/module-loadex + """ + pieces = [] + if options is not None: + pieces.append("CONFIG") + pieces.extend(options) + if args is not None: + pieces.append("ARGS") + pieces.extend(args) + + return self.execute_command("MODULE LOADEX", path, *pieces) + + def module_unload(self, name) -> ResponseT: + """ + Unloads the module ``name``. + Raises ``ModuleError`` if ``name`` is not in loaded modules. + + For more information see https://redis.io/commands/module-unload + """ + return self.execute_command("MODULE UNLOAD", name) + + def module_list(self) -> ResponseT: + """ + Returns a list of dictionaries containing the name and version of + all loaded modules. + + For more information see https://redis.io/commands/module-list + """ + return self.execute_command("MODULE LIST") + + def command_info(self) -> None: + raise NotImplementedError( + "COMMAND INFO is intentionally not implemented in the client." + ) + + def command_count(self) -> ResponseT: + return self.execute_command("COMMAND COUNT") + + def command_getkeys(self, *args) -> ResponseT: + return self.execute_command("COMMAND GETKEYS", *args) + + def command(self) -> ResponseT: + return self.execute_command("COMMAND") + + +class Script: + """ + An executable Lua script object returned by ``register_script`` + """ + + def __init__(self, registered_client, script): + self.registered_client = registered_client + self.script = script + # Precalculate and store the SHA1 hex digest of the script. + + if isinstance(script, str): + # We need the encoding from the client in order to generate an + # accurate byte representation of the script + encoder = self.get_encoder() + script = encoder.encode(script) + self.sha = hashlib.sha1(script).hexdigest() + + def __call__(self, keys=[], args=[], client=None): + "Execute the script, passing any required ``args``" + if client is None: + client = self.registered_client + args = tuple(keys) + tuple(args) + # make sure the Redis server knows about the script + from redis.client import Pipeline + + if isinstance(client, Pipeline): + # Make sure the pipeline can register the script before executing. + client.scripts.add(self) + try: + return client.evalsha(self.sha, len(keys), *args) + except NoScriptError: + # Maybe the client is pointed to a different server than the client + # that created this instance? + # Overwrite the sha just in case there was a discrepancy. + self.sha = client.script_load(self.script) + return client.evalsha(self.sha, len(keys), *args) + + def get_encoder(self): + """Get the encoder to encode string scripts into bytes.""" + try: + return self.registered_client.get_encoder() + except AttributeError: + # DEPRECATED + # In version <=4.1.2, this was the code we used to get the encoder. + # However, after 4.1.2 we added support for scripting in clustered + # redis. ClusteredRedis doesn't have a `.connection_pool` attribute + # so we changed the Script class to use + # `self.registered_client.get_encoder` (see above). + # However, that is technically a breaking change, as consumers who + # use Scripts directly might inject a `registered_client` that + # doesn't have a `.get_encoder` field. This try/except prevents us + # from breaking backward-compatibility. Ideally, it would be + # removed in the next major release. + return self.registered_client.connection_pool.get_encoder() + + +class AsyncModuleCommands(ModuleCommands): + async def command_info(self) -> None: + return super().command_info() + + +class ClusterCommands(CommandsProtocol): + """ + Class for Redis Cluster commands + """ + + def cluster(self, cluster_arg, *args, **kwargs) -> ResponseT: + return self.execute_command(f"CLUSTER {cluster_arg.upper()}", *args, **kwargs) + + def readwrite(self, **kwargs) -> ResponseT: + """ + Disables read queries for a connection to a Redis Cluster slave node. + + For more information see https://redis.io/commands/readwrite + """ + return self.execute_command("READWRITE", **kwargs) + + def readonly(self, **kwargs) -> ResponseT: + """ + Enables read queries for a connection to a Redis Cluster replica node. + + For more information see https://redis.io/commands/readonly + """ + return self.execute_command("READONLY", **kwargs) + + +AsyncClusterCommands = ClusterCommands + + +class FunctionCommands: + """ + Redis Function commands + """ + + def function_load( + self, code: str, replace: Optional[bool] = False + ) -> Union[Awaitable[str], str]: + """ + Load a library to Redis. + :param code: the source code (must start with + Shebang statement that provides a metadata about the library) + :param replace: changes the behavior to overwrite the existing library + with the new contents. + Return the library name that was loaded. + + For more information see https://redis.io/commands/function-load + """ + pieces = ["REPLACE"] if replace else [] + pieces.append(code) + return self.execute_command("FUNCTION LOAD", *pieces) + + def function_delete(self, library: str) -> Union[Awaitable[str], str]: + """ + Delete the library called ``library`` and all its functions. + + For more information see https://redis.io/commands/function-delete + """ + return self.execute_command("FUNCTION DELETE", library) + + def function_flush(self, mode: str = "SYNC") -> Union[Awaitable[str], str]: + """ + Deletes all the libraries. + + For more information see https://redis.io/commands/function-flush + """ + return self.execute_command("FUNCTION FLUSH", mode) + + def function_list( + self, library: Optional[str] = "*", withcode: Optional[bool] = False + ) -> Union[Awaitable[List], List]: + """ + Return information about the functions and libraries. + :param library: pecify a pattern for matching library names + :param withcode: cause the server to include the libraries source + implementation in the reply + """ + args = ["LIBRARYNAME", library] + if withcode: + args.append("WITHCODE") + return self.execute_command("FUNCTION LIST", *args) + + def _fcall( + self, command: str, function, numkeys: int, *keys_and_args: Optional[List] + ) -> Union[Awaitable[str], str]: + return self.execute_command(command, function, numkeys, *keys_and_args) + + def fcall( + self, function, numkeys: int, *keys_and_args: Optional[List] + ) -> Union[Awaitable[str], str]: + """ + Invoke a function. + + For more information see https://redis.io/commands/fcall + """ + return self._fcall("FCALL", function, numkeys, *keys_and_args) + + def fcall_ro( + self, function, numkeys: int, *keys_and_args: Optional[List] + ) -> Union[Awaitable[str], str]: + """ + This is a read-only variant of the FCALL command that cannot + execute commands that modify data. + + For more information see https://redis.io/commands/fcal_ro + """ + return self._fcall("FCALL_RO", function, numkeys, *keys_and_args) + + def function_dump(self) -> Union[Awaitable[str], str]: + """ + Return the serialized payload of loaded libraries. + + For more information see https://redis.io/commands/function-dump + """ + from redis.client import NEVER_DECODE + + options = {} + options[NEVER_DECODE] = [] + + return self.execute_command("FUNCTION DUMP", **options) + + def function_restore( + self, payload: str, policy: Optional[str] = "APPEND" + ) -> Union[Awaitable[str], str]: + """ + Restore libraries from the serialized ``payload``. + You can use the optional policy argument to provide a policy + for handling existing libraries. + + For more information see https://redis.io/commands/function-restore + """ + return self.execute_command("FUNCTION RESTORE", payload, policy) + + def function_kill(self) -> Union[Awaitable[str], str]: + """ + Kill a function that is currently executing. + + For more information see https://redis.io/commands/function-kill + """ + return self.execute_command("FUNCTION KILL") + + def function_stats(self) -> Union[Awaitable[List], List]: + """ + Return information about the function that's currently running + and information about the available execution engines. + + For more information see https://redis.io/commands/function-stats + """ + return self.execute_command("FUNCTION STATS") + + +AsyncFunctionCommands = FunctionCommands + + +class GearsCommands: + def tfunction_load( + self, lib_code: str, replace: bool = False, config: Union[str, None] = None + ) -> ResponseT: + """ + Load a new library to RedisGears. + + ``lib_code`` - the library code. + ``config`` - a string representation of a JSON object + that will be provided to the library on load time, + for more information refer to + https://github.com/RedisGears/RedisGears/blob/master/docs/function_advance_topics.md#library-configuration + ``replace`` - an optional argument, instructs RedisGears to replace the + function if its already exists + + For more information see https://redis.io/commands/tfunction-load/ + """ + pieces = [] + if replace: + pieces.append("REPLACE") + if config is not None: + pieces.extend(["CONFIG", config]) + pieces.append(lib_code) + return self.execute_command("TFUNCTION LOAD", *pieces) + + def tfunction_delete(self, lib_name: str) -> ResponseT: + """ + Delete a library from RedisGears. + + ``lib_name`` the library name to delete. + + For more information see https://redis.io/commands/tfunction-delete/ + """ + return self.execute_command("TFUNCTION DELETE", lib_name) + + def tfunction_list( + self, + with_code: bool = False, + verbose: int = 0, + lib_name: Union[str, None] = None, + ) -> ResponseT: + """ + List the functions with additional information about each function. + + ``with_code`` Show libraries code. + ``verbose`` output verbosity level, higher number will increase verbosity level + ``lib_name`` specifying a library name (can be used multiple times to show multiple libraries in a single command) # noqa + + For more information see https://redis.io/commands/tfunction-list/ + """ + pieces = [] + if with_code: + pieces.append("WITHCODE") + if verbose >= 1 and verbose <= 3: + pieces.append("v" * verbose) + else: + raise DataError("verbose can be 1, 2 or 3") + if lib_name is not None: + pieces.append("LIBRARY") + pieces.append(lib_name) + + return self.execute_command("TFUNCTION LIST", *pieces) + + def _tfcall( + self, + lib_name: str, + func_name: str, + keys: KeysT = None, + _async: bool = False, + *args: List, + ) -> ResponseT: + pieces = [f"{lib_name}.{func_name}"] + if keys is not None: + pieces.append(len(keys)) + pieces.extend(keys) + else: + pieces.append(0) + if args is not None: + pieces.extend(args) + if _async: + return self.execute_command("TFCALLASYNC", *pieces) + return self.execute_command("TFCALL", *pieces) + + def tfcall( + self, + lib_name: str, + func_name: str, + keys: KeysT = None, + *args: List, + ) -> ResponseT: + """ + Invoke a function. + + ``lib_name`` - the library name contains the function. + ``func_name`` - the function name to run. + ``keys`` - the keys that will be touched by the function. + ``args`` - Additional argument to pass to the function. + + For more information see https://redis.io/commands/tfcall/ + """ + return self._tfcall(lib_name, func_name, keys, False, *args) + + def tfcall_async( + self, + lib_name: str, + func_name: str, + keys: KeysT = None, + *args: List, + ) -> ResponseT: + """ + Invoke an async function (coroutine). + + ``lib_name`` - the library name contains the function. + ``func_name`` - the function name to run. + ``keys`` - the keys that will be touched by the function. + ``args`` - Additional argument to pass to the function. + + For more information see https://redis.io/commands/tfcall/ + """ + return self._tfcall(lib_name, func_name, keys, True, *args) + + +AsyncGearsCommands = GearsCommands + + +class DataAccessCommands( + BasicKeyCommands, + HyperlogCommands, + HashCommands, + GeoCommands, + ListCommands, + ScanCommands, + SetCommands, + StreamCommands, + SortedSetCommands, +): + """ + A class containing all of the implemented data access redis commands. + This class is to be used as a mixin for synchronous Redis clients. + """ + + +class AsyncDataAccessCommands( + AsyncBasicKeyCommands, + AsyncHyperlogCommands, + AsyncHashCommands, + AsyncGeoCommands, + AsyncListCommands, + AsyncScanCommands, + AsyncSetCommands, + AsyncStreamCommands, + AsyncSortedSetCommands, +): + """ + A class containing all of the implemented data access redis commands. + This class is to be used as a mixin for asynchronous Redis clients. + """ + + +class CoreCommands( + ACLCommands, + ClusterCommands, + DataAccessCommands, + ManagementCommands, + ModuleCommands, + PubSubCommands, + ScriptCommands, + FunctionCommands, + GearsCommands, +): + """ + A class containing all of the implemented redis commands. This class is + to be used as a mixin for synchronous Redis clients. + """ + + +class AsyncCoreCommands( + AsyncACLCommands, + AsyncClusterCommands, + AsyncDataAccessCommands, + AsyncManagementCommands, + AsyncModuleCommands, + AsyncPubSubCommands, + AsyncScriptCommands, + AsyncFunctionCommands, + AsyncGearsCommands, +): + """ + A class containing all of the implemented redis commands. This class is + to be used as a mixin for asynchronous Redis clients. + """ diff --git a/.venv/Lib/site-packages/redis/commands/graph/__init__.py b/.venv/Lib/site-packages/redis/commands/graph/__init__.py new file mode 100644 index 00000000..ffaf1fb4 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/graph/__init__.py @@ -0,0 +1,263 @@ +import warnings + +from ..helpers import quote_string, random_string, stringify_param_value +from .commands import AsyncGraphCommands, GraphCommands +from .edge import Edge # noqa +from .node import Node # noqa +from .path import Path # noqa + +DB_LABELS = "DB.LABELS" +DB_RAELATIONSHIPTYPES = "DB.RELATIONSHIPTYPES" +DB_PROPERTYKEYS = "DB.PROPERTYKEYS" + + +class Graph(GraphCommands): + """ + Graph, collection of nodes and edges. + """ + + def __init__(self, client, name=random_string()): + """ + Create a new graph. + """ + warnings.warn( + DeprecationWarning( + "RedisGraph support is deprecated as of Redis Stack 7.2 \ + (https://redis.com/blog/redisgraph-eol/)" + ) + ) + self.NAME = name # Graph key + self.client = client + self.execute_command = client.execute_command + + self.nodes = {} + self.edges = [] + self._labels = [] # List of node labels. + self._properties = [] # List of properties. + self._relationship_types = [] # List of relation types. + self.version = 0 # Graph version + + @property + def name(self): + return self.NAME + + def _clear_schema(self): + self._labels = [] + self._properties = [] + self._relationship_types = [] + + def _refresh_schema(self): + self._clear_schema() + self._refresh_labels() + self._refresh_relations() + self._refresh_attributes() + + def _refresh_labels(self): + lbls = self.labels() + + # Unpack data. + self._labels = [l[0] for _, l in enumerate(lbls)] + + def _refresh_relations(self): + rels = self.relationship_types() + + # Unpack data. + self._relationship_types = [r[0] for _, r in enumerate(rels)] + + def _refresh_attributes(self): + props = self.property_keys() + + # Unpack data. + self._properties = [p[0] for _, p in enumerate(props)] + + def get_label(self, idx): + """ + Returns a label by it's index + + Args: + + idx: + The index of the label + """ + try: + label = self._labels[idx] + except IndexError: + # Refresh labels. + self._refresh_labels() + label = self._labels[idx] + return label + + def get_relation(self, idx): + """ + Returns a relationship type by it's index + + Args: + + idx: + The index of the relation + """ + try: + relationship_type = self._relationship_types[idx] + except IndexError: + # Refresh relationship types. + self._refresh_relations() + relationship_type = self._relationship_types[idx] + return relationship_type + + def get_property(self, idx): + """ + Returns a property by it's index + + Args: + + idx: + The index of the property + """ + try: + p = self._properties[idx] + except IndexError: + # Refresh properties. + self._refresh_attributes() + p = self._properties[idx] + return p + + def add_node(self, node): + """ + Adds a node to the graph. + """ + if node.alias is None: + node.alias = random_string() + self.nodes[node.alias] = node + + def add_edge(self, edge): + """ + Adds an edge to the graph. + """ + if not (self.nodes[edge.src_node.alias] and self.nodes[edge.dest_node.alias]): + raise AssertionError("Both edge's end must be in the graph") + + self.edges.append(edge) + + def _build_params_header(self, params): + if params is None: + return "" + if not isinstance(params, dict): + raise TypeError("'params' must be a dict") + # Header starts with "CYPHER" + params_header = "CYPHER " + for key, value in params.items(): + params_header += str(key) + "=" + stringify_param_value(value) + " " + return params_header + + # Procedures. + def call_procedure(self, procedure, *args, read_only=False, **kwagrs): + args = [quote_string(arg) for arg in args] + q = f"CALL {procedure}({','.join(args)})" + + y = kwagrs.get("y", None) + if y is not None: + q += f"YIELD {','.join(y)}" + + return self.query(q, read_only=read_only) + + def labels(self): + return self.call_procedure(DB_LABELS, read_only=True).result_set + + def relationship_types(self): + return self.call_procedure(DB_RAELATIONSHIPTYPES, read_only=True).result_set + + def property_keys(self): + return self.call_procedure(DB_PROPERTYKEYS, read_only=True).result_set + + +class AsyncGraph(Graph, AsyncGraphCommands): + """Async version for Graph""" + + async def _refresh_labels(self): + lbls = await self.labels() + + # Unpack data. + self._labels = [l[0] for _, l in enumerate(lbls)] + + async def _refresh_attributes(self): + props = await self.property_keys() + + # Unpack data. + self._properties = [p[0] for _, p in enumerate(props)] + + async def _refresh_relations(self): + rels = await self.relationship_types() + + # Unpack data. + self._relationship_types = [r[0] for _, r in enumerate(rels)] + + async def get_label(self, idx): + """ + Returns a label by it's index + + Args: + + idx: + The index of the label + """ + try: + label = self._labels[idx] + except IndexError: + # Refresh labels. + await self._refresh_labels() + label = self._labels[idx] + return label + + async def get_property(self, idx): + """ + Returns a property by it's index + + Args: + + idx: + The index of the property + """ + try: + p = self._properties[idx] + except IndexError: + # Refresh properties. + await self._refresh_attributes() + p = self._properties[idx] + return p + + async def get_relation(self, idx): + """ + Returns a relationship type by it's index + + Args: + + idx: + The index of the relation + """ + try: + relationship_type = self._relationship_types[idx] + except IndexError: + # Refresh relationship types. + await self._refresh_relations() + relationship_type = self._relationship_types[idx] + return relationship_type + + async def call_procedure(self, procedure, *args, read_only=False, **kwagrs): + args = [quote_string(arg) for arg in args] + q = f"CALL {procedure}({','.join(args)})" + + y = kwagrs.get("y", None) + if y is not None: + f"YIELD {','.join(y)}" + return await self.query(q, read_only=read_only) + + async def labels(self): + return ((await self.call_procedure(DB_LABELS, read_only=True))).result_set + + async def property_keys(self): + return (await self.call_procedure(DB_PROPERTYKEYS, read_only=True)).result_set + + async def relationship_types(self): + return ( + await self.call_procedure(DB_RAELATIONSHIPTYPES, read_only=True) + ).result_set diff --git a/.venv/Lib/site-packages/redis/commands/graph/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/graph/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d83a08f0d84d8a6413f8b408b24bd01e4787c83b GIT binary patch literal 13132 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 Lzt|uP)zJR|A(tK6 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/graph/__pycache__/commands.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/graph/__pycache__/commands.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..adee1ba256bf7df845c68f3f706a34d383663fdb GIT binary patch literal 13621 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/graph/__pycache__/exceptions.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/graph/__pycache__/exceptions.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a40688074af844f093ac83fd6cd3c90718fc7410 GIT binary patch literal 640 zcmZ`#J5K^Z5S~3SqLJ8`XkmO-6hf^rRvImo!dF2qZjRj%FLHOdi$slu1&I{)`U^D1 z+W%s%^$%dMvT}w4EY#WTH{Z^C=P8>V1(Mt8S3D*C&X2wf^+;!d$UQi)2^yN91;S$r z;Dv4?C83=?$fZ=@z*_Vkoe3iMfIv}DaQ-^4*AB8)<4ZONK*|<FttDO|EKda5x zF5`@pe(2Ywyqf>-Px*cbk7Tn1H}Ez&(@Niswdi!n0L5IIONCy5QpTfF29Z9mG9Q!j z?A)s+9+RQiXD}nA%rFD*rwhDxyGU>|IBiD^&9>n;B>9|Lq@|4vwx3kv34c0#Wmc0} g*339Lx^0$;v{OQew&Muu@Eaa3KiK;DhpSuq8^~3d(EtDd literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/graph/__pycache__/execution_plan.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/graph/__pycache__/execution_plan.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3e3b4fff28832b85d91b2f2dd33c1b2f6a43f1ed GIT binary patch literal 10162 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/graph/__pycache__/path.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/graph/__pycache__/path.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..63e271758e2da8c6be6179f37dca420185cbd342 GIT binary patch literal 4708 zcmdT{U2GHC6~5!Kor&#u92+N)A2QjJA8$y2h4crqP!uS;+sa)vR9j_(M#gstW@9_t znd}zhv{8jrvx?Ldu}WBhno0`=(Mq&x)u&2rRjIEYWNEFDA|X|M*f*oJFL`OtxnnyS zo3yL4FTHWTx#!$F_nyCd?wMb-wfP9NANTxDQzSzEhD5EotDViSLT8mwLWMb!7N!LO z`>r`xTAUUI;v(k=6>kvge&8bHG5p(Y+D$!EBIQ6~9zcnD0b6McppQy`e%cBc zpgzDh>IV$c0H93U07Eng*iK~-F=V;lP8gSyVr_kRqVh;@{t{r77^pstp zv#4XHYxkMDY62UBaumJmK%9i>-lT*+F8c3%<`)IZFur` z8SZNN6Z7+0hN=cki;0$7*XAx+9($sP&(l#>MNziCcjov^GD}mL*_rQVFP(oQk$g{| z`Hq&>(ib(R=}8TCof&&y%e+7Ht<=RCJ!NR4^Drp^g3d6Fru0L}Y&s3X>xX7pV*c`> zd2r6y{54Bb)l?>BsA{ea{WVr2QGfkyfF-gK>RKDWf4~e4l|n-mBD7BY>a8aWf1u{U z$Tjak@Sd%2{P647G7F|HB zLgePjEc`ixV2V5v;*T)q#pIl>w z8MYZHyN;Hu8Rf|G4~kOnOUm*uXfKwfbuLj8CCEjo)BTN-yte$qqO`wR60``n%B#?6 zNY&&D20U-h1Y3=rn9CC9vPTPzFu;!+HN;l;2%CXxgOu4Tl z_Z6kSFIqx23VZQG+~i3=&%jj?L)%B$<_zI`hY*@hm>amoP`v+mQBDrdnHaDiRQGEGTPyj+wxp8z)U|fZl$4UB6eXp0sX$gO`2YWX zfrfAJ1-fUaFW6DAnSH2^VGl#0ZhbsNj?5^bxsh8<&^7W1zWNn}-Q%|m!;SI#ABrw0 zDyQI3{GAIot@$}-*=zDr?i(?;9pPBx@Ee=oqcvN4 zvc_eNIgII5RqZO2NPeCTYyt~-Jr1x${tjV0aDR^}50>OXjNyId$ljIlXL95xxes$U z^UL|Qg`Zvj`1+m2yNgfdgGD+1WY6!re$(~qp5ONTG5Xi;KX?DB_b=uGb0NodiX7pQ2o zZttIWJLl$Lh`JGTkVUw>JL>Ws?=|eP=z$8|a|QjvTi$KEjSW%H&ixFmFscpa*R^y? z;iR}sUc}5GZTUi0leRTnez2<@T~0Z+rTri5DA3lbMd8TBeDN(|g5iy{B@Ax~v7Br4 z-JEz~^khz)fS&8Z=$3FYCb2P?VR=|0Gpn&zupuiQVuWr zMEI_--xN|-3ubpUMcLQj1s(kZUnS7&3cN*CVKF!#f$I6-)G0m{t{$j*g6##d9No97 z-crrzU@1CS@NKkrtXy4t)odRqwGUK?)EeYaI9=}OT20?dub(zM221#h70#6d^2*VB zk+pa3^xW++BLfdbGcsZZMhcVVNav@K;ir+|hwZ>BMMer|VDhs_=k3?m&pnNd6eA-Q zk+erY((fHzGwyzHXX5UJ**RS595zG4568{W;bQ3UvuM}7sr!-j^Pjx)^PW$7%-*q5 z@0b}Kd$Pxjjz4d4w*?E6g~^JKL^@YTZ;h_|%;%?;LW5YNwf`D#jJimV#d&d!8NBAZ}2Lk4N?lZ=79|9gs{ht6! z^}mYC>rpDC4k6-guebzHH{>=?_j3`*8}Hf-Z;i``D$V38I8X%`Z6NpKXcb_z56LP3 z2{P27k@R@>R7f3y^&aN|`E3D*>ll)3W8839YyD_nN#t;DF`6Xi}5+<|6`X?F7dwsKGuvG literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/graph/__pycache__/query_result.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/graph/__pycache__/query_result.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ba5a93a507b55510af39597b462c14ef1b2339af GIT binary patch literal 25921 zcmd^o3vgT4mDqa#9tjd(f&{?7K#`J2i64>r(~>NTq$J8T^rPGaQ9?s}PZBK{)GO6N_Yh}u|&Q#m(cAVMl^fTKQU|)t9wCZTvq>bC1EnO)c zjb=LAbME`#eE?eat~QTRf_y0NP+;h*p=kW(FS2+dl?fM^a^G7M_zu=4FoU-Rp zHBC`>D3)UB7!|?4mKZ%@iCAd#TVvJxg(+XQYC4MSQF~QptKERjfDSXDcEB))xt~m62+; zDpJGxBek4|^Kunj73b#yoR6#If?PFM!_{7PM(Qloaf%JRMX|y6Efn$ET*xYjwY@oox{S(amyZuyPpCMI8pcNeA=LSsA^P2^u$F2>=j z|11}aVyVKF@hKss1iMf3lT#d@7>Aq!mq_|F?@GajtV#u*p*TA}rm0a4Pzv|0b<8=J;jh?TWOY^*iH zu(n7E%fJMbqBr(=n8T%vz6Ha!s^xiQ5FJWf1c0^noxeT?%KZY#~%M@Qq)32t;W zS3WvAG09HH(C-`_y*3?<$uaK!Q^V(94v(G>zZ5?8cfvWB{C=*#Z@BMl&LO{sPYn#_ zJo3xg!QsAJijLJ$-ec_rlmDJ08D$;r!&KkrUCetHOn|+ypmq5s*X}$^w|-V zAwbsju>(N3&BJ@(FYiTA0U+mkrEmEBpgKe4(rftq@Nmv4`Ol4<9SR>;5)Oq&29FP( zRbG#tIyF4l7go{^oH~DWcrfRXa`v4)+xNwsT;$-u@j=B;CR`3b-8XU~S0-h6x$m@+ z_w*^Ki4R~q$xv6LuT}xw;1Ny&(99H>qzd2M$!ulS+^{rfB#gY0*(0%e;PuT7Wqnn1 zFX4|=4c4HWQHAY2`Wa!~Dh0K%mbZ|KtZz|3M>c>A%K$84O8}O#r2y@$9bg$-2C$qh z2k2lO0G+H8po?_@bhB=N9@YcU%X$G;uoVD(tPfx%TM4j=tpez0{Qv{Vl7Wc_0RpRL zfepV8ZTYap(Ut7m}`8{!%uw9XXT2%*554QV$)XoD#<1fh+l&?X4oWD4C3 zp&?UfGlVvoLR%novng~7gf^Q(w?b%(DRdizZZUJj=NxB{ zLrBc<*cj55;?R!_@X;{Ah8cQ>8dc(`%M`pR99Mc%um@rmF`voJSl)*mAE>!#DuE;` zJ7X+MUnM2-4NxAEyUER1SWAr>YAlp9F^{cK`io6~bSVth=3zbp) zcX+u&B~${Zs2Q52^JJ6I1GMusMS;DMk z#_~1V&^p^QwayOpXi|QSmW0S;9>4n$%M@f*&?7W98BavV<3P&s5W&7Yg%Au*dVy+C zh!0K3Qalkp`5qX^aGNbxJ}yA+L=?n69>*hRh5Z4K!cLowKLmexl)Z8cDLYpx7p6x> zejg-BHt6usNE2UyB*F}UIqH{o${CoyvT*J8)$bq5IJ!kgHzHAWwyJ*N%a>mgk zI(pVAx@=R{SG&-2yFKk}T(`n22{R)Wt|DXw`W|@hAa91hW;a9YCtABQ>ClLJO+`(8 z4t1@86@{z;h1V~0J&5|mVZLQ+a#&?kr;)#Cc&xgaQJ6Zva(ISLYzRc_5 z5G{lO0C%!e!Me4;w$;G4C3hyUPYmosCiTk_%IQfZZoQdt)QOI|g=?#hP}&j7I(?~Q z4{ICOYTH+9+n2tQsXZvx9z=GQf*rVS+Q(MRmHATJW!46a+EHau7mq^(1gBAv>tCW!6?yl(0byp*?xM z!7MYw{CfEeGefspH9?sPCh&8|kEM>b1 zxH**SpRao0saa_GK9lim6+K&l9k_O9w{HKz)$d*X?!?`RdG~^l@issCc|~BIvX*Tl zAk~-kR^9Qu>sh3sP;Zau?SUYVH#M8xvUT2e8^SZ*%}>@#l?-MCM4})Fh+8kG^Ah3k7GE$;s8Uv{byUzo10q@E8eN1Js&>ZUbMf#6qLH=~hDSSl|C60dGO|JV_YmoP(WFf=ZJ*(wEQ5BAjrE@hm-rw z2%rq>!Pq2dLxjVf`Q#e!9jHQh3BVJ;5X$Ou=fR&>HO%)fRIOX7ibL}@(YtNQcF(cW zFShQ#Um>=>AbJnpAIW%+ir%B^R$WGdSkTE+P%L0?6nkOiC$CGLkg!+k13w0F$&Sy| z_`e5PgtGuhi%TlY*C`d0Qx#R~WxB?Y{`|aY`_iuOHr{PqXCU$u?B`?BS*w~A3n2}c z#3v+YE#>7($(GCKfy*k zMvy99_fpjgr#c6A}>yZgy-3wcIlZxC=M$~s4K*Q>Nx~k9$EF9r+SIwVei7rR%w&u z#C1kadqWXn1fttpmKPodqlH{~zQmjj{kbxPMCB?)O6!$z9m)kI3WUw_c;bdq7pSC@ z&1R%DC0c~W3Mg+7?h3oF@@!QNt}I;yqz1Cp_3xFhRd=mccdgh~&U{#!sopPE?@tY7 zYZ}&Swy)M~U)sGwuUJ+r_x5LMc8fK;Qzx@6ovD-aH!{wqw6p1@p)8$oe7E`{AmPd5cC6(74__e~QiWsDnLTjN^{tq$VaRAB=h5gQ8#<5v+ zY?gK>mBBkNy!*mChi)HAJ3|jD>J|pR-<+w~Dpr6nVJ)kEP#Ks{ymR38fwZ&!VI^!# z%(J4B=1w3!G zSR`dA^(lX6Z2G$NZ!~plXHn&rZg;ECH_IeY^)5SL6xJE$9-}|i0xT&>?kI*OiAlf` zWFUDQk#;r`v&Pbwt+`T6F*?rXm>8Z`@e>dX0-x=uw+=2etvc$`j=HQrm^zl-)V$dD-gOjf`)CQy zJF?!u9oM_A1@^ty)*5?O8+%q>$TYqvHolng9ud7q(&WkdYu5bTtN!klmX&KCZp-+4 zMSpLq{DG%(;rP&-vLmAJI=ow1ehs-FA$`C}FM~$Bmr2*O06{rY0>V!%I%2@Sc zomNF-NNF>q)F@dDDPb$Ms1gA5Np(O(OkQX+u3j1jABH3aCtQc$wjEK(J;_J@OF-tx ze+>X?7^P#^oI~KpMits{!bxpHc_YOOm>>2N=p@~vjLO)CLa2=4{|fR5Uk3oFTxCS% z%HZwZwaV?Qm1KFlw=YwT!19ON5WXD1vaGtp+0HRIwE}4HU|IxakD#APEVIx|V)%cA zGK8Z5P(-CF{A=E(Rd3T`%i^`W+cMtmqIY|Wfo*c3VBjJ1gA02yo+i=Ll(sjS*@wC! zK7zICy^e;ZQ6SZ?AF%QrCIYOc6sS^mppn^_Efii2As1^!Jw!3) z0Bad@5aMsWC<(pE?Zp@Xk#i=ZQ^uLarHk+YAaZQFv`{g8G=3TGMqmI=x-9LIbty+r z}iBMAN(lq>K6h&be`zWMU4ms9kEs^Eg{ zouS)9sj^>!!XP+*ZJ}-POr~O+SOGc{Md1Qk5?^4=*SzX$UL07exO+U~YZra(seVGk zTUY&C7ZXc;EA;Z<-8VD-U7~+isxLKm^BCy%K)Yf$;|Y#GcK;FfR@&4U*t%w~ttUA= z!oxW*q}S;5P3egijm#KRe8xcLn3@F9!7yVvJ95>;G@KG4a_7oolkv;seVNWNmtvFA zgtBiW)Jae2^fft$G%uv+WY9b_B;qlYETAry(4@Pjpjhzj#`hW_Xva-AYOe~6FD}Joe6h`NrwXNVOLB_=TS3N}2AP~__VV2hOV`K!Lfd&cih*Gi@Gb};8E@tM?wdDm-ALQ3&An0)`WFRy z_1E8^#pxM(mM)_<+I;bFZz&Ek)~qGo-ApC$$VYZ96yE|T=eUx{?lr^<;tHQavxb8( zJn5dbe36RVu2XMVzersNl{d@|liXckcF0DLAeFS;laFxoGc$55>7R~YjZa>WtLM9@ z3@Z<}*^N6v99Xy)gUV-erwz`tZh(ebNB}|dIp#VK7n(qSfG1lyhExiXL}j3-LwVBW zwiKFlIm&^P{&gshOnP(2()k|^W;XYVn|ssV!FlG6^IhjV?%VEp_eV^MS-05AY9BOg zU7XG|bchWdY5)HDk@=C8Jt^RQPe4PBJhV0s9ymR>POdrYSDp3ghCLbQUeUQX?c57& z6f>lbtuv7P$&)8=%IXcITtWr3TOW`rl=Hs32<7k z^3{qBHx23sJ>xejgH`RkQ67Vn)+oMarY(8h^i9hmG~4WM!hXG&EFtNp z39ntIrB&ZXbf-M(XeH?$H8iq>H>cI0?l7+-qz9nrH7S3aa1wSvK~LtWbj6VLtTfHH z$m{vwQq$cN8DEF!>rkV~{D1)ZO>7CC8}fgEEx`$T^;KEalovKqZ=r>aL^NRKxUfBe z+Ckj(out)D!1JT&KR)-7{|_U76v^y6A?`Z?L79pnv0~`ck1PhDP*^69!N}Z4F0T;xk)wc5 zQ$h&JAl#?Sd8>TQUcG9sPS><$?At~A_OyL_)>Bz%VMR_!NGJv#3)Q51};Fs5DprafoMqL!P*sC9@hNfB;HekW1{@P=2gON7P59L2PRTs z(t!yG&g2>ck+vL~7#^vGzXw3TU3v%|+20c4D#WFv%sX(%5y{Dr!yZ+$WrdB<{F&RO zup_G2GhZcEv@X?&6?;~=OvOR5;$W)eVc~-{6r0FYw1Nl4ueU%kYUD@SqidFeVYGyG z=Tx{&uY})6(tP6exi5Fmf*`;`VT%x9c19G}s_+XR5WEkCRHq;&3K??r8(PV*=&25<aWFcac8@2}31`I)zyg3B z5U?7Vz1qixQEp-?aYKI}ObOkOO%FoyISOyr?7sbC#?vf%nisFFdhp)Y1}p6EK`uPG zhAs3Etclc&<#kZF>$X#t!pLGoFRfmrNDhM>sl5`VAD}TX^EgM{I!P#j2`4SRA+q6m zN{5u;!iEDPPQ}J?%Y}DNc)WAMzXCuf?D6LyM88MLUtxFwNA6WfFh@PCYDCfO2q;() z!ubs-I1;Iu)Xalm{lduaM}9Z5WRnEDrKs4jbFE?TYQx?YA=B`J*zm&rKC$6&CitQl zd@=2nA2>Yq)}!!NaO(!OgY2N3IF2gm;jqy&`5PAe!+`mWuj zm64v}wFF7972AiNbnA=oz~!7@TS$nWmb9nkqcdsyF$skbB^9S) zKH_X~HJfg`1NlEt%K+X&C%ev)dn(dx0l0qxb_ytYNs4#L;siE$`Fl{%)qf53<($KP zM+b+`jrI);3=Z%=fgmltIHmlflEsSdf`m5a81_B@c|jb(Y5JY7e&eg(iDf)HM9+@2 zeaG|abN7aQmd#%Z_S!A?`t0D#r(P-0Z@1h##e}9-D;nzKUV^?qGWI>5@pOouju%Yp!e%iP*)5VF~ zuPad{@+R%56imV*u}gxHW?*(@JiA5D?zDaPuXJEGqI$!?6r+B_z$jc`gMpEgj3b@= z=jTW#J%v$&7;fZkHwz+#XDB={)V~3*_sFHFh)}0R1VdyTQNXy)O=diuqNg)$?|fbu z@G1S@Xztbi7n^mp|H^z9?7tj|ViEuG#xspZ0G~&K%kN|0JfT;a@#|MOP|JfD$HT3S zL|$~$*xpXXK+T3mI%C9Am&o>tWasVg>pw9#Fgo~!!T$4T+-h16yi%@F^-8?{F0nE8 z4HyBT9=fQJ@_yRbnelXqp01Vd)#u6yI+anulM2boNiz;;gN))XMqWcZI%N=oXgYc} z+&7#bhS8Csmj_K_;ozs^qgc%7grHZvX(DEE1WasjPsX!X^z2RB_nL{I8itE(Ykv>2 z7SpW31_d`8#OZWzn3Fh2VN?9N6za_hNTHrS=u)7SP@NER02o@1EBlsr>egZ(V{o?-+-jjNnMY5J7M=_G-?rVsX zzXb_F(FRszO`>zh(#XBh2hNb_>{v>OT}OzwbHyg^JZki660|R|V&`F!AYVWs-}a?} zdts7JlSL|iy~c&NNnFZp5@?$05cdcr{5E+0-=TzYP_^=pp-F9Jl1)D1m~=;^3VmcI z5v!z`M7%6KS9pW9&|FD3o~60^CeD?t6qV+Rj9Z^Fn)fD&Z|6$Ohh4=|QiX0i!k* zgvyyi>y!$r-3;8vP(i4K0lO9zc%4jeol-%)gMl+g71Wk7)$5cB0v_fhXuLFVa|HvF zrh=^{3|x^_f!EDcVAV1Rm7z}s0UHA*qbhLP7&!A(fwLUjse)=7Q-`rKa55OH0yl$2 zslaW=SQS*!q}du+LgOf^poA*%ty`4rpIG7btqW3sn`VyVEy_HE#O`&Ag=q)XAJdMB z-EVzC3b4yjofy@riRy#{EGbt9Ms;YSI-VtJg96dGiRsZ4*rOJ>2c!0AqV_yX6x>L+ zFkPBlU23ikqBf{&9~QVzQ{XrB7zV)83Phgog!a6 zdIf@v-w1&(H`rJYd{2V@{NIxRC8Rg!?GtXq$26OW4ziJ+!QCmY^( zgy1+!HNhuYKZ_YYo=xcvdvN_BYYvJ=>V=(tQZObSnS_ngxFlLj_1>7A4oyshNfoTH zF_1H3mpU=Ucr-Sio)I*1v1RT!5@hvhfrPAPJ32>Tbc9gE22OwM?*0LXw=$Uxr;FiJrZw3&*40BBRuYronO zXKe{}pGa~QC0v6k3$c1DXv&f&z|*+zK`SRbgD7@4F--Iy(tQUPw48q(KwGJFB8)eX z$>o3kP4p3g_y+orAL~q3W-xRX!32Wq0E`!d$+n;X(o5G;v5o%%k^UpdDkHs@@&%sJ zG=&INuH&?7nzA@>_vBj3{?(TK_v3)KT-gX*cOsW9`F{%U1#iB@P z@k*s#x>AYSo$uBkrv7=TugUu35Didwp^|}kf-~6uw`Hu6Ii3bvfaC3-wGxAQi~fe9 zk(U|o{pfL{D9<#Q<^kV3AQ>I-UxJ1a{-Ki~aUQ=3zmIV5{4H9-c5-Q`=Xsd6YxyZ$ z8`=dpDP0>1^IyUCy$V2Ch3BL#@fZXpdx{{=2IlL3f!K5rGCz?y6lD#d-MS3&cI&}@ zdY%;n9ZT%JtM{8hM|A(1*x4rrj()T|6F4CTPNcoY2Ta+uWsyZQ3_Upo)$z!P+vMwJ z!x+FJU;*SxGdH>b(-&=V+Rb#8_B z5i0mc;E_dpY7zWqXS}ulxAiR@z(9+_W1&u!zv8V<{y4OgKY`#S0J=+IsC3$3j_~to z!eg8xoM;*2KF3FGLM>~dp4Cv#%Hd4ts2Dn$t~EaTD`u*M1huM?+K2EWjlOF4fBLU$ z_pcqd4Zi^ZMpxPkgnBtlSBmy~0B2+_bs3sYRv1~l(*nC5S4UfZ;Db<@t3s+H)< z#g&U6R%bT#iko`VHOA)|jrB{RafEhy0gFDf)SPszE#ESYfDY`wRV0E3e-p``7gQ>yIKC%F&amj{|x{pyH=tH zFDm+?`J@YR=>y0s%PA(y)|!U*YS(IZuGSFj_%N8MIUv>?NLL!4PqlS@W;xeW`MIoL z3BLUS^yJfcb@7YfI*NvSp^H$O*#UMG-7V=#_;kxy8~>Y7zLrPa!uQ_-phyn#vWoiu zq7#Wmts$I9RQ#LywQcFlz0yozrx@6o_8K3!*d3^qzgG4s37^gQmCVCBG{j8z??Wi! zn&kcl3}6TT_6=ZRhE?^HY78rV0cK;<%4ldKW7sf{!Zv>!fN6F3HUuVXi>wY%Xe&;A z3KGdQ3}VhR+P3!M7NWPfZ7b4j`)XbL(#T5FO7tIYx%Z_^-2t)gK-zD7KE>KqUCv|B zOf+tikmGOKz)44b(x=F*$rk-KQMPm%%QM&C=5ZFic_K{g_>Gx3Ki!6Hxz6BN_pw%C_6beI?5lxHvb<4TkvSlF0G6m_7woiZHx;~^JL(x$KyLaIH);g zlujHsJMmOc1@-EoB{{yVFK7B;XRm?P>MXoG30~!(sxyDC_wNi>*dNhch1v~SH3UCHkVEhQ!9xW94Z;6F@RtZaL2wp< z6G1Hka=MHiFdRESwI7uJ*T7-E66OvbO8930;ghK}ou$g>$WNAPPV1j6)sogfpo6AE zX=;=9c}NA)`X@{6OzWSlJ^`dRhdlH&%sI0aO>^$7chj6p0@Yn<$}a`_+tQRTD+TzP z=R8>gDz~I5Z?<+jS+^1gU!P56B7Pd8=EYD)j|W(7l!k1enMg%7l|jx`hNjY C*+Izw literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/graph/commands.py b/.venv/Lib/site-packages/redis/commands/graph/commands.py new file mode 100644 index 00000000..762ab42e --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/graph/commands.py @@ -0,0 +1,313 @@ +from redis import DataError +from redis.exceptions import ResponseError + +from .exceptions import VersionMismatchException +from .execution_plan import ExecutionPlan +from .query_result import AsyncQueryResult, QueryResult + +PROFILE_CMD = "GRAPH.PROFILE" +RO_QUERY_CMD = "GRAPH.RO_QUERY" +QUERY_CMD = "GRAPH.QUERY" +DELETE_CMD = "GRAPH.DELETE" +SLOWLOG_CMD = "GRAPH.SLOWLOG" +CONFIG_CMD = "GRAPH.CONFIG" +LIST_CMD = "GRAPH.LIST" +EXPLAIN_CMD = "GRAPH.EXPLAIN" + + +class GraphCommands: + """RedisGraph Commands""" + + def commit(self): + """ + Create entire graph. + """ + if len(self.nodes) == 0 and len(self.edges) == 0: + return None + + query = "CREATE " + for _, node in self.nodes.items(): + query += str(node) + "," + + query += ",".join([str(edge) for edge in self.edges]) + + # Discard leading comma. + if query[-1] == ",": + query = query[:-1] + + return self.query(query) + + def query(self, q, params=None, timeout=None, read_only=False, profile=False): + """ + Executes a query against the graph. + For more information see `GRAPH.QUERY `_. # noqa + + Args: + + q : str + The query. + params : dict + Query parameters. + timeout : int + Maximum runtime for read queries in milliseconds. + read_only : bool + Executes a readonly query if set to True. + profile : bool + Return details on results produced by and time + spent in each operation. + """ + + # maintain original 'q' + query = q + + # handle query parameters + query = self._build_params_header(params) + query + + # construct query command + # ask for compact result-set format + # specify known graph version + if profile: + cmd = PROFILE_CMD + else: + cmd = RO_QUERY_CMD if read_only else QUERY_CMD + command = [cmd, self.name, query, "--compact"] + + # include timeout is specified + if isinstance(timeout, int): + command.extend(["timeout", timeout]) + elif timeout is not None: + raise Exception("Timeout argument must be a positive integer") + + # issue query + try: + response = self.execute_command(*command) + return QueryResult(self, response, profile) + except ResponseError as e: + if "unknown command" in str(e) and read_only: + # `GRAPH.RO_QUERY` is unavailable in older versions. + return self.query(q, params, timeout, read_only=False) + raise e + except VersionMismatchException as e: + # client view over the graph schema is out of sync + # set client version and refresh local schema + self.version = e.version + self._refresh_schema() + # re-issue query + return self.query(q, params, timeout, read_only) + + def merge(self, pattern): + """ + Merge pattern. + """ + query = "MERGE " + query += str(pattern) + + return self.query(query) + + def delete(self): + """ + Deletes graph. + For more information see `DELETE `_. # noqa + """ + self._clear_schema() + return self.execute_command(DELETE_CMD, self.name) + + # declared here, to override the built in redis.db.flush() + def flush(self): + """ + Commit the graph and reset the edges and the nodes to zero length. + """ + self.commit() + self.nodes = {} + self.edges = [] + + def bulk(self, **kwargs): + """Internal only. Not supported.""" + raise NotImplementedError( + "GRAPH.BULK is internal only. " + "Use https://github.com/redisgraph/redisgraph-bulk-loader." + ) + + def profile(self, query): + """ + Execute a query and produce an execution plan augmented with metrics + for each operation's execution. Return a string representation of a + query execution plan, with details on results produced by and time + spent in each operation. + For more information see `GRAPH.PROFILE `_. # noqa + """ + return self.query(query, profile=True) + + def slowlog(self): + """ + Get a list containing up to 10 of the slowest queries issued + against the given graph ID. + For more information see `GRAPH.SLOWLOG `_. # noqa + + Each item in the list has the following structure: + 1. A unix timestamp at which the log entry was processed. + 2. The issued command. + 3. The issued query. + 4. The amount of time needed for its execution, in milliseconds. + """ + return self.execute_command(SLOWLOG_CMD, self.name) + + def config(self, name, value=None, set=False): + """ + Retrieve or update a RedisGraph configuration. + For more information see `https://redis.io/commands/graph.config-get/>`_. # noqa + + Args: + + name : str + The name of the configuration + value : + The value we want to set (can be used only when `set` is on) + set : bool + Turn on to set a configuration. Default behavior is get. + """ + params = ["SET" if set else "GET", name] + if value is not None: + if set: + params.append(value) + else: + raise DataError( + "``value`` can be provided only when ``set`` is True" + ) # noqa + return self.execute_command(CONFIG_CMD, *params) + + def list_keys(self): + """ + Lists all graph keys in the keyspace. + For more information see `GRAPH.LIST `_. # noqa + """ + return self.execute_command(LIST_CMD) + + def execution_plan(self, query, params=None): + """ + Get the execution plan for given query, + GRAPH.EXPLAIN returns an array of operations. + + Args: + query: the query that will be executed + params: query parameters + """ + query = self._build_params_header(params) + query + + plan = self.execute_command(EXPLAIN_CMD, self.name, query) + if isinstance(plan[0], bytes): + plan = [b.decode() for b in plan] + return "\n".join(plan) + + def explain(self, query, params=None): + """ + Get the execution plan for given query, + GRAPH.EXPLAIN returns ExecutionPlan object. + For more information see `GRAPH.EXPLAIN `_. # noqa + + Args: + query: the query that will be executed + params: query parameters + """ + query = self._build_params_header(params) + query + + plan = self.execute_command(EXPLAIN_CMD, self.name, query) + return ExecutionPlan(plan) + + +class AsyncGraphCommands(GraphCommands): + async def query(self, q, params=None, timeout=None, read_only=False, profile=False): + """ + Executes a query against the graph. + For more information see `GRAPH.QUERY `_. # noqa + + Args: + + q : str + The query. + params : dict + Query parameters. + timeout : int + Maximum runtime for read queries in milliseconds. + read_only : bool + Executes a readonly query if set to True. + profile : bool + Return details on results produced by and time + spent in each operation. + """ + + # maintain original 'q' + query = q + + # handle query parameters + query = self._build_params_header(params) + query + + # construct query command + # ask for compact result-set format + # specify known graph version + if profile: + cmd = PROFILE_CMD + else: + cmd = RO_QUERY_CMD if read_only else QUERY_CMD + command = [cmd, self.name, query, "--compact"] + + # include timeout is specified + if isinstance(timeout, int): + command.extend(["timeout", timeout]) + elif timeout is not None: + raise Exception("Timeout argument must be a positive integer") + + # issue query + try: + response = await self.execute_command(*command) + return await AsyncQueryResult().initialize(self, response, profile) + except ResponseError as e: + if "unknown command" in str(e) and read_only: + # `GRAPH.RO_QUERY` is unavailable in older versions. + return await self.query(q, params, timeout, read_only=False) + raise e + except VersionMismatchException as e: + # client view over the graph schema is out of sync + # set client version and refresh local schema + self.version = e.version + self._refresh_schema() + # re-issue query + return await self.query(q, params, timeout, read_only) + + async def execution_plan(self, query, params=None): + """ + Get the execution plan for given query, + GRAPH.EXPLAIN returns an array of operations. + + Args: + query: the query that will be executed + params: query parameters + """ + query = self._build_params_header(params) + query + + plan = await self.execute_command(EXPLAIN_CMD, self.name, query) + if isinstance(plan[0], bytes): + plan = [b.decode() for b in plan] + return "\n".join(plan) + + async def explain(self, query, params=None): + """ + Get the execution plan for given query, + GRAPH.EXPLAIN returns ExecutionPlan object. + + Args: + query: the query that will be executed + params: query parameters + """ + query = self._build_params_header(params) + query + + plan = await self.execute_command(EXPLAIN_CMD, self.name, query) + return ExecutionPlan(plan) + + async def flush(self): + """ + Commit the graph and reset the edges and the nodes to zero length. + """ + await self.commit() + self.nodes = {} + self.edges = [] diff --git a/.venv/Lib/site-packages/redis/commands/graph/edge.py b/.venv/Lib/site-packages/redis/commands/graph/edge.py new file mode 100644 index 00000000..6ee195f1 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/graph/edge.py @@ -0,0 +1,91 @@ +from ..helpers import quote_string +from .node import Node + + +class Edge: + """ + An edge connecting two nodes. + """ + + def __init__(self, src_node, relation, dest_node, edge_id=None, properties=None): + """ + Create a new edge. + """ + if src_node is None or dest_node is None: + # NOTE(bors-42): It makes sense to change AssertionError to + # ValueError here + raise AssertionError("Both src_node & dest_node must be provided") + + self.id = edge_id + self.relation = relation or "" + self.properties = properties or {} + self.src_node = src_node + self.dest_node = dest_node + + def to_string(self): + res = "" + if self.properties: + props = ",".join( + key + ":" + str(quote_string(val)) + for key, val in sorted(self.properties.items()) + ) + res += "{" + props + "}" + + return res + + def __str__(self): + # Source node. + if isinstance(self.src_node, Node): + res = str(self.src_node) + else: + res = "()" + + # Edge + res += "-[" + if self.relation: + res += ":" + self.relation + if self.properties: + props = ",".join( + key + ":" + str(quote_string(val)) + for key, val in sorted(self.properties.items()) + ) + res += "{" + props + "}" + res += "]->" + + # Dest node. + if isinstance(self.dest_node, Node): + res += str(self.dest_node) + else: + res += "()" + + return res + + def __eq__(self, rhs): + # Type checking + if not isinstance(rhs, Edge): + return False + + # Quick positive check, if both IDs are set. + if self.id is not None and rhs.id is not None and self.id == rhs.id: + return True + + # Source and destination nodes should match. + if self.src_node != rhs.src_node: + return False + + if self.dest_node != rhs.dest_node: + return False + + # Relation should match. + if self.relation != rhs.relation: + return False + + # Quick check for number of properties. + if len(self.properties) != len(rhs.properties): + return False + + # Compare properties. + if self.properties != rhs.properties: + return False + + return True diff --git a/.venv/Lib/site-packages/redis/commands/graph/exceptions.py b/.venv/Lib/site-packages/redis/commands/graph/exceptions.py new file mode 100644 index 00000000..4bbac100 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/graph/exceptions.py @@ -0,0 +1,3 @@ +class VersionMismatchException(Exception): + def __init__(self, version): + self.version = version diff --git a/.venv/Lib/site-packages/redis/commands/graph/execution_plan.py b/.venv/Lib/site-packages/redis/commands/graph/execution_plan.py new file mode 100644 index 00000000..179a80cc --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/graph/execution_plan.py @@ -0,0 +1,211 @@ +import re + + +class ProfileStats: + """ + ProfileStats, runtime execution statistics of operation. + """ + + def __init__(self, records_produced, execution_time): + self.records_produced = records_produced + self.execution_time = execution_time + + +class Operation: + """ + Operation, single operation within execution plan. + """ + + def __init__(self, name, args=None, profile_stats=None): + """ + Create a new operation. + + Args: + name: string that represents the name of the operation + args: operation arguments + profile_stats: profile statistics + """ + self.name = name + self.args = args + self.profile_stats = profile_stats + self.children = [] + + def append_child(self, child): + if not isinstance(child, Operation) or self is child: + raise Exception("child must be Operation") + + self.children.append(child) + return self + + def child_count(self): + return len(self.children) + + def __eq__(self, o: object) -> bool: + if not isinstance(o, Operation): + return False + + return self.name == o.name and self.args == o.args + + def __str__(self) -> str: + args_str = "" if self.args is None else " | " + self.args + return f"{self.name}{args_str}" + + +class ExecutionPlan: + """ + ExecutionPlan, collection of operations. + """ + + def __init__(self, plan): + """ + Create a new execution plan. + + Args: + plan: array of strings that represents the collection operations + the output from GRAPH.EXPLAIN + """ + if not isinstance(plan, list): + raise Exception("plan must be an array") + + if isinstance(plan[0], bytes): + plan = [b.decode() for b in plan] + + self.plan = plan + self.structured_plan = self._operation_tree() + + def _compare_operations(self, root_a, root_b): + """ + Compare execution plan operation tree + + Return: True if operation trees are equal, False otherwise + """ + + # compare current root + if root_a != root_b: + return False + + # make sure root have the same number of children + if root_a.child_count() != root_b.child_count(): + return False + + # recursively compare children + for i in range(root_a.child_count()): + if not self._compare_operations(root_a.children[i], root_b.children[i]): + return False + + return True + + def __str__(self) -> str: + def aggraget_str(str_children): + return "\n".join( + [ + " " + line + for str_child in str_children + for line in str_child.splitlines() + ] + ) + + def combine_str(x, y): + return f"{x}\n{y}" + + return self._operation_traverse( + self.structured_plan, str, aggraget_str, combine_str + ) + + def __eq__(self, o: object) -> bool: + """Compares two execution plans + + Return: True if the two plans are equal False otherwise + """ + # make sure 'o' is an execution-plan + if not isinstance(o, ExecutionPlan): + return False + + # get root for both plans + root_a = self.structured_plan + root_b = o.structured_plan + + # compare execution trees + return self._compare_operations(root_a, root_b) + + def _operation_traverse(self, op, op_f, aggregate_f, combine_f): + """ + Traverse operation tree recursively applying functions + + Args: + op: operation to traverse + op_f: function applied for each operation + aggregate_f: aggregation function applied for all children of a single operation + combine_f: combine function applied for the operation result and the children result + """ # noqa + # apply op_f for each operation + op_res = op_f(op) + if len(op.children) == 0: + return op_res # no children return + else: + # apply _operation_traverse recursively + children = [ + self._operation_traverse(child, op_f, aggregate_f, combine_f) + for child in op.children + ] + # combine the operation result with the children aggregated result + return combine_f(op_res, aggregate_f(children)) + + def _operation_tree(self): + """Build the operation tree from the string representation""" + + # initial state + i = 0 + level = 0 + stack = [] + current = None + + def _create_operation(args): + profile_stats = None + name = args[0].strip() + args.pop(0) + if len(args) > 0 and "Records produced" in args[-1]: + records_produced = int( + re.search("Records produced: (\\d+)", args[-1]).group(1) + ) + execution_time = float( + re.search("Execution time: (\\d+.\\d+) ms", args[-1]).group(1) + ) + profile_stats = ProfileStats(records_produced, execution_time) + args.pop(-1) + return Operation( + name, None if len(args) == 0 else args[0].strip(), profile_stats + ) + + # iterate plan operations + while i < len(self.plan): + current_op = self.plan[i] + op_level = current_op.count(" ") + if op_level == level: + # if the operation level equal to the current level + # set the current operation and move next + child = _create_operation(current_op.split("|")) + if current: + current = stack.pop() + current.append_child(child) + current = child + i += 1 + elif op_level == level + 1: + # if the operation is child of the current operation + # add it as child and set as current operation + child = _create_operation(current_op.split("|")) + current.append_child(child) + stack.append(current) + current = child + level += 1 + i += 1 + elif op_level < level: + # if the operation is not child of current operation + # go back to it's parent operation + levels_back = level - op_level + 1 + for _ in range(levels_back): + current = stack.pop() + level -= levels_back + else: + raise Exception("corrupted plan") + return stack[0] diff --git a/.venv/Lib/site-packages/redis/commands/graph/node.py b/.venv/Lib/site-packages/redis/commands/graph/node.py new file mode 100644 index 00000000..4546a393 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/graph/node.py @@ -0,0 +1,88 @@ +from ..helpers import quote_string + + +class Node: + """ + A node within the graph. + """ + + def __init__(self, node_id=None, alias=None, label=None, properties=None): + """ + Create a new node. + """ + self.id = node_id + self.alias = alias + if isinstance(label, list): + label = [inner_label for inner_label in label if inner_label != ""] + + if ( + label is None + or label == "" + or (isinstance(label, list) and len(label) == 0) + ): + self.label = None + self.labels = None + elif isinstance(label, str): + self.label = label + self.labels = [label] + elif isinstance(label, list) and all( + [isinstance(inner_label, str) for inner_label in label] + ): + self.label = label[0] + self.labels = label + else: + raise AssertionError( + "label should be either None, string or a list of strings" + ) + + self.properties = properties or {} + + def to_string(self): + res = "" + if self.properties: + props = ",".join( + key + ":" + str(quote_string(val)) + for key, val in sorted(self.properties.items()) + ) + res += "{" + props + "}" + + return res + + def __str__(self): + res = "(" + if self.alias: + res += self.alias + if self.labels: + res += ":" + ":".join(self.labels) + if self.properties: + props = ",".join( + key + ":" + str(quote_string(val)) + for key, val in sorted(self.properties.items()) + ) + res += "{" + props + "}" + res += ")" + + return res + + def __eq__(self, rhs): + # Type checking + if not isinstance(rhs, Node): + return False + + # Quick positive check, if both IDs are set. + if self.id is not None and rhs.id is not None and self.id != rhs.id: + return False + + # Label should match. + if self.label != rhs.label: + return False + + # Quick check for number of properties. + if len(self.properties) != len(rhs.properties): + return False + + # Compare properties. + if self.properties != rhs.properties: + return False + + return True diff --git a/.venv/Lib/site-packages/redis/commands/graph/path.py b/.venv/Lib/site-packages/redis/commands/graph/path.py new file mode 100644 index 00000000..ee22dc8c --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/graph/path.py @@ -0,0 +1,78 @@ +from .edge import Edge +from .node import Node + + +class Path: + def __init__(self, nodes, edges): + if not (isinstance(nodes, list) and isinstance(edges, list)): + raise TypeError("nodes and edges must be list") + + self._nodes = nodes + self._edges = edges + self.append_type = Node + + @classmethod + def new_empty_path(cls): + return cls([], []) + + def nodes(self): + return self._nodes + + def edges(self): + return self._edges + + def get_node(self, index): + return self._nodes[index] + + def get_relationship(self, index): + return self._edges[index] + + def first_node(self): + return self._nodes[0] + + def last_node(self): + return self._nodes[-1] + + def edge_count(self): + return len(self._edges) + + def nodes_count(self): + return len(self._nodes) + + def add_node(self, node): + if not isinstance(node, self.append_type): + raise AssertionError("Add Edge before adding Node") + self._nodes.append(node) + self.append_type = Edge + return self + + def add_edge(self, edge): + if not isinstance(edge, self.append_type): + raise AssertionError("Add Node before adding Edge") + self._edges.append(edge) + self.append_type = Node + return self + + def __eq__(self, other): + # Type checking + if not isinstance(other, Path): + return False + + return self.nodes() == other.nodes() and self.edges() == other.edges() + + def __str__(self): + res = "<" + edge_count = self.edge_count() + for i in range(0, edge_count): + node_id = self.get_node(i).id + res += "(" + str(node_id) + ")" + edge = self.get_relationship(i) + res += ( + "-[" + str(int(edge.id)) + "]->" + if edge.src_node == node_id + else "<-[" + str(int(edge.id)) + "]-" + ) + node_id = self.get_node(edge_count).id + res += "(" + str(node_id) + ")" + res += ">" + return res diff --git a/.venv/Lib/site-packages/redis/commands/graph/query_result.py b/.venv/Lib/site-packages/redis/commands/graph/query_result.py new file mode 100644 index 00000000..7c7f58b9 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/graph/query_result.py @@ -0,0 +1,573 @@ +import sys +from collections import OrderedDict +from distutils.util import strtobool + +# from prettytable import PrettyTable +from redis import ResponseError + +from .edge import Edge +from .exceptions import VersionMismatchException +from .node import Node +from .path import Path + +LABELS_ADDED = "Labels added" +LABELS_REMOVED = "Labels removed" +NODES_CREATED = "Nodes created" +NODES_DELETED = "Nodes deleted" +RELATIONSHIPS_DELETED = "Relationships deleted" +PROPERTIES_SET = "Properties set" +PROPERTIES_REMOVED = "Properties removed" +RELATIONSHIPS_CREATED = "Relationships created" +INDICES_CREATED = "Indices created" +INDICES_DELETED = "Indices deleted" +CACHED_EXECUTION = "Cached execution" +INTERNAL_EXECUTION_TIME = "internal execution time" + +STATS = [ + LABELS_ADDED, + LABELS_REMOVED, + NODES_CREATED, + PROPERTIES_SET, + PROPERTIES_REMOVED, + RELATIONSHIPS_CREATED, + NODES_DELETED, + RELATIONSHIPS_DELETED, + INDICES_CREATED, + INDICES_DELETED, + CACHED_EXECUTION, + INTERNAL_EXECUTION_TIME, +] + + +class ResultSetColumnTypes: + COLUMN_UNKNOWN = 0 + COLUMN_SCALAR = 1 + COLUMN_NODE = 2 # Unused as of RedisGraph v2.1.0, retained for backwards compatibility. # noqa + COLUMN_RELATION = 3 # Unused as of RedisGraph v2.1.0, retained for backwards compatibility. # noqa + + +class ResultSetScalarTypes: + VALUE_UNKNOWN = 0 + VALUE_NULL = 1 + VALUE_STRING = 2 + VALUE_INTEGER = 3 + VALUE_BOOLEAN = 4 + VALUE_DOUBLE = 5 + VALUE_ARRAY = 6 + VALUE_EDGE = 7 + VALUE_NODE = 8 + VALUE_PATH = 9 + VALUE_MAP = 10 + VALUE_POINT = 11 + + +class QueryResult: + def __init__(self, graph, response, profile=False): + """ + A class that represents a result of the query operation. + + Args: + + graph: + The graph on which the query was executed. + response: + The response from the server. + profile: + A boolean indicating if the query command was "GRAPH.PROFILE" + """ + self.graph = graph + self.header = [] + self.result_set = [] + + # in case of an error an exception will be raised + self._check_for_errors(response) + + if len(response) == 1: + self.parse_statistics(response[0]) + elif profile: + self.parse_profile(response) + else: + # start by parsing statistics, matches the one we have + self.parse_statistics(response[-1]) # Last element. + self.parse_results(response) + + def _check_for_errors(self, response): + """ + Check if the response contains an error. + """ + if isinstance(response[0], ResponseError): + error = response[0] + if str(error) == "version mismatch": + version = response[1] + error = VersionMismatchException(version) + raise error + + # If we encountered a run-time error, the last response + # element will be an exception + if isinstance(response[-1], ResponseError): + raise response[-1] + + def parse_results(self, raw_result_set): + """ + Parse the query execution result returned from the server. + """ + self.header = self.parse_header(raw_result_set) + + # Empty header. + if len(self.header) == 0: + return + + self.result_set = self.parse_records(raw_result_set) + + def parse_statistics(self, raw_statistics): + """ + Parse the statistics returned in the response. + """ + self.statistics = {} + + # decode statistics + for idx, stat in enumerate(raw_statistics): + if isinstance(stat, bytes): + raw_statistics[idx] = stat.decode() + + for s in STATS: + v = self._get_value(s, raw_statistics) + if v is not None: + self.statistics[s] = v + + def parse_header(self, raw_result_set): + """ + Parse the header of the result. + """ + # An array of column name/column type pairs. + header = raw_result_set[0] + return header + + def parse_records(self, raw_result_set): + """ + Parses the result set and returns a list of records. + """ + records = [ + [ + self.parse_record_types[self.header[idx][0]](cell) + for idx, cell in enumerate(row) + ] + for row in raw_result_set[1] + ] + + return records + + def parse_entity_properties(self, props): + """ + Parse node / edge properties. + """ + # [[name, value type, value] X N] + properties = {} + for prop in props: + prop_name = self.graph.get_property(prop[0]) + prop_value = self.parse_scalar(prop[1:]) + properties[prop_name] = prop_value + + return properties + + def parse_string(self, cell): + """ + Parse the cell as a string. + """ + if isinstance(cell, bytes): + return cell.decode() + elif not isinstance(cell, str): + return str(cell) + else: + return cell + + def parse_node(self, cell): + """ + Parse the cell to a node. + """ + # Node ID (integer), + # [label string offset (integer)], + # [[name, value type, value] X N] + + node_id = int(cell[0]) + labels = None + if len(cell[1]) > 0: + labels = [] + for inner_label in cell[1]: + labels.append(self.graph.get_label(inner_label)) + properties = self.parse_entity_properties(cell[2]) + return Node(node_id=node_id, label=labels, properties=properties) + + def parse_edge(self, cell): + """ + Parse the cell to an edge. + """ + # Edge ID (integer), + # reltype string offset (integer), + # src node ID offset (integer), + # dest node ID offset (integer), + # [[name, value, value type] X N] + + edge_id = int(cell[0]) + relation = self.graph.get_relation(cell[1]) + src_node_id = int(cell[2]) + dest_node_id = int(cell[3]) + properties = self.parse_entity_properties(cell[4]) + return Edge( + src_node_id, relation, dest_node_id, edge_id=edge_id, properties=properties + ) + + def parse_path(self, cell): + """ + Parse the cell to a path. + """ + nodes = self.parse_scalar(cell[0]) + edges = self.parse_scalar(cell[1]) + return Path(nodes, edges) + + def parse_map(self, cell): + """ + Parse the cell as a map. + """ + m = OrderedDict() + n_entries = len(cell) + + # A map is an array of key value pairs. + # 1. key (string) + # 2. array: (value type, value) + for i in range(0, n_entries, 2): + key = self.parse_string(cell[i]) + m[key] = self.parse_scalar(cell[i + 1]) + + return m + + def parse_point(self, cell): + """ + Parse the cell to point. + """ + p = {} + # A point is received an array of the form: [latitude, longitude] + # It is returned as a map of the form: {"latitude": latitude, "longitude": longitude} # noqa + p["latitude"] = float(cell[0]) + p["longitude"] = float(cell[1]) + return p + + def parse_null(self, cell): + """ + Parse a null value. + """ + return None + + def parse_integer(self, cell): + """ + Parse the integer value from the cell. + """ + return int(cell) + + def parse_boolean(self, value): + """ + Parse the cell value as a boolean. + """ + value = value.decode() if isinstance(value, bytes) else value + try: + scalar = True if strtobool(value) else False + except ValueError: + sys.stderr.write("unknown boolean type\n") + scalar = None + return scalar + + def parse_double(self, cell): + """ + Parse the cell as a double. + """ + return float(cell) + + def parse_array(self, value): + """ + Parse an array of values. + """ + scalar = [self.parse_scalar(value[i]) for i in range(len(value))] + return scalar + + def parse_unknown(self, cell): + """ + Parse a cell of unknown type. + """ + sys.stderr.write("Unknown type\n") + return None + + def parse_scalar(self, cell): + """ + Parse a scalar value from a cell in the result set. + """ + scalar_type = int(cell[0]) + value = cell[1] + scalar = self.parse_scalar_types[scalar_type](value) + + return scalar + + def parse_profile(self, response): + self.result_set = [x[0 : x.index(",")].strip() for x in response] + + def is_empty(self): + return len(self.result_set) == 0 + + @staticmethod + def _get_value(prop, statistics): + for stat in statistics: + if prop in stat: + return float(stat.split(": ")[1].split(" ")[0]) + + return None + + def _get_stat(self, stat): + return self.statistics[stat] if stat in self.statistics else 0 + + @property + def labels_added(self): + """Returns the number of labels added in the query""" + return self._get_stat(LABELS_ADDED) + + @property + def labels_removed(self): + """Returns the number of labels removed in the query""" + return self._get_stat(LABELS_REMOVED) + + @property + def nodes_created(self): + """Returns the number of nodes created in the query""" + return self._get_stat(NODES_CREATED) + + @property + def nodes_deleted(self): + """Returns the number of nodes deleted in the query""" + return self._get_stat(NODES_DELETED) + + @property + def properties_set(self): + """Returns the number of properties set in the query""" + return self._get_stat(PROPERTIES_SET) + + @property + def properties_removed(self): + """Returns the number of properties removed in the query""" + return self._get_stat(PROPERTIES_REMOVED) + + @property + def relationships_created(self): + """Returns the number of relationships created in the query""" + return self._get_stat(RELATIONSHIPS_CREATED) + + @property + def relationships_deleted(self): + """Returns the number of relationships deleted in the query""" + return self._get_stat(RELATIONSHIPS_DELETED) + + @property + def indices_created(self): + """Returns the number of indices created in the query""" + return self._get_stat(INDICES_CREATED) + + @property + def indices_deleted(self): + """Returns the number of indices deleted in the query""" + return self._get_stat(INDICES_DELETED) + + @property + def cached_execution(self): + """Returns whether or not the query execution plan was cached""" + return self._get_stat(CACHED_EXECUTION) == 1 + + @property + def run_time_ms(self): + """Returns the server execution time of the query""" + return self._get_stat(INTERNAL_EXECUTION_TIME) + + @property + def parse_scalar_types(self): + return { + ResultSetScalarTypes.VALUE_NULL: self.parse_null, + ResultSetScalarTypes.VALUE_STRING: self.parse_string, + ResultSetScalarTypes.VALUE_INTEGER: self.parse_integer, + ResultSetScalarTypes.VALUE_BOOLEAN: self.parse_boolean, + ResultSetScalarTypes.VALUE_DOUBLE: self.parse_double, + ResultSetScalarTypes.VALUE_ARRAY: self.parse_array, + ResultSetScalarTypes.VALUE_NODE: self.parse_node, + ResultSetScalarTypes.VALUE_EDGE: self.parse_edge, + ResultSetScalarTypes.VALUE_PATH: self.parse_path, + ResultSetScalarTypes.VALUE_MAP: self.parse_map, + ResultSetScalarTypes.VALUE_POINT: self.parse_point, + ResultSetScalarTypes.VALUE_UNKNOWN: self.parse_unknown, + } + + @property + def parse_record_types(self): + return { + ResultSetColumnTypes.COLUMN_SCALAR: self.parse_scalar, + ResultSetColumnTypes.COLUMN_NODE: self.parse_node, + ResultSetColumnTypes.COLUMN_RELATION: self.parse_edge, + ResultSetColumnTypes.COLUMN_UNKNOWN: self.parse_unknown, + } + + +class AsyncQueryResult(QueryResult): + """ + Async version for the QueryResult class - a class that + represents a result of the query operation. + """ + + def __init__(self): + """ + To init the class you must call self.initialize() + """ + pass + + async def initialize(self, graph, response, profile=False): + """ + Initializes the class. + Args: + + graph: + The graph on which the query was executed. + response: + The response from the server. + profile: + A boolean indicating if the query command was "GRAPH.PROFILE" + """ + self.graph = graph + self.header = [] + self.result_set = [] + + # in case of an error an exception will be raised + self._check_for_errors(response) + + if len(response) == 1: + self.parse_statistics(response[0]) + elif profile: + self.parse_profile(response) + else: + # start by parsing statistics, matches the one we have + self.parse_statistics(response[-1]) # Last element. + await self.parse_results(response) + + return self + + async def parse_node(self, cell): + """ + Parses a node from the cell. + """ + # Node ID (integer), + # [label string offset (integer)], + # [[name, value type, value] X N] + + labels = None + if len(cell[1]) > 0: + labels = [] + for inner_label in cell[1]: + labels.append(await self.graph.get_label(inner_label)) + properties = await self.parse_entity_properties(cell[2]) + node_id = int(cell[0]) + return Node(node_id=node_id, label=labels, properties=properties) + + async def parse_scalar(self, cell): + """ + Parses a scalar value from the server response. + """ + scalar_type = int(cell[0]) + value = cell[1] + try: + scalar = await self.parse_scalar_types[scalar_type](value) + except TypeError: + # Not all of the functions are async + scalar = self.parse_scalar_types[scalar_type](value) + + return scalar + + async def parse_records(self, raw_result_set): + """ + Parses the result set and returns a list of records. + """ + records = [] + for row in raw_result_set[1]: + record = [ + await self.parse_record_types[self.header[idx][0]](cell) + for idx, cell in enumerate(row) + ] + records.append(record) + + return records + + async def parse_results(self, raw_result_set): + """ + Parse the query execution result returned from the server. + """ + self.header = self.parse_header(raw_result_set) + + # Empty header. + if len(self.header) == 0: + return + + self.result_set = await self.parse_records(raw_result_set) + + async def parse_entity_properties(self, props): + """ + Parse node / edge properties. + """ + # [[name, value type, value] X N] + properties = {} + for prop in props: + prop_name = await self.graph.get_property(prop[0]) + prop_value = await self.parse_scalar(prop[1:]) + properties[prop_name] = prop_value + + return properties + + async def parse_edge(self, cell): + """ + Parse the cell to an edge. + """ + # Edge ID (integer), + # reltype string offset (integer), + # src node ID offset (integer), + # dest node ID offset (integer), + # [[name, value, value type] X N] + + edge_id = int(cell[0]) + relation = await self.graph.get_relation(cell[1]) + src_node_id = int(cell[2]) + dest_node_id = int(cell[3]) + properties = await self.parse_entity_properties(cell[4]) + return Edge( + src_node_id, relation, dest_node_id, edge_id=edge_id, properties=properties + ) + + async def parse_path(self, cell): + """ + Parse the cell to a path. + """ + nodes = await self.parse_scalar(cell[0]) + edges = await self.parse_scalar(cell[1]) + return Path(nodes, edges) + + async def parse_map(self, cell): + """ + Parse the cell to a map. + """ + m = OrderedDict() + n_entries = len(cell) + + # A map is an array of key value pairs. + # 1. key (string) + # 2. array: (value type, value) + for i in range(0, n_entries, 2): + key = self.parse_string(cell[i]) + m[key] = await self.parse_scalar(cell[i + 1]) + + return m + + async def parse_array(self, value): + """ + Parse array value. + """ + scalar = [await self.parse_scalar(value[i]) for i in range(len(value))] + return scalar diff --git a/.venv/Lib/site-packages/redis/commands/helpers.py b/.venv/Lib/site-packages/redis/commands/helpers.py new file mode 100644 index 00000000..324d981d --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/helpers.py @@ -0,0 +1,166 @@ +import copy +import random +import string +from typing import List, Tuple + +import redis +from redis.typing import KeysT, KeyT + + +def list_or_args(keys: KeysT, args: Tuple[KeyT, ...]) -> List[KeyT]: + # returns a single new list combining keys and args + try: + iter(keys) + # a string or bytes instance can be iterated, but indicates + # keys wasn't passed as a list + if isinstance(keys, (bytes, str)): + keys = [keys] + else: + keys = list(keys) + except TypeError: + keys = [keys] + if args: + keys.extend(args) + return keys + + +def nativestr(x): + """Return the decoded binary string, or a string, depending on type.""" + r = x.decode("utf-8", "replace") if isinstance(x, bytes) else x + if r == "null": + return + return r + + +def delist(x): + """Given a list of binaries, return the stringified version.""" + if x is None: + return x + return [nativestr(obj) for obj in x] + + +def parse_to_list(response): + """Optimistically parse the response to a list.""" + res = [] + + if response is None: + return res + + for item in response: + try: + res.append(int(item)) + except ValueError: + try: + res.append(float(item)) + except ValueError: + res.append(nativestr(item)) + except TypeError: + res.append(None) + return res + + +def parse_list_to_dict(response): + res = {} + for i in range(0, len(response), 2): + if isinstance(response[i], list): + res["Child iterators"].append(parse_list_to_dict(response[i])) + elif isinstance(response[i + 1], list): + res["Child iterators"] = [parse_list_to_dict(response[i + 1])] + else: + try: + res[response[i]] = float(response[i + 1]) + except (TypeError, ValueError): + res[response[i]] = response[i + 1] + return res + + +def parse_to_dict(response): + if response is None: + return {} + + res = {} + for det in response: + if isinstance(det[1], list): + res[det[0]] = parse_list_to_dict(det[1]) + else: + try: # try to set the attribute. may be provided without value + try: # try to convert the value to float + res[det[0]] = float(det[1]) + except (TypeError, ValueError): + res[det[0]] = det[1] + except IndexError: + pass + return res + + +def random_string(length=10): + """ + Returns a random N character long string. + """ + return "".join( # nosec + random.choice(string.ascii_lowercase) for x in range(length) + ) + + +def quote_string(v): + """ + RedisGraph strings must be quoted, + quote_string wraps given v with quotes incase + v is a string. + """ + + if isinstance(v, bytes): + v = v.decode() + elif not isinstance(v, str): + return v + if len(v) == 0: + return '""' + + v = v.replace("\\", "\\\\") + v = v.replace('"', '\\"') + + return f'"{v}"' + + +def decode_dict_keys(obj): + """Decode the keys of the given dictionary with utf-8.""" + newobj = copy.copy(obj) + for k in obj.keys(): + if isinstance(k, bytes): + newobj[k.decode("utf-8")] = newobj[k] + newobj.pop(k) + return newobj + + +def stringify_param_value(value): + """ + Turn a parameter value into a string suitable for the params header of + a Cypher command. + You may pass any value that would be accepted by `json.dumps()`. + + Ways in which output differs from that of `str()`: + * Strings are quoted. + * None --> "null". + * In dictionaries, keys are _not_ quoted. + + :param value: The parameter value to be turned into a string. + :return: string + """ + + if isinstance(value, str): + return quote_string(value) + elif value is None: + return "null" + elif isinstance(value, (list, tuple)): + return f'[{",".join(map(stringify_param_value, value))}]' + elif isinstance(value, dict): + return f'{{{",".join(f"{k}:{stringify_param_value(v)}" for k, v in value.items())}}}' # noqa + else: + return str(value) + + +def get_protocol_version(client): + if isinstance(client, redis.Redis) or isinstance(client, redis.asyncio.Redis): + return client.connection_pool.connection_kwargs.get("protocol") + elif isinstance(client, redis.cluster.AbstractRedisCluster): + return client.nodes_manager.connection_kwargs.get("protocol") diff --git a/.venv/Lib/site-packages/redis/commands/json/__init__.py b/.venv/Lib/site-packages/redis/commands/json/__init__.py new file mode 100644 index 00000000..01077e6b --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/json/__init__.py @@ -0,0 +1,147 @@ +from json import JSONDecodeError, JSONDecoder, JSONEncoder + +import redis + +from ..helpers import get_protocol_version, nativestr +from .commands import JSONCommands +from .decoders import bulk_of_jsons, decode_list + + +class JSON(JSONCommands): + """ + Create a client for talking to json. + + :param decoder: + :type json.JSONDecoder: An instance of json.JSONDecoder + + :param encoder: + :type json.JSONEncoder: An instance of json.JSONEncoder + """ + + def __init__( + self, client, version=None, decoder=JSONDecoder(), encoder=JSONEncoder() + ): + """ + Create a client for talking to json. + + :param decoder: + :type json.JSONDecoder: An instance of json.JSONDecoder + + :param encoder: + :type json.JSONEncoder: An instance of json.JSONEncoder + """ + # Set the module commands' callbacks + self._MODULE_CALLBACKS = { + "JSON.ARRPOP": self._decode, + "JSON.DEBUG": self._decode, + "JSON.GET": self._decode, + "JSON.MERGE": lambda r: r and nativestr(r) == "OK", + "JSON.MGET": bulk_of_jsons(self._decode), + "JSON.MSET": lambda r: r and nativestr(r) == "OK", + "JSON.RESP": self._decode, + "JSON.SET": lambda r: r and nativestr(r) == "OK", + "JSON.TOGGLE": self._decode, + } + + _RESP2_MODULE_CALLBACKS = { + "JSON.ARRAPPEND": self._decode, + "JSON.ARRINDEX": self._decode, + "JSON.ARRINSERT": self._decode, + "JSON.ARRLEN": self._decode, + "JSON.ARRTRIM": self._decode, + "JSON.CLEAR": int, + "JSON.DEL": int, + "JSON.FORGET": int, + "JSON.GET": self._decode, + "JSON.NUMINCRBY": self._decode, + "JSON.NUMMULTBY": self._decode, + "JSON.OBJKEYS": self._decode, + "JSON.STRAPPEND": self._decode, + "JSON.OBJLEN": self._decode, + "JSON.STRLEN": self._decode, + "JSON.TOGGLE": self._decode, + } + + _RESP3_MODULE_CALLBACKS = {} + + self.client = client + self.execute_command = client.execute_command + self.MODULE_VERSION = version + + if get_protocol_version(self.client) in ["3", 3]: + self._MODULE_CALLBACKS.update(_RESP3_MODULE_CALLBACKS) + else: + self._MODULE_CALLBACKS.update(_RESP2_MODULE_CALLBACKS) + + for key, value in self._MODULE_CALLBACKS.items(): + self.client.set_response_callback(key, value) + + self.__encoder__ = encoder + self.__decoder__ = decoder + + def _decode(self, obj): + """Get the decoder.""" + if obj is None: + return obj + + try: + x = self.__decoder__.decode(obj) + if x is None: + raise TypeError + return x + except TypeError: + try: + return self.__decoder__.decode(obj.decode()) + except AttributeError: + return decode_list(obj) + except (AttributeError, JSONDecodeError): + return decode_list(obj) + + def _encode(self, obj): + """Get the encoder.""" + return self.__encoder__.encode(obj) + + def pipeline(self, transaction=True, shard_hint=None): + """Creates a pipeline for the JSON module, that can be used for executing + JSON commands, as well as classic core commands. + + Usage example: + + r = redis.Redis() + pipe = r.json().pipeline() + pipe.jsonset('foo', '.', {'hello!': 'world'}) + pipe.jsonget('foo') + pipe.jsonget('notakey') + """ + if isinstance(self.client, redis.RedisCluster): + p = ClusterPipeline( + nodes_manager=self.client.nodes_manager, + commands_parser=self.client.commands_parser, + startup_nodes=self.client.nodes_manager.startup_nodes, + result_callbacks=self.client.result_callbacks, + cluster_response_callbacks=self.client.cluster_response_callbacks, + cluster_error_retry_attempts=self.client.cluster_error_retry_attempts, + read_from_replicas=self.client.read_from_replicas, + reinitialize_steps=self.client.reinitialize_steps, + lock=self.client._lock, + ) + + else: + p = Pipeline( + connection_pool=self.client.connection_pool, + response_callbacks=self._MODULE_CALLBACKS, + transaction=transaction, + shard_hint=shard_hint, + ) + + p._encode = self._encode + p._decode = self._decode + return p + + +class ClusterPipeline(JSONCommands, redis.cluster.ClusterPipeline): + """Cluster pipeline for the module.""" + + +class Pipeline(JSONCommands, redis.client.Pipeline): + """Pipeline for the module.""" diff --git a/.venv/Lib/site-packages/redis/commands/json/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/json/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1d16612c5c8070c24aee6bbb177e607d167cbd56 GIT binary patch literal 6838 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 Q;fur1So!B=o-#cAAKIY6od5s; literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/json/__pycache__/decoders.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/json/__pycache__/decoders.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a4dabe0ed7dc3cb7dc5e2cd0d253522b3ddc0725 GIT binary patch literal 2862 zcmai0TW=Fb6rNe%V<*mqP(cD<jg9aEK^^q6i6zThjt60g0xDbhA57maKQp%s7zX z2)9KdL6$HTh#*lZPZUI7``Euw#gZSal_DWkeL(7iRa6P_)H7qp*ru1U_v~EG%sDgX zoA2z8?d@#{%ANk7$#*`4eiMzYqSPv{k3i)SGLV5SG*x}$DQqZ)$5K+BDGx@5_cogH z8a|Ld!w=GL1V9E1Jc(k#S7M>Fuf%%Ku^X~AZY~hUsgA`!t%y+%Jg>V!+yQ$lD2WYx zJGhLqVijfS;(3y`G@Yo7P*bzaC1R)(ljqK=3!0T7OucUMIn|lDN_5Ut(^j=M70OJ; znpZVSwMCT@mUe7L)V-F;cq}f*o1E~1?H=L8c@PirBg7kA%%Z2zdQtB=jxP5m!0lzc ztYnpMIux|($tuk{S(L@&uvUJ17QrU)*%%xEu`?+`HBMq)7tgpp(>BNr*K2Z;a4rkg)PK!|%AGaJ`v)Ix2bTR@y zuunj|$)U}@q4h5wk3Si&ASE;?#p-7(Ckh{zqdgnZfpTB}+SuBK$A_LAD&WHK{otE& zv~wl+8YZLX5H~8;q8%WZi1F7dZHJfJ-ejA0L0>@V41xfol{T-htAhSPL{Ow7_bH8n zUQ_J+&>;cz2UMCPcNKc7r8R~CF0@{c=$4jvKZWN-y#r!Bv8-^oB3mV^aAC1lp2F5% zi0#Qj4`gvx*|F6G3}lsc5!UyLft&Fnu#&~=4R+p5X~h;s`Oj)sK)1O-cA)u?t>b*F{NX|W*fhv8m$*er+~`n|m?|7C%# zUddm{oh-L^-n(@7(&|)xs)9Veol>me&2Vo)`=PfO9w>ze1m1R*_r{-H`zf??vM~1O z@b`z;P8EBGN`4OQ?<} zEl1;$NmWi4M|F+sbLtGywG1o{P@_aOS&e2H0iNNe4q!_rVFd64s{A?u{OtvMD!HM- z>LjL)9gOc+fs;f<`n?pok}y7s!!tz16*b z;oOOGAW~4iy_vhY8QoU6xHk6S((0}Jt&QOBm+if|lU4PFHCBuamLh{q>fMEdYh4cx zuP*18H-i1;a7S+9eK3mKEy4IFRGOJ8i+G(yfPN|x)unyY|B8N7jBh~-H?^j8}Sb{F5L(~!IPxS?j1HHg!yCcjsunAT`bwd`3c^xr4X@tJ-`oi9 zEQcex)74!BsW^8kHth!Hh?Ry<5V;4L^<{>r?n}5^J#CTQWkz`$98Wn$#v(^)9QwpY znFFHY!5EiOI46H)6w1lpOEj?2{IB@KxTAvVqCbGUE2u8EMRBx(>S8F2+l6wgkQ@0M DtQ(98 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/json/__pycache__/path.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/json/__pycache__/path.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef363fddad68227e212ae434be27acc542e248ae GIT binary patch literal 1087 zcmZuv%}(1u5FR^DVrT*sDzy?Ee5-Q69I2|dr%F^+n^r(u$+ENgH=shC`yL#TPe^@%AbR4|89Rm|7;8VzpJu+9-Cy8~kwS?mQI=dWirt{-#EbU(#g>u)@NSGlVq6yc^ocD{&w;o5s5+H>Cpo308HvDm>RZ(Ar= z3LdB>KMq4L;%aF}#nBQCVt2l$6U2p))tjQx?Q5IZs|kcYj4CiQcc7$+mS1cd^=#|e zsE^PX!oIc-jQp952Y>nA+ZDL5NPNrJx9KUttvFxBz2nn{H;B`Q-8|OPDkc%PhMpQq zw6{`&Vv2}ZmL!U)$yg8t31hu_Hbr4Rz@Vxl^x^#R{DE;;JHRg=gzl-3>pPo44-Nu5 zMFjBnw5F_~-O%I|{uCwO^riRlU*FuEraXG-eK?z*JKR4t=d-5G#sqPVyihQfPBIq8 zyxS(d#@N@c*B(czjPclKOcM9BrV@M>ekhVw%q5kT#8b`^&?CueXPc089T^Zy^%#a>*cu-AY7E7GCOc{hpCqr$U6p8BkeBaEvZ`*_mXwJ&E(2_ ikq`GuKEbSv&N3>alBQ`ReOkk^cj1D3fA0xo{r&+AAOhI{ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/json/_util.py b/.venv/Lib/site-packages/redis/commands/json/_util.py new file mode 100644 index 00000000..3400bcd6 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/json/_util.py @@ -0,0 +1,3 @@ +from typing import Any, Dict, List, Union + +JsonType = Union[str, int, float, bool, None, Dict[str, Any], List[Any]] diff --git a/.venv/Lib/site-packages/redis/commands/json/commands.py b/.venv/Lib/site-packages/redis/commands/json/commands.py new file mode 100644 index 00000000..0f92e0d6 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/json/commands.py @@ -0,0 +1,429 @@ +import os +from json import JSONDecodeError, loads +from typing import Dict, List, Optional, Tuple, Union + +from redis.exceptions import DataError +from redis.utils import deprecated_function + +from ._util import JsonType +from .decoders import decode_dict_keys +from .path import Path + + +class JSONCommands: + """json commands.""" + + def arrappend( + self, name: str, path: Optional[str] = Path.root_path(), *args: List[JsonType] + ) -> List[Union[int, None]]: + """Append the objects ``args`` to the array under the + ``path` in key ``name``. + + For more information see `JSON.ARRAPPEND `_.. + """ # noqa + pieces = [name, str(path)] + for o in args: + pieces.append(self._encode(o)) + return self.execute_command("JSON.ARRAPPEND", *pieces) + + def arrindex( + self, + name: str, + path: str, + scalar: int, + start: Optional[int] = None, + stop: Optional[int] = None, + ) -> List[Union[int, None]]: + """ + Return the index of ``scalar`` in the JSON array under ``path`` at key + ``name``. + + The search can be limited using the optional inclusive ``start`` + and exclusive ``stop`` indices. + + For more information see `JSON.ARRINDEX `_. + """ # noqa + pieces = [name, str(path), self._encode(scalar)] + if start is not None: + pieces.append(start) + if stop is not None: + pieces.append(stop) + + return self.execute_command("JSON.ARRINDEX", *pieces) + + def arrinsert( + self, name: str, path: str, index: int, *args: List[JsonType] + ) -> List[Union[int, None]]: + """Insert the objects ``args`` to the array at index ``index`` + under the ``path` in key ``name``. + + For more information see `JSON.ARRINSERT `_. + """ # noqa + pieces = [name, str(path), index] + for o in args: + pieces.append(self._encode(o)) + return self.execute_command("JSON.ARRINSERT", *pieces) + + def arrlen( + self, name: str, path: Optional[str] = Path.root_path() + ) -> List[Union[int, None]]: + """Return the length of the array JSON value under ``path`` + at key``name``. + + For more information see `JSON.ARRLEN `_. + """ # noqa + return self.execute_command("JSON.ARRLEN", name, str(path)) + + def arrpop( + self, + name: str, + path: Optional[str] = Path.root_path(), + index: Optional[int] = -1, + ) -> List[Union[str, None]]: + """Pop the element at ``index`` in the array JSON value under + ``path`` at key ``name``. + + For more information see `JSON.ARRPOP `_. + """ # noqa + return self.execute_command("JSON.ARRPOP", name, str(path), index) + + def arrtrim( + self, name: str, path: str, start: int, stop: int + ) -> List[Union[int, None]]: + """Trim the array JSON value under ``path`` at key ``name`` to the + inclusive range given by ``start`` and ``stop``. + + For more information see `JSON.ARRTRIM `_. + """ # noqa + return self.execute_command("JSON.ARRTRIM", name, str(path), start, stop) + + def type(self, name: str, path: Optional[str] = Path.root_path()) -> List[str]: + """Get the type of the JSON value under ``path`` from key ``name``. + + For more information see `JSON.TYPE `_. + """ # noqa + return self.execute_command("JSON.TYPE", name, str(path)) + + def resp(self, name: str, path: Optional[str] = Path.root_path()) -> List: + """Return the JSON value under ``path`` at key ``name``. + + For more information see `JSON.RESP `_. + """ # noqa + return self.execute_command("JSON.RESP", name, str(path)) + + def objkeys( + self, name: str, path: Optional[str] = Path.root_path() + ) -> List[Union[List[str], None]]: + """Return the key names in the dictionary JSON value under ``path`` at + key ``name``. + + For more information see `JSON.OBJKEYS `_. + """ # noqa + return self.execute_command("JSON.OBJKEYS", name, str(path)) + + def objlen(self, name: str, path: Optional[str] = Path.root_path()) -> int: + """Return the length of the dictionary JSON value under ``path`` at key + ``name``. + + For more information see `JSON.OBJLEN `_. + """ # noqa + return self.execute_command("JSON.OBJLEN", name, str(path)) + + def numincrby(self, name: str, path: str, number: int) -> str: + """Increment the numeric (integer or floating point) JSON value under + ``path`` at key ``name`` by the provided ``number``. + + For more information see `JSON.NUMINCRBY `_. + """ # noqa + return self.execute_command( + "JSON.NUMINCRBY", name, str(path), self._encode(number) + ) + + @deprecated_function(version="4.0.0", reason="deprecated since redisjson 1.0.0") + def nummultby(self, name: str, path: str, number: int) -> str: + """Multiply the numeric (integer or floating point) JSON value under + ``path`` at key ``name`` with the provided ``number``. + + For more information see `JSON.NUMMULTBY `_. + """ # noqa + return self.execute_command( + "JSON.NUMMULTBY", name, str(path), self._encode(number) + ) + + def clear(self, name: str, path: Optional[str] = Path.root_path()) -> int: + """Empty arrays and objects (to have zero slots/keys without deleting the + array/object). + + Return the count of cleared paths (ignoring non-array and non-objects + paths). + + For more information see `JSON.CLEAR `_. + """ # noqa + return self.execute_command("JSON.CLEAR", name, str(path)) + + def delete(self, key: str, path: Optional[str] = Path.root_path()) -> int: + """Delete the JSON value stored at key ``key`` under ``path``. + + For more information see `JSON.DEL `_. + """ + return self.execute_command("JSON.DEL", key, str(path)) + + # forget is an alias for delete + forget = delete + + def get( + self, name: str, *args, no_escape: Optional[bool] = False + ) -> List[JsonType]: + """ + Get the object stored as a JSON value at key ``name``. + + ``args`` is zero or more paths, and defaults to root path + ```no_escape`` is a boolean flag to add no_escape option to get + non-ascii characters + + For more information see `JSON.GET `_. + """ # noqa + pieces = [name] + if no_escape: + pieces.append("noescape") + + if len(args) == 0: + pieces.append(Path.root_path()) + + else: + for p in args: + pieces.append(str(p)) + + # Handle case where key doesn't exist. The JSONDecoder would raise a + # TypeError exception since it can't decode None + try: + return self.execute_command("JSON.GET", *pieces) + except TypeError: + return None + + def mget(self, keys: List[str], path: str) -> List[JsonType]: + """ + Get the objects stored as a JSON values under ``path``. ``keys`` + is a list of one or more keys. + + For more information see `JSON.MGET `_. + """ # noqa + pieces = [] + pieces += keys + pieces.append(str(path)) + return self.execute_command("JSON.MGET", *pieces) + + def set( + self, + name: str, + path: str, + obj: JsonType, + nx: Optional[bool] = False, + xx: Optional[bool] = False, + decode_keys: Optional[bool] = False, + ) -> Optional[str]: + """ + Set the JSON value at key ``name`` under the ``path`` to ``obj``. + + ``nx`` if set to True, set ``value`` only if it does not exist. + ``xx`` if set to True, set ``value`` only if it exists. + ``decode_keys`` If set to True, the keys of ``obj`` will be decoded + with utf-8. + + For the purpose of using this within a pipeline, this command is also + aliased to JSON.SET. + + For more information see `JSON.SET `_. + """ + if decode_keys: + obj = decode_dict_keys(obj) + + pieces = [name, str(path), self._encode(obj)] + + # Handle existential modifiers + if nx and xx: + raise Exception( + "nx and xx are mutually exclusive: use one, the " + "other or neither - but not both" + ) + elif nx: + pieces.append("NX") + elif xx: + pieces.append("XX") + return self.execute_command("JSON.SET", *pieces) + + def mset(self, triplets: List[Tuple[str, str, JsonType]]) -> Optional[str]: + """ + Set the JSON value at key ``name`` under the ``path`` to ``obj`` + for one or more keys. + + ``triplets`` is a list of one or more triplets of key, path, value. + + For the purpose of using this within a pipeline, this command is also + aliased to JSON.MSET. + + For more information see `JSON.MSET `_. + """ + pieces = [] + for triplet in triplets: + pieces.extend([triplet[0], str(triplet[1]), self._encode(triplet[2])]) + return self.execute_command("JSON.MSET", *pieces) + + def merge( + self, + name: str, + path: str, + obj: JsonType, + decode_keys: Optional[bool] = False, + ) -> Optional[str]: + """ + Merges a given JSON value into matching paths. Consequently, JSON values + at matching paths are updated, deleted, or expanded with new children + + ``decode_keys`` If set to True, the keys of ``obj`` will be decoded + with utf-8. + + For more information see `JSON.MERGE `_. + """ + if decode_keys: + obj = decode_dict_keys(obj) + + pieces = [name, str(path), self._encode(obj)] + + return self.execute_command("JSON.MERGE", *pieces) + + def set_file( + self, + name: str, + path: str, + file_name: str, + nx: Optional[bool] = False, + xx: Optional[bool] = False, + decode_keys: Optional[bool] = False, + ) -> Optional[str]: + """ + Set the JSON value at key ``name`` under the ``path`` to the content + of the json file ``file_name``. + + ``nx`` if set to True, set ``value`` only if it does not exist. + ``xx`` if set to True, set ``value`` only if it exists. + ``decode_keys`` If set to True, the keys of ``obj`` will be decoded + with utf-8. + + """ + + with open(file_name, "r") as fp: + file_content = loads(fp.read()) + + return self.set(name, path, file_content, nx=nx, xx=xx, decode_keys=decode_keys) + + def set_path( + self, + json_path: str, + root_folder: str, + nx: Optional[bool] = False, + xx: Optional[bool] = False, + decode_keys: Optional[bool] = False, + ) -> List[Dict[str, bool]]: + """ + Iterate over ``root_folder`` and set each JSON file to a value + under ``json_path`` with the file name as the key. + + ``nx`` if set to True, set ``value`` only if it does not exist. + ``xx`` if set to True, set ``value`` only if it exists. + ``decode_keys`` If set to True, the keys of ``obj`` will be decoded + with utf-8. + + """ + set_files_result = {} + for root, dirs, files in os.walk(root_folder): + for file in files: + file_path = os.path.join(root, file) + try: + file_name = file_path.rsplit(".")[0] + self.set_file( + file_name, + json_path, + file_path, + nx=nx, + xx=xx, + decode_keys=decode_keys, + ) + set_files_result[file_path] = True + except JSONDecodeError: + set_files_result[file_path] = False + + return set_files_result + + def strlen(self, name: str, path: Optional[str] = None) -> List[Union[int, None]]: + """Return the length of the string JSON value under ``path`` at key + ``name``. + + For more information see `JSON.STRLEN `_. + """ # noqa + pieces = [name] + if path is not None: + pieces.append(str(path)) + return self.execute_command("JSON.STRLEN", *pieces) + + def toggle( + self, name: str, path: Optional[str] = Path.root_path() + ) -> Union[bool, List[Optional[int]]]: + """Toggle boolean value under ``path`` at key ``name``. + returning the new value. + + For more information see `JSON.TOGGLE `_. + """ # noqa + return self.execute_command("JSON.TOGGLE", name, str(path)) + + def strappend( + self, name: str, value: str, path: Optional[int] = Path.root_path() + ) -> Union[int, List[Optional[int]]]: + """Append to the string JSON value. If two options are specified after + the key name, the path is determined to be the first. If a single + option is passed, then the root_path (i.e Path.root_path()) is used. + + For more information see `JSON.STRAPPEND `_. + """ # noqa + pieces = [name, str(path), self._encode(value)] + return self.execute_command("JSON.STRAPPEND", *pieces) + + def debug( + self, + subcommand: str, + key: Optional[str] = None, + path: Optional[str] = Path.root_path(), + ) -> Union[int, List[str]]: + """Return the memory usage in bytes of a value under ``path`` from + key ``name``. + + For more information see `JSON.DEBUG `_. + """ # noqa + valid_subcommands = ["MEMORY", "HELP"] + if subcommand not in valid_subcommands: + raise DataError("The only valid subcommands are ", str(valid_subcommands)) + pieces = [subcommand] + if subcommand == "MEMORY": + if key is None: + raise DataError("No key specified") + pieces.append(key) + pieces.append(str(path)) + return self.execute_command("JSON.DEBUG", *pieces) + + @deprecated_function( + version="4.0.0", reason="redisjson-py supported this, call get directly." + ) + def jsonget(self, *args, **kwargs): + return self.get(*args, **kwargs) + + @deprecated_function( + version="4.0.0", reason="redisjson-py supported this, call get directly." + ) + def jsonmget(self, *args, **kwargs): + return self.mget(*args, **kwargs) + + @deprecated_function( + version="4.0.0", reason="redisjson-py supported this, call get directly." + ) + def jsonset(self, *args, **kwargs): + return self.set(*args, **kwargs) diff --git a/.venv/Lib/site-packages/redis/commands/json/decoders.py b/.venv/Lib/site-packages/redis/commands/json/decoders.py new file mode 100644 index 00000000..b9384711 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/json/decoders.py @@ -0,0 +1,60 @@ +import copy +import re + +from ..helpers import nativestr + + +def bulk_of_jsons(d): + """Replace serialized JSON values with objects in a + bulk array response (list). + """ + + def _f(b): + for index, item in enumerate(b): + if item is not None: + b[index] = d(item) + return b + + return _f + + +def decode_dict_keys(obj): + """Decode the keys of the given dictionary with utf-8.""" + newobj = copy.copy(obj) + for k in obj.keys(): + if isinstance(k, bytes): + newobj[k.decode("utf-8")] = newobj[k] + newobj.pop(k) + return newobj + + +def unstring(obj): + """ + Attempt to parse string to native integer formats. + One can't simply call int/float in a try/catch because there is a + semantic difference between (for example) 15.0 and 15. + """ + floatreg = "^\\d+.\\d+$" + match = re.findall(floatreg, obj) + if match != []: + return float(match[0]) + + intreg = "^\\d+$" + match = re.findall(intreg, obj) + if match != []: + return int(match[0]) + return obj + + +def decode_list(b): + """ + Given a non-deserializable object, make a best effort to + return a useful set of results. + """ + if isinstance(b, list): + return [nativestr(obj) for obj in b] + elif isinstance(b, bytes): + return unstring(nativestr(b)) + elif isinstance(b, str): + return unstring(b) + return b diff --git a/.venv/Lib/site-packages/redis/commands/json/path.py b/.venv/Lib/site-packages/redis/commands/json/path.py new file mode 100644 index 00000000..bfb0ab2d --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/json/path.py @@ -0,0 +1,16 @@ +class Path: + """This class represents a path in a JSON value.""" + + strPath = "" + + @staticmethod + def root_path(): + """Return the root path's string representation.""" + return "." + + def __init__(self, path): + """Make a new path based on the string representation in `path`.""" + self.strPath = path + + def __repr__(self): + return self.strPath diff --git a/.venv/Lib/site-packages/redis/commands/redismodules.py b/.venv/Lib/site-packages/redis/commands/redismodules.py new file mode 100644 index 00000000..7e2045a7 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/redismodules.py @@ -0,0 +1,103 @@ +from json import JSONDecoder, JSONEncoder + + +class RedisModuleCommands: + """This class contains the wrapper functions to bring supported redis + modules into the command namespace. + """ + + def json(self, encoder=JSONEncoder(), decoder=JSONDecoder()): + """Access the json namespace, providing support for redis json.""" + + from .json import JSON + + jj = JSON(client=self, encoder=encoder, decoder=decoder) + return jj + + def ft(self, index_name="idx"): + """Access the search namespace, providing support for redis search.""" + + from .search import Search + + s = Search(client=self, index_name=index_name) + return s + + def ts(self): + """Access the timeseries namespace, providing support for + redis timeseries data. + """ + + from .timeseries import TimeSeries + + s = TimeSeries(client=self) + return s + + def bf(self): + """Access the bloom namespace.""" + + from .bf import BFBloom + + bf = BFBloom(client=self) + return bf + + def cf(self): + """Access the bloom namespace.""" + + from .bf import CFBloom + + cf = CFBloom(client=self) + return cf + + def cms(self): + """Access the bloom namespace.""" + + from .bf import CMSBloom + + cms = CMSBloom(client=self) + return cms + + def topk(self): + """Access the bloom namespace.""" + + from .bf import TOPKBloom + + topk = TOPKBloom(client=self) + return topk + + def tdigest(self): + """Access the bloom namespace.""" + + from .bf import TDigestBloom + + tdigest = TDigestBloom(client=self) + return tdigest + + def graph(self, index_name="idx"): + """Access the graph namespace, providing support for + redis graph data. + """ + + from .graph import Graph + + g = Graph(client=self, name=index_name) + return g + + +class AsyncRedisModuleCommands(RedisModuleCommands): + def ft(self, index_name="idx"): + """Access the search namespace, providing support for redis search.""" + + from .search import AsyncSearch + + s = AsyncSearch(client=self, index_name=index_name) + return s + + def graph(self, index_name="idx"): + """Access the graph namespace, providing support for + redis graph data. + """ + + from .graph import AsyncGraph + + g = AsyncGraph(client=self, name=index_name) + return g diff --git a/.venv/Lib/site-packages/redis/commands/search/__init__.py b/.venv/Lib/site-packages/redis/commands/search/__init__.py new file mode 100644 index 00000000..a2bb23b7 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/search/__init__.py @@ -0,0 +1,189 @@ +import redis + +from ...asyncio.client import Pipeline as AsyncioPipeline +from .commands import ( + AGGREGATE_CMD, + CONFIG_CMD, + INFO_CMD, + PROFILE_CMD, + SEARCH_CMD, + SPELLCHECK_CMD, + SYNDUMP_CMD, + AsyncSearchCommands, + SearchCommands, +) + + +class Search(SearchCommands): + """ + Create a client for talking to search. + It abstracts the API of the module and lets you just use the engine. + """ + + class BatchIndexer: + """ + A batch indexer allows you to automatically batch + document indexing in pipelines, flushing it every N documents. + """ + + def __init__(self, client, chunk_size=1000): + self.client = client + self.execute_command = client.execute_command + self._pipeline = client.pipeline(transaction=False, shard_hint=None) + self.total = 0 + self.chunk_size = chunk_size + self.current_chunk = 0 + + def __del__(self): + if self.current_chunk: + self.commit() + + def add_document( + self, + doc_id, + nosave=False, + score=1.0, + payload=None, + replace=False, + partial=False, + no_create=False, + **fields, + ): + """ + Add a document to the batch query + """ + self.client._add_document( + doc_id, + conn=self._pipeline, + nosave=nosave, + score=score, + payload=payload, + replace=replace, + partial=partial, + no_create=no_create, + **fields, + ) + self.current_chunk += 1 + self.total += 1 + if self.current_chunk >= self.chunk_size: + self.commit() + + def add_document_hash(self, doc_id, score=1.0, replace=False): + """ + Add a hash to the batch query + """ + self.client._add_document_hash( + doc_id, conn=self._pipeline, score=score, replace=replace + ) + self.current_chunk += 1 + self.total += 1 + if self.current_chunk >= self.chunk_size: + self.commit() + + def commit(self): + """ + Manually commit and flush the batch indexing query + """ + self._pipeline.execute() + self.current_chunk = 0 + + def __init__(self, client, index_name="idx"): + """ + Create a new Client for the given index_name. + The default name is `idx` + + If conn is not None, we employ an already existing redis connection + """ + self._MODULE_CALLBACKS = {} + self.client = client + self.index_name = index_name + self.execute_command = client.execute_command + self._pipeline = client.pipeline + self._RESP2_MODULE_CALLBACKS = { + INFO_CMD: self._parse_info, + SEARCH_CMD: self._parse_search, + AGGREGATE_CMD: self._parse_aggregate, + PROFILE_CMD: self._parse_profile, + SPELLCHECK_CMD: self._parse_spellcheck, + CONFIG_CMD: self._parse_config_get, + SYNDUMP_CMD: self._parse_syndump, + } + + def pipeline(self, transaction=True, shard_hint=None): + """Creates a pipeline for the SEARCH module, that can be used for executing + SEARCH commands, as well as classic core commands. + """ + p = Pipeline( + connection_pool=self.client.connection_pool, + response_callbacks=self._MODULE_CALLBACKS, + transaction=transaction, + shard_hint=shard_hint, + ) + p.index_name = self.index_name + return p + + +class AsyncSearch(Search, AsyncSearchCommands): + class BatchIndexer(Search.BatchIndexer): + """ + A batch indexer allows you to automatically batch + document indexing in pipelines, flushing it every N documents. + """ + + async def add_document( + self, + doc_id, + nosave=False, + score=1.0, + payload=None, + replace=False, + partial=False, + no_create=False, + **fields, + ): + """ + Add a document to the batch query + """ + self.client._add_document( + doc_id, + conn=self._pipeline, + nosave=nosave, + score=score, + payload=payload, + replace=replace, + partial=partial, + no_create=no_create, + **fields, + ) + self.current_chunk += 1 + self.total += 1 + if self.current_chunk >= self.chunk_size: + await self.commit() + + async def commit(self): + """ + Manually commit and flush the batch indexing query + """ + await self._pipeline.execute() + self.current_chunk = 0 + + def pipeline(self, transaction=True, shard_hint=None): + """Creates a pipeline for the SEARCH module, that can be used for executing + SEARCH commands, as well as classic core commands. + """ + p = AsyncPipeline( + connection_pool=self.client.connection_pool, + response_callbacks=self._MODULE_CALLBACKS, + transaction=transaction, + shard_hint=shard_hint, + ) + p.index_name = self.index_name + return p + + +class Pipeline(SearchCommands, redis.client.Pipeline): + """Pipeline for the module.""" + + +class AsyncPipeline(AsyncSearchCommands, AsyncioPipeline, Pipeline): + """AsyncPipeline for the module.""" diff --git a/.venv/Lib/site-packages/redis/commands/search/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/search/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bbc0d60d2fcb4e9f97c11f74f605267af60bbc92 GIT binary patch literal 7584 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 bYuh+0azr~zN2y3m##mycSs{VHsdN7wEuDK~ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/search/__pycache__/aggregation.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/search/__pycache__/aggregation.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8e9bca57ba3a77b3499db266f8e4e50c407a53c4 GIT binary patch literal 16474 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 OAFwAsT<1BX3I7M_EMsH< literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/search/__pycache__/document.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/search/__pycache__/document.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dc5ba9481407f11a9239c69712403696c9c6d11d GIT binary patch literal 1276 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/search/__pycache__/querystring.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/search/__pycache__/querystring.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f7b034530521466b4e269cf00d386a433e00a2a0 GIT binary patch literal 16254 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 HU=sSj0o_#2 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/search/__pycache__/reducers.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/search/__pycache__/reducers.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9689a62156e9de305ce9e2129788e2c84a8e760c GIT binary patch literal 9239 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/search/__pycache__/result.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/search/__pycache__/result.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..14116acff20e2b5bdae2f0c51cd47895f5dc504e GIT binary patch literal 2956 zcmb7GU2NOd6~31gsUJ(WmB@i$xH$Kc@bvsv(5Fr%I;<+QQ>gAlyU>Qg9CC@e0ONW^zoP zU12d|(0fQ>uOTIHhe7Bbynb5=DBMRV%|F7Rr?C^Z4AHcRre6RhlriM>ysBGr$DQ&{ z?BfYgZXy+}UOhK3HmG3u^lY+*c^-$>z>!QzjUOihDtHmr{7bYc2D=r zzxy04mPOB_-MZv>rxzjX;B&Hf^?m)njj9CT$NqtR4p-L&|G&m!UOrZL>U8gZx29vd z6Jcb>6z*-L_m3hgvA?D0`keg~UBR9wzrO~E3(i0QaQ=UZhx6*U4(-oi zhqKs@+7TtR$=I>m_)l2xebKIj?TChbYpK^pm-cRZExJF_zGU}yuMxxjyuPFaAh{#O z4KMv@V!tj-PMW$_D5#b>IeA)`)dizqX@)N41VxiQiFjE|^FC{k{9fo6SxwC;r-gR7 zXlg~ZL|r;Pp1WjOP@eXJ2u(0Tu|J~ZoWp3!Gd$)5E}4d&W*p9x4Wc^1g0zt{B!%>X zQ#$5wmSIUbC#0+siDGgBiXod0MaaOgCo~fsE(=i>SOL1j7PW%I=B0uYT2MFU z2r&qu1=!&wSg)?6`<#HO=CTe8^~{Mt*^&+2f+9!ysaFqlh;1BB&lSzOD0<*bh_cjz z!yDPGsag)!2)*?lR43+biYfXwLX*C>Hycys~|~(?KhhxeUi}6}kN=dAJ(?YPlS^9%&5KSkm4yRfN4^@Z1JXOxLdXhiU@h~}Dk55$Mm3VEf%>NKiR@S~At;)A1HYaMC zMm*h&r(HB29@(X&Ji8Mgs-CQ_ZNAlrk2K>W<#$`tzpN+E+|X)lZT2qzm$SF~8p#vQ zAQhQQa}OpkP=_a~wN7+-@6Qzi zIe2MGx4&By3?&a#zx^5hoI&672c7+zei;SM6@&gQ|DxC{ctztifu`MQ!NH|8LumRD z`sbC#WC)l^#}LRkP?{+OzH_=V#qW5ZdL9LG6}9?it7Ds!^}bnnwle=X<4cr=W*>tK zI+td>DmOo$4$?7oDX)s66A{I{p{(bq92Ld2bt%`j1Vs@b!sI`LXorOlIx-2;-x2va zFb^A{-$)*z`(myFxw`jr8I}vVh>|E;z#m|j{RIbS&`pXMbMNBnDBLLEFQ@**bk1{d zJe;_0X*s{Zh5)Jek?B=ZAJ!Wb+aAz TGZ<5ZKhAc2+mn~Lc!2&5$v(&# literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/search/__pycache__/suggestion.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/search/__pycache__/suggestion.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ce0deff385a44ca1f73b3f766583c0ff48b540a0 GIT binary patch literal 3031 zcmZ`5OKcNIbk@7;PvQXiIUxzK|HanhLSoG zQmN_#2M$z8B`W1aL2#|qLk}E!>CKURuvS8f)I*z_QRszB``)a*#tA&{zL|OR-kY~? z-p9XmbhHtGABKKq7lMTRg^LDg^~u^8Ocn?wRLPQ@l2jBz160iha%xglNPwIpRJ%i{ z{xCqu6L>vHYH}wCJE3(uIt`DLcw`kBYsw+D0{|QJv{D$bwAU>PylPRj0!=d`C})XozXk0UEiZCBsw& zBih}z@xsgu6KKKQl{N!ljO95K%yNX0G6YzWWrpyXj41{r1NRM^8=N@>ZZT?1b311^ zSD93iDmZr9&gHYr0a?axFfQqTdsfvxO1MGq3te5LZO+_KK6NW=r>GnBG^QKwM+vq5 zu2GmQ5C{EKhobTjR!@9Nk(mCxg-_kU=U-JZ08)5{1WLxqVTHO;Ivn;gEutQ(UT zGEWVbjc58OJo|x|=sQ+#p85 z4sj6BZSrrB^chRR<=DPTY+p&c+x{Guean6EN?#n7(Q5Ai3~eR&t$_eZ`+kE3&e0=l zTL3MPBAJEJgK@$)!7Q#wAHc8~RssbKj@)P=hY;Fep-1dSZgkvjQr+Br_uF!KfOo+% z9^hdZ67dKsuu?f@nr@qE=4@KX;yh}a*9)m^eJ5m^)J_9gg*bBcX^0(%qs6=vQ4gTU zL@Jg>@eooGL7EdW59qf4s|8d&TqB60f`uuemF zNHR!uNaV1)r5O%irZ^j*&8) z46vYHsR20awZdaED9bYo^Te<%`ic@4Co#S)6B8;g$wtVeM@v5MOqHLRl8>VE+7Am5JE9e~^r z)CrN9V{XLrQ-*%ywwrY?;X*f&1L_(k>}!H5R9wG+dD((FG`DqqK>1Y$4;9}7f*c;) zThc1w{_3{109n+eHzigYs&=5NmEQhF^^&>NQoS&ZcEP)L1n&8BC}yoagDQ^iYl5}SzlZfb zV%Fz-2(u^tYLt9^Z5|?~DOpsS9d{n0XV$-KzSF_>QHNF;ST$0f%mGJJN2?{4LId*< z6|-0|B=Fu1ny`FIXw?L=WL|Ty?$!Y^KrL#mUo=4$6ouT)%4ky)99<#{a=gvedCHn$ zu9{^Q--qxt+HhJC|yLbKPU5oU=>`x;PMjpNY^yG5qu}bH$8qp$$B`Te%cJ|&MSUhuo zTj`VPsWX*R7t1{pKb~FO{b2vnSC4w0ZeQN>VP)Xha?kNf&+#%m;}fN`)f1;HCoYs@ z6Zh!-*`>~B8|hnZWiLb zU@?y&>O<5I$knE7JL`3*VI&SB!tUp#-8P&dLJ2Ve==CP0VUt1>?b5d{jn)VZzxBxB znInhw=v`e0hipXNk$6xd9(04wtvu9W**&316r4=f`|E=jDa~1D=d18ZuPdMCcsE!} y#dm;es-h@WGFWbXR>)Af^{E9nDbO1?q8CVe+1%J^DDVLr(F>%#e8YzPvi|{ou(06( literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/search/_util.py b/.venv/Lib/site-packages/redis/commands/search/_util.py new file mode 100644 index 00000000..dd1dff33 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/search/_util.py @@ -0,0 +1,7 @@ +def to_string(s): + if isinstance(s, str): + return s + elif isinstance(s, bytes): + return s.decode("utf-8", "ignore") + else: + return s # Not a string we care about diff --git a/.venv/Lib/site-packages/redis/commands/search/aggregation.py b/.venv/Lib/site-packages/redis/commands/search/aggregation.py new file mode 100644 index 00000000..50d18f47 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/search/aggregation.py @@ -0,0 +1,372 @@ +from typing import List, Union + +FIELDNAME = object() + + +class Limit: + def __init__(self, offset: int = 0, count: int = 0) -> None: + self.offset = offset + self.count = count + + def build_args(self): + if self.count: + return ["LIMIT", str(self.offset), str(self.count)] + else: + return [] + + +class Reducer: + """ + Base reducer object for all reducers. + + See the `redisearch.reducers` module for the actual reducers. + """ + + NAME = None + + def __init__(self, *args: List[str]) -> None: + self._args = args + self._field = None + self._alias = None + + def alias(self, alias: str) -> "Reducer": + """ + Set the alias for this reducer. + + ### Parameters + + - **alias**: The value of the alias for this reducer. If this is the + special value `aggregation.FIELDNAME` then this reducer will be + aliased using the same name as the field upon which it operates. + Note that using `FIELDNAME` is only possible on reducers which + operate on a single field value. + + This method returns the `Reducer` object making it suitable for + chaining. + """ + if alias is FIELDNAME: + if not self._field: + raise ValueError("Cannot use FIELDNAME alias with no field") + # Chop off initial '@' + alias = self._field[1:] + self._alias = alias + return self + + @property + def args(self) -> List[str]: + return self._args + + +class SortDirection: + """ + This special class is used to indicate sort direction. + """ + + DIRSTRING = None + + def __init__(self, field: str) -> None: + self.field = field + + +class Asc(SortDirection): + """ + Indicate that the given field should be sorted in ascending order + """ + + DIRSTRING = "ASC" + + +class Desc(SortDirection): + """ + Indicate that the given field should be sorted in descending order + """ + + DIRSTRING = "DESC" + + +class AggregateRequest: + """ + Aggregation request which can be passed to `Client.aggregate`. + """ + + def __init__(self, query: str = "*") -> None: + """ + Create an aggregation request. This request may then be passed to + `client.aggregate()`. + + In order for the request to be usable, it must contain at least one + group. + + - **query** Query string for filtering records. + + All member methods (except `build_args()`) + return the object itself, making them useful for chaining. + """ + self._query = query + self._aggregateplan = [] + self._loadfields = [] + self._loadall = False + self._max = 0 + self._with_schema = False + self._verbatim = False + self._cursor = [] + self._dialect = None + + def load(self, *fields: List[str]) -> "AggregateRequest": + """ + Indicate the fields to be returned in the response. These fields are + returned in addition to any others implicitly specified. + + ### Parameters + + - **fields**: If fields not specified, all the fields will be loaded. + Otherwise, fields should be given in the format of `@field`. + """ + if fields: + self._loadfields.extend(fields) + else: + self._loadall = True + return self + + def group_by( + self, fields: List[str], *reducers: Union[Reducer, List[Reducer]] + ) -> "AggregateRequest": + """ + Specify by which fields to group the aggregation. + + ### Parameters + + - **fields**: Fields to group by. This can either be a single string, + or a list of strings. both cases, the field should be specified as + `@field`. + - **reducers**: One or more reducers. Reducers may be found in the + `aggregation` module. + """ + fields = [fields] if isinstance(fields, str) else fields + reducers = [reducers] if isinstance(reducers, Reducer) else reducers + + ret = ["GROUPBY", str(len(fields)), *fields] + for reducer in reducers: + ret += ["REDUCE", reducer.NAME, str(len(reducer.args))] + ret.extend(reducer.args) + if reducer._alias is not None: + ret += ["AS", reducer._alias] + + self._aggregateplan.extend(ret) + return self + + def apply(self, **kwexpr) -> "AggregateRequest": + """ + Specify one or more projection expressions to add to each result + + ### Parameters + + - **kwexpr**: One or more key-value pairs for a projection. The key is + the alias for the projection, and the value is the projection + expression itself, for example `apply(square_root="sqrt(@foo)")` + """ + for alias, expr in kwexpr.items(): + ret = ["APPLY", expr] + if alias is not None: + ret += ["AS", alias] + self._aggregateplan.extend(ret) + + return self + + def limit(self, offset: int, num: int) -> "AggregateRequest": + """ + Sets the limit for the most recent group or query. + + If no group has been defined yet (via `group_by()`) then this sets + the limit for the initial pool of results from the query. Otherwise, + this limits the number of items operated on from the previous group. + + Setting a limit on the initial search results may be useful when + attempting to execute an aggregation on a sample of a large data set. + + ### Parameters + + - **offset**: Result offset from which to begin paging + - **num**: Number of results to return + + + Example of sorting the initial results: + + ``` + AggregateRequest("@sale_amount:[10000, inf]")\ + .limit(0, 10)\ + .group_by("@state", r.count()) + ``` + + Will only group by the states found in the first 10 results of the + query `@sale_amount:[10000, inf]`. On the other hand, + + ``` + AggregateRequest("@sale_amount:[10000, inf]")\ + .limit(0, 1000)\ + .group_by("@state", r.count()\ + .limit(0, 10) + ``` + + Will group all the results matching the query, but only return the + first 10 groups. + + If you only wish to return a *top-N* style query, consider using + `sort_by()` instead. + + """ + _limit = Limit(offset, num) + self._aggregateplan.extend(_limit.build_args()) + return self + + def sort_by(self, *fields: List[str], **kwargs) -> "AggregateRequest": + """ + Indicate how the results should be sorted. This can also be used for + *top-N* style queries + + ### Parameters + + - **fields**: The fields by which to sort. This can be either a single + field or a list of fields. If you wish to specify order, you can + use the `Asc` or `Desc` wrapper classes. + - **max**: Maximum number of results to return. This can be + used instead of `LIMIT` and is also faster. + + + Example of sorting by `foo` ascending and `bar` descending: + + ``` + sort_by(Asc("@foo"), Desc("@bar")) + ``` + + Return the top 10 customers: + + ``` + AggregateRequest()\ + .group_by("@customer", r.sum("@paid").alias(FIELDNAME))\ + .sort_by(Desc("@paid"), max=10) + ``` + """ + if isinstance(fields, (str, SortDirection)): + fields = [fields] + + fields_args = [] + for f in fields: + if isinstance(f, SortDirection): + fields_args += [f.field, f.DIRSTRING] + else: + fields_args += [f] + + ret = ["SORTBY", str(len(fields_args))] + ret.extend(fields_args) + max = kwargs.get("max", 0) + if max > 0: + ret += ["MAX", str(max)] + + self._aggregateplan.extend(ret) + return self + + def filter(self, expressions: Union[str, List[str]]) -> "AggregateRequest": + """ + Specify filter for post-query results using predicates relating to + values in the result set. + + ### Parameters + + - **fields**: Fields to group by. This can either be a single string, + or a list of strings. + """ + if isinstance(expressions, str): + expressions = [expressions] + + for expression in expressions: + self._aggregateplan.extend(["FILTER", expression]) + + return self + + def with_schema(self) -> "AggregateRequest": + """ + If set, the `schema` property will contain a list of `[field, type]` + entries in the result object. + """ + self._with_schema = True + return self + + def verbatim(self) -> "AggregateRequest": + self._verbatim = True + return self + + def cursor(self, count: int = 0, max_idle: float = 0.0) -> "AggregateRequest": + args = ["WITHCURSOR"] + if count: + args += ["COUNT", str(count)] + if max_idle: + args += ["MAXIDLE", str(max_idle * 1000)] + self._cursor = args + return self + + def build_args(self) -> List[str]: + # @foo:bar ... + ret = [self._query] + + if self._with_schema: + ret.append("WITHSCHEMA") + + if self._verbatim: + ret.append("VERBATIM") + + if self._cursor: + ret += self._cursor + + if self._loadall: + ret.append("LOAD") + ret.append("*") + elif self._loadfields: + ret.append("LOAD") + ret.append(str(len(self._loadfields))) + ret.extend(self._loadfields) + + if self._dialect: + ret.extend(["DIALECT", self._dialect]) + + ret.extend(self._aggregateplan) + + return ret + + def dialect(self, dialect: int) -> "AggregateRequest": + """ + Add a dialect field to the aggregate command. + + - **dialect** - dialect version to execute the query under + """ + self._dialect = dialect + return self + + +class Cursor: + def __init__(self, cid: int) -> None: + self.cid = cid + self.max_idle = 0 + self.count = 0 + + def build_args(self): + args = [str(self.cid)] + if self.max_idle: + args += ["MAXIDLE", str(self.max_idle)] + if self.count: + args += ["COUNT", str(self.count)] + return args + + +class AggregateResult: + def __init__(self, rows, cursor: Cursor, schema) -> None: + self.rows = rows + self.cursor = cursor + self.schema = schema + + def __repr__(self) -> (str, str): + cid = self.cursor.cid if self.cursor else -1 + return ( + f"<{self.__class__.__name__} at 0x{id(self):x} " + f"Rows={len(self.rows)}, Cursor={cid}>" + ) diff --git a/.venv/Lib/site-packages/redis/commands/search/commands.py b/.venv/Lib/site-packages/redis/commands/search/commands.py new file mode 100644 index 00000000..2df2b5a7 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/search/commands.py @@ -0,0 +1,1117 @@ +import itertools +import time +from typing import Dict, List, Optional, Union + +from redis.client import Pipeline +from redis.utils import deprecated_function + +from ..helpers import get_protocol_version, parse_to_dict +from ._util import to_string +from .aggregation import AggregateRequest, AggregateResult, Cursor +from .document import Document +from .query import Query +from .result import Result +from .suggestion import SuggestionParser + +NUMERIC = "NUMERIC" + +CREATE_CMD = "FT.CREATE" +ALTER_CMD = "FT.ALTER" +SEARCH_CMD = "FT.SEARCH" +ADD_CMD = "FT.ADD" +ADDHASH_CMD = "FT.ADDHASH" +DROP_CMD = "FT.DROP" +DROPINDEX_CMD = "FT.DROPINDEX" +EXPLAIN_CMD = "FT.EXPLAIN" +EXPLAINCLI_CMD = "FT.EXPLAINCLI" +DEL_CMD = "FT.DEL" +AGGREGATE_CMD = "FT.AGGREGATE" +PROFILE_CMD = "FT.PROFILE" +CURSOR_CMD = "FT.CURSOR" +SPELLCHECK_CMD = "FT.SPELLCHECK" +DICT_ADD_CMD = "FT.DICTADD" +DICT_DEL_CMD = "FT.DICTDEL" +DICT_DUMP_CMD = "FT.DICTDUMP" +GET_CMD = "FT.GET" +MGET_CMD = "FT.MGET" +CONFIG_CMD = "FT.CONFIG" +TAGVALS_CMD = "FT.TAGVALS" +ALIAS_ADD_CMD = "FT.ALIASADD" +ALIAS_UPDATE_CMD = "FT.ALIASUPDATE" +ALIAS_DEL_CMD = "FT.ALIASDEL" +INFO_CMD = "FT.INFO" +SUGADD_COMMAND = "FT.SUGADD" +SUGDEL_COMMAND = "FT.SUGDEL" +SUGLEN_COMMAND = "FT.SUGLEN" +SUGGET_COMMAND = "FT.SUGGET" +SYNUPDATE_CMD = "FT.SYNUPDATE" +SYNDUMP_CMD = "FT.SYNDUMP" + +NOOFFSETS = "NOOFFSETS" +NOFIELDS = "NOFIELDS" +NOHL = "NOHL" +NOFREQS = "NOFREQS" +MAXTEXTFIELDS = "MAXTEXTFIELDS" +TEMPORARY = "TEMPORARY" +STOPWORDS = "STOPWORDS" +SKIPINITIALSCAN = "SKIPINITIALSCAN" +WITHSCORES = "WITHSCORES" +FUZZY = "FUZZY" +WITHPAYLOADS = "WITHPAYLOADS" + + +class SearchCommands: + """Search commands.""" + + def _parse_results(self, cmd, res, **kwargs): + if get_protocol_version(self.client) in ["3", 3]: + return res + else: + return self._RESP2_MODULE_CALLBACKS[cmd](res, **kwargs) + + def _parse_info(self, res, **kwargs): + it = map(to_string, res) + return dict(zip(it, it)) + + def _parse_search(self, res, **kwargs): + return Result( + res, + not kwargs["query"]._no_content, + duration=kwargs["duration"], + has_payload=kwargs["query"]._with_payloads, + with_scores=kwargs["query"]._with_scores, + ) + + def _parse_aggregate(self, res, **kwargs): + return self._get_aggregate_result(res, kwargs["query"], kwargs["has_cursor"]) + + def _parse_profile(self, res, **kwargs): + query = kwargs["query"] + if isinstance(query, AggregateRequest): + result = self._get_aggregate_result(res[0], query, query._cursor) + else: + result = Result( + res[0], + not query._no_content, + duration=kwargs["duration"], + has_payload=query._with_payloads, + with_scores=query._with_scores, + ) + + return result, parse_to_dict(res[1]) + + def _parse_spellcheck(self, res, **kwargs): + corrections = {} + if res == 0: + return corrections + + for _correction in res: + if isinstance(_correction, int) and _correction == 0: + continue + + if len(_correction) != 3: + continue + if not _correction[2]: + continue + if not _correction[2][0]: + continue + + # For spellcheck output + # 1) 1) "TERM" + # 2) "{term1}" + # 3) 1) 1) "{score1}" + # 2) "{suggestion1}" + # 2) 1) "{score2}" + # 2) "{suggestion2}" + # + # Following dictionary will be made + # corrections = { + # '{term1}': [ + # {'score': '{score1}', 'suggestion': '{suggestion1}'}, + # {'score': '{score2}', 'suggestion': '{suggestion2}'} + # ] + # } + corrections[_correction[1]] = [ + {"score": _item[0], "suggestion": _item[1]} for _item in _correction[2] + ] + + return corrections + + def _parse_config_get(self, res, **kwargs): + return {kvs[0]: kvs[1] for kvs in res} if res else {} + + def _parse_syndump(self, res, **kwargs): + return {res[i]: res[i + 1] for i in range(0, len(res), 2)} + + def batch_indexer(self, chunk_size=100): + """ + Create a new batch indexer from the client with a given chunk size + """ + return self.BatchIndexer(self, chunk_size=chunk_size) + + def create_index( + self, + fields, + no_term_offsets=False, + no_field_flags=False, + stopwords=None, + definition=None, + max_text_fields=False, + temporary=None, + no_highlight=False, + no_term_frequencies=False, + skip_initial_scan=False, + ): + """ + Create the search index. The index must not already exist. + + ### Parameters: + + - **fields**: a list of TextField or NumericField objects + - **no_term_offsets**: If true, we will not save term offsets in + the index + - **no_field_flags**: If true, we will not save field flags that + allow searching in specific fields + - **stopwords**: If not None, we create the index with this custom + stopword list. The list can be empty + - **max_text_fields**: If true, we will encode indexes as if there + were more than 32 text fields which allows you to add additional + fields (beyond 32). + - **temporary**: Create a lightweight temporary index which will + expire after the specified period of inactivity (in seconds). The + internal idle timer is reset whenever the index is searched or added to. + - **no_highlight**: If true, disabling highlighting support. + Also implied by no_term_offsets. + - **no_term_frequencies**: If true, we avoid saving the term frequencies + in the index. + - **skip_initial_scan**: If true, we do not scan and index. + + For more information see `FT.CREATE `_. + """ # noqa + + args = [CREATE_CMD, self.index_name] + if definition is not None: + args += definition.args + if max_text_fields: + args.append(MAXTEXTFIELDS) + if temporary is not None and isinstance(temporary, int): + args.append(TEMPORARY) + args.append(temporary) + if no_term_offsets: + args.append(NOOFFSETS) + if no_highlight: + args.append(NOHL) + if no_field_flags: + args.append(NOFIELDS) + if no_term_frequencies: + args.append(NOFREQS) + if skip_initial_scan: + args.append(SKIPINITIALSCAN) + if stopwords is not None and isinstance(stopwords, (list, tuple, set)): + args += [STOPWORDS, len(stopwords)] + if len(stopwords) > 0: + args += list(stopwords) + + args.append("SCHEMA") + try: + args += list(itertools.chain(*(f.redis_args() for f in fields))) + except TypeError: + args += fields.redis_args() + + return self.execute_command(*args) + + def alter_schema_add(self, fields: List[str]): + """ + Alter the existing search index by adding new fields. The index + must already exist. + + ### Parameters: + + - **fields**: a list of Field objects to add for the index + + For more information see `FT.ALTER `_. + """ # noqa + + args = [ALTER_CMD, self.index_name, "SCHEMA", "ADD"] + try: + args += list(itertools.chain(*(f.redis_args() for f in fields))) + except TypeError: + args += fields.redis_args() + + return self.execute_command(*args) + + def dropindex(self, delete_documents: bool = False): + """ + Drop the index if it exists. + Replaced `drop_index` in RediSearch 2.0. + Default behavior was changed to not delete the indexed documents. + + ### Parameters: + + - **delete_documents**: If `True`, all documents will be deleted. + + For more information see `FT.DROPINDEX `_. + """ # noqa + delete_str = "DD" if delete_documents else "" + return self.execute_command(DROPINDEX_CMD, self.index_name, delete_str) + + def _add_document( + self, + doc_id, + conn=None, + nosave=False, + score=1.0, + payload=None, + replace=False, + partial=False, + language=None, + no_create=False, + **fields, + ): + """ + Internal add_document used for both batch and single doc indexing + """ + + if partial or no_create: + replace = True + + args = [ADD_CMD, self.index_name, doc_id, score] + if nosave: + args.append("NOSAVE") + if payload is not None: + args.append("PAYLOAD") + args.append(payload) + if replace: + args.append("REPLACE") + if partial: + args.append("PARTIAL") + if no_create: + args.append("NOCREATE") + if language: + args += ["LANGUAGE", language] + args.append("FIELDS") + args += list(itertools.chain(*fields.items())) + + if conn is not None: + return conn.execute_command(*args) + + return self.execute_command(*args) + + def _add_document_hash( + self, doc_id, conn=None, score=1.0, language=None, replace=False + ): + """ + Internal add_document_hash used for both batch and single doc indexing + """ + + args = [ADDHASH_CMD, self.index_name, doc_id, score] + + if replace: + args.append("REPLACE") + + if language: + args += ["LANGUAGE", language] + + if conn is not None: + return conn.execute_command(*args) + + return self.execute_command(*args) + + @deprecated_function( + version="2.0.0", reason="deprecated since redisearch 2.0, call hset instead" + ) + def add_document( + self, + doc_id: str, + nosave: bool = False, + score: float = 1.0, + payload: bool = None, + replace: bool = False, + partial: bool = False, + language: Optional[str] = None, + no_create: str = False, + **fields: List[str], + ): + """ + Add a single document to the index. + + ### Parameters + + - **doc_id**: the id of the saved document. + - **nosave**: if set to true, we just index the document, and don't + save a copy of it. This means that searches will just + return ids. + - **score**: the document ranking, between 0.0 and 1.0 + - **payload**: optional inner-index payload we can save for fast + i access in scoring functions + - **replace**: if True, and the document already is in the index, + we perform an update and reindex the document + - **partial**: if True, the fields specified will be added to the + existing document. + This has the added benefit that any fields specified + with `no_index` + will not be reindexed again. Implies `replace` + - **language**: Specify the language used for document tokenization. + - **no_create**: if True, the document is only updated and reindexed + if it already exists. + If the document does not exist, an error will be + returned. Implies `replace` + - **fields** kwargs dictionary of the document fields to be saved + and/or indexed. + NOTE: Geo points shoule be encoded as strings of "lon,lat" + """ # noqa + return self._add_document( + doc_id, + conn=None, + nosave=nosave, + score=score, + payload=payload, + replace=replace, + partial=partial, + language=language, + no_create=no_create, + **fields, + ) + + @deprecated_function( + version="2.0.0", reason="deprecated since redisearch 2.0, call hset instead" + ) + def add_document_hash(self, doc_id, score=1.0, language=None, replace=False): + """ + Add a hash document to the index. + + ### Parameters + + - **doc_id**: the document's id. This has to be an existing HASH key + in Redis that will hold the fields the index needs. + - **score**: the document ranking, between 0.0 and 1.0 + - **replace**: if True, and the document already is in the index, we + perform an update and reindex the document + - **language**: Specify the language used for document tokenization. + """ # noqa + return self._add_document_hash( + doc_id, conn=None, score=score, language=language, replace=replace + ) + + def delete_document(self, doc_id, conn=None, delete_actual_document=False): + """ + Delete a document from index + Returns 1 if the document was deleted, 0 if not + + ### Parameters + + - **delete_actual_document**: if set to True, RediSearch also delete + the actual document if it is in the index + """ # noqa + args = [DEL_CMD, self.index_name, doc_id] + if delete_actual_document: + args.append("DD") + + if conn is not None: + return conn.execute_command(*args) + + return self.execute_command(*args) + + def load_document(self, id): + """ + Load a single document by id + """ + fields = self.client.hgetall(id) + f2 = {to_string(k): to_string(v) for k, v in fields.items()} + fields = f2 + + try: + del fields["id"] + except KeyError: + pass + + return Document(id=id, **fields) + + def get(self, *ids): + """ + Returns the full contents of multiple documents. + + ### Parameters + + - **ids**: the ids of the saved documents. + + """ + + return self.execute_command(MGET_CMD, self.index_name, *ids) + + def info(self): + """ + Get info an stats about the the current index, including the number of + documents, memory consumption, etc + + For more information see `FT.INFO `_. + """ + + res = self.execute_command(INFO_CMD, self.index_name) + return self._parse_results(INFO_CMD, res) + + def get_params_args( + self, query_params: Union[Dict[str, Union[str, int, float, bytes]], None] + ): + if query_params is None: + return [] + args = [] + if len(query_params) > 0: + args.append("params") + args.append(len(query_params) * 2) + for key, value in query_params.items(): + args.append(key) + args.append(value) + return args + + def _mk_query_args( + self, query, query_params: Union[Dict[str, Union[str, int, float, bytes]], None] + ): + args = [self.index_name] + + if isinstance(query, str): + # convert the query from a text to a query object + query = Query(query) + if not isinstance(query, Query): + raise ValueError(f"Bad query type {type(query)}") + + args += query.get_args() + args += self.get_params_args(query_params) + + return args, query + + def search( + self, + query: Union[str, Query], + query_params: Union[Dict[str, Union[str, int, float, bytes]], None] = None, + ): + """ + Search the index for a given query, and return a result of documents + + ### Parameters + + - **query**: the search query. Either a text for simple queries with + default parameters, or a Query object for complex queries. + See RediSearch's documentation on query format + + For more information see `FT.SEARCH `_. + """ # noqa + args, query = self._mk_query_args(query, query_params=query_params) + st = time.time() + res = self.execute_command(SEARCH_CMD, *args) + + if isinstance(res, Pipeline): + return res + + return self._parse_results( + SEARCH_CMD, res, query=query, duration=(time.time() - st) * 1000.0 + ) + + def explain( + self, + query: Union[str, Query], + query_params: Dict[str, Union[str, int, float]] = None, + ): + """Returns the execution plan for a complex query. + + For more information see `FT.EXPLAIN `_. + """ # noqa + args, query_text = self._mk_query_args(query, query_params=query_params) + return self.execute_command(EXPLAIN_CMD, *args) + + def explain_cli(self, query: Union[str, Query]): # noqa + raise NotImplementedError("EXPLAINCLI will not be implemented.") + + def aggregate( + self, + query: Union[str, Query], + query_params: Dict[str, Union[str, int, float]] = None, + ): + """ + Issue an aggregation query. + + ### Parameters + + **query**: This can be either an `AggregateRequest`, or a `Cursor` + + An `AggregateResult` object is returned. You can access the rows from + its `rows` property, which will always yield the rows of the result. + + For more information see `FT.AGGREGATE `_. + """ # noqa + if isinstance(query, AggregateRequest): + has_cursor = bool(query._cursor) + cmd = [AGGREGATE_CMD, self.index_name] + query.build_args() + elif isinstance(query, Cursor): + has_cursor = True + cmd = [CURSOR_CMD, "READ", self.index_name] + query.build_args() + else: + raise ValueError("Bad query", query) + cmd += self.get_params_args(query_params) + + raw = self.execute_command(*cmd) + return self._parse_results( + AGGREGATE_CMD, raw, query=query, has_cursor=has_cursor + ) + + def _get_aggregate_result( + self, raw: List, query: Union[str, Query, AggregateRequest], has_cursor: bool + ): + if has_cursor: + if isinstance(query, Cursor): + query.cid = raw[1] + cursor = query + else: + cursor = Cursor(raw[1]) + raw = raw[0] + else: + cursor = None + + if isinstance(query, AggregateRequest) and query._with_schema: + schema = raw[0] + rows = raw[2:] + else: + schema = None + rows = raw[1:] + + return AggregateResult(rows, cursor, schema) + + def profile( + self, + query: Union[str, Query, AggregateRequest], + limited: bool = False, + query_params: Optional[Dict[str, Union[str, int, float]]] = None, + ): + """ + Performs a search or aggregate command and collects performance + information. + + ### Parameters + + **query**: This can be either an `AggregateRequest`, `Query` or string. + **limited**: If set to True, removes details of reader iterator. + **query_params**: Define one or more value parameters. + Each parameter has a name and a value. + + """ + st = time.time() + cmd = [PROFILE_CMD, self.index_name, ""] + if limited: + cmd.append("LIMITED") + cmd.append("QUERY") + + if isinstance(query, AggregateRequest): + cmd[2] = "AGGREGATE" + cmd += query.build_args() + elif isinstance(query, Query): + cmd[2] = "SEARCH" + cmd += query.get_args() + cmd += self.get_params_args(query_params) + else: + raise ValueError("Must provide AggregateRequest object or Query object.") + + res = self.execute_command(*cmd) + + return self._parse_results( + PROFILE_CMD, res, query=query, duration=(time.time() - st) * 1000.0 + ) + + def spellcheck(self, query, distance=None, include=None, exclude=None): + """ + Issue a spellcheck query + + ### Parameters + + **query**: search query. + **distance***: the maximal Levenshtein distance for spelling + suggestions (default: 1, max: 4). + **include**: specifies an inclusion custom dictionary. + **exclude**: specifies an exclusion custom dictionary. + + For more information see `FT.SPELLCHECK `_. + """ # noqa + cmd = [SPELLCHECK_CMD, self.index_name, query] + if distance: + cmd.extend(["DISTANCE", distance]) + + if include: + cmd.extend(["TERMS", "INCLUDE", include]) + + if exclude: + cmd.extend(["TERMS", "EXCLUDE", exclude]) + + res = self.execute_command(*cmd) + + return self._parse_results(SPELLCHECK_CMD, res) + + def dict_add(self, name: str, *terms: List[str]): + """Adds terms to a dictionary. + + ### Parameters + + - **name**: Dictionary name. + - **terms**: List of items for adding to the dictionary. + + For more information see `FT.DICTADD `_. + """ # noqa + cmd = [DICT_ADD_CMD, name] + cmd.extend(terms) + return self.execute_command(*cmd) + + def dict_del(self, name: str, *terms: List[str]): + """Deletes terms from a dictionary. + + ### Parameters + + - **name**: Dictionary name. + - **terms**: List of items for removing from the dictionary. + + For more information see `FT.DICTDEL `_. + """ # noqa + cmd = [DICT_DEL_CMD, name] + cmd.extend(terms) + return self.execute_command(*cmd) + + def dict_dump(self, name: str): + """Dumps all terms in the given dictionary. + + ### Parameters + + - **name**: Dictionary name. + + For more information see `FT.DICTDUMP `_. + """ # noqa + cmd = [DICT_DUMP_CMD, name] + return self.execute_command(*cmd) + + def config_set(self, option: str, value: str) -> bool: + """Set runtime configuration option. + + ### Parameters + + - **option**: the name of the configuration option. + - **value**: a value for the configuration option. + + For more information see `FT.CONFIG SET `_. + """ # noqa + cmd = [CONFIG_CMD, "SET", option, value] + raw = self.execute_command(*cmd) + return raw == "OK" + + def config_get(self, option: str) -> str: + """Get runtime configuration option value. + + ### Parameters + + - **option**: the name of the configuration option. + + For more information see `FT.CONFIG GET `_. + """ # noqa + cmd = [CONFIG_CMD, "GET", option] + res = self.execute_command(*cmd) + return self._parse_results(CONFIG_CMD, res) + + def tagvals(self, tagfield: str): + """ + Return a list of all possible tag values + + ### Parameters + + - **tagfield**: Tag field name + + For more information see `FT.TAGVALS `_. + """ # noqa + + return self.execute_command(TAGVALS_CMD, self.index_name, tagfield) + + def aliasadd(self, alias: str): + """ + Alias a search index - will fail if alias already exists + + ### Parameters + + - **alias**: Name of the alias to create + + For more information see `FT.ALIASADD `_. + """ # noqa + + return self.execute_command(ALIAS_ADD_CMD, alias, self.index_name) + + def aliasupdate(self, alias: str): + """ + Updates an alias - will fail if alias does not already exist + + ### Parameters + + - **alias**: Name of the alias to create + + For more information see `FT.ALIASUPDATE `_. + """ # noqa + + return self.execute_command(ALIAS_UPDATE_CMD, alias, self.index_name) + + def aliasdel(self, alias: str): + """ + Removes an alias to a search index + + ### Parameters + + - **alias**: Name of the alias to delete + + For more information see `FT.ALIASDEL `_. + """ # noqa + return self.execute_command(ALIAS_DEL_CMD, alias) + + def sugadd(self, key, *suggestions, **kwargs): + """ + Add suggestion terms to the AutoCompleter engine. Each suggestion has + a score and string. + If kwargs["increment"] is true and the terms are already in the + server's dictionary, we increment their scores. + + For more information see `FT.SUGADD `_. + """ # noqa + # If Transaction is not False it will MULTI/EXEC which will error + pipe = self.pipeline(transaction=False) + for sug in suggestions: + args = [SUGADD_COMMAND, key, sug.string, sug.score] + if kwargs.get("increment"): + args.append("INCR") + if sug.payload: + args.append("PAYLOAD") + args.append(sug.payload) + + pipe.execute_command(*args) + + return pipe.execute()[-1] + + def suglen(self, key: str) -> int: + """ + Return the number of entries in the AutoCompleter index. + + For more information see `FT.SUGLEN `_. + """ # noqa + return self.execute_command(SUGLEN_COMMAND, key) + + def sugdel(self, key: str, string: str) -> int: + """ + Delete a string from the AutoCompleter index. + Returns 1 if the string was found and deleted, 0 otherwise. + + For more information see `FT.SUGDEL `_. + """ # noqa + return self.execute_command(SUGDEL_COMMAND, key, string) + + def sugget( + self, + key: str, + prefix: str, + fuzzy: bool = False, + num: int = 10, + with_scores: bool = False, + with_payloads: bool = False, + ) -> List[SuggestionParser]: + """ + Get a list of suggestions from the AutoCompleter, for a given prefix. + + Parameters: + + prefix : str + The prefix we are searching. **Must be valid ascii or utf-8** + fuzzy : bool + If set to true, the prefix search is done in fuzzy mode. + **NOTE**: Running fuzzy searches on short (<3 letters) prefixes + can be very + slow, and even scan the entire index. + with_scores : bool + If set to true, we also return the (refactored) score of + each suggestion. + This is normally not needed, and is NOT the original score + inserted into the index. + with_payloads : bool + Return suggestion payloads + num : int + The maximum number of results we return. Note that we might + return less. The algorithm trims irrelevant suggestions. + + Returns: + + list: + A list of Suggestion objects. If with_scores was False, the + score of all suggestions is 1. + + For more information see `FT.SUGGET `_. + """ # noqa + args = [SUGGET_COMMAND, key, prefix, "MAX", num] + if fuzzy: + args.append(FUZZY) + if with_scores: + args.append(WITHSCORES) + if with_payloads: + args.append(WITHPAYLOADS) + + res = self.execute_command(*args) + results = [] + if not res: + return results + + parser = SuggestionParser(with_scores, with_payloads, res) + return [s for s in parser] + + def synupdate(self, groupid: str, skipinitial: bool = False, *terms: List[str]): + """ + Updates a synonym group. + The command is used to create or update a synonym group with + additional terms. + Only documents which were indexed after the update will be affected. + + Parameters: + + groupid : + Synonym group id. + skipinitial : bool + If set to true, we do not scan and index. + terms : + The terms. + + For more information see `FT.SYNUPDATE `_. + """ # noqa + cmd = [SYNUPDATE_CMD, self.index_name, groupid] + if skipinitial: + cmd.extend(["SKIPINITIALSCAN"]) + cmd.extend(terms) + return self.execute_command(*cmd) + + def syndump(self): + """ + Dumps the contents of a synonym group. + + The command is used to dump the synonyms data structure. + Returns a list of synonym terms and their synonym group ids. + + For more information see `FT.SYNDUMP `_. + """ # noqa + res = self.execute_command(SYNDUMP_CMD, self.index_name) + return self._parse_results(SYNDUMP_CMD, res) + + +class AsyncSearchCommands(SearchCommands): + async def info(self): + """ + Get info an stats about the the current index, including the number of + documents, memory consumption, etc + + For more information see `FT.INFO `_. + """ + + res = await self.execute_command(INFO_CMD, self.index_name) + return self._parse_results(INFO_CMD, res) + + async def search( + self, + query: Union[str, Query], + query_params: Dict[str, Union[str, int, float]] = None, + ): + """ + Search the index for a given query, and return a result of documents + + ### Parameters + + - **query**: the search query. Either a text for simple queries with + default parameters, or a Query object for complex queries. + See RediSearch's documentation on query format + + For more information see `FT.SEARCH `_. + """ # noqa + args, query = self._mk_query_args(query, query_params=query_params) + st = time.time() + res = await self.execute_command(SEARCH_CMD, *args) + + if isinstance(res, Pipeline): + return res + + return self._parse_results( + SEARCH_CMD, res, query=query, duration=(time.time() - st) * 1000.0 + ) + + async def aggregate( + self, + query: Union[str, Query], + query_params: Dict[str, Union[str, int, float]] = None, + ): + """ + Issue an aggregation query. + + ### Parameters + + **query**: This can be either an `AggregateRequest`, or a `Cursor` + + An `AggregateResult` object is returned. You can access the rows from + its `rows` property, which will always yield the rows of the result. + + For more information see `FT.AGGREGATE `_. + """ # noqa + if isinstance(query, AggregateRequest): + has_cursor = bool(query._cursor) + cmd = [AGGREGATE_CMD, self.index_name] + query.build_args() + elif isinstance(query, Cursor): + has_cursor = True + cmd = [CURSOR_CMD, "READ", self.index_name] + query.build_args() + else: + raise ValueError("Bad query", query) + cmd += self.get_params_args(query_params) + + raw = await self.execute_command(*cmd) + return self._parse_results( + AGGREGATE_CMD, raw, query=query, has_cursor=has_cursor + ) + + async def spellcheck(self, query, distance=None, include=None, exclude=None): + """ + Issue a spellcheck query + + ### Parameters + + **query**: search query. + **distance***: the maximal Levenshtein distance for spelling + suggestions (default: 1, max: 4). + **include**: specifies an inclusion custom dictionary. + **exclude**: specifies an exclusion custom dictionary. + + For more information see `FT.SPELLCHECK `_. + """ # noqa + cmd = [SPELLCHECK_CMD, self.index_name, query] + if distance: + cmd.extend(["DISTANCE", distance]) + + if include: + cmd.extend(["TERMS", "INCLUDE", include]) + + if exclude: + cmd.extend(["TERMS", "EXCLUDE", exclude]) + + res = await self.execute_command(*cmd) + + return self._parse_results(SPELLCHECK_CMD, res) + + async def config_set(self, option: str, value: str) -> bool: + """Set runtime configuration option. + + ### Parameters + + - **option**: the name of the configuration option. + - **value**: a value for the configuration option. + + For more information see `FT.CONFIG SET `_. + """ # noqa + cmd = [CONFIG_CMD, "SET", option, value] + raw = await self.execute_command(*cmd) + return raw == "OK" + + async def config_get(self, option: str) -> str: + """Get runtime configuration option value. + + ### Parameters + + - **option**: the name of the configuration option. + + For more information see `FT.CONFIG GET `_. + """ # noqa + cmd = [CONFIG_CMD, "GET", option] + res = {} + res = await self.execute_command(*cmd) + return self._parse_results(CONFIG_CMD, res) + + async def load_document(self, id): + """ + Load a single document by id + """ + fields = await self.client.hgetall(id) + f2 = {to_string(k): to_string(v) for k, v in fields.items()} + fields = f2 + + try: + del fields["id"] + except KeyError: + pass + + return Document(id=id, **fields) + + async def sugadd(self, key, *suggestions, **kwargs): + """ + Add suggestion terms to the AutoCompleter engine. Each suggestion has + a score and string. + If kwargs["increment"] is true and the terms are already in the + server's dictionary, we increment their scores. + + For more information see `FT.SUGADD `_. + """ # noqa + # If Transaction is not False it will MULTI/EXEC which will error + pipe = self.pipeline(transaction=False) + for sug in suggestions: + args = [SUGADD_COMMAND, key, sug.string, sug.score] + if kwargs.get("increment"): + args.append("INCR") + if sug.payload: + args.append("PAYLOAD") + args.append(sug.payload) + + pipe.execute_command(*args) + + return (await pipe.execute())[-1] + + async def sugget( + self, + key: str, + prefix: str, + fuzzy: bool = False, + num: int = 10, + with_scores: bool = False, + with_payloads: bool = False, + ) -> List[SuggestionParser]: + """ + Get a list of suggestions from the AutoCompleter, for a given prefix. + + Parameters: + + prefix : str + The prefix we are searching. **Must be valid ascii or utf-8** + fuzzy : bool + If set to true, the prefix search is done in fuzzy mode. + **NOTE**: Running fuzzy searches on short (<3 letters) prefixes + can be very + slow, and even scan the entire index. + with_scores : bool + If set to true, we also return the (refactored) score of + each suggestion. + This is normally not needed, and is NOT the original score + inserted into the index. + with_payloads : bool + Return suggestion payloads + num : int + The maximum number of results we return. Note that we might + return less. The algorithm trims irrelevant suggestions. + + Returns: + + list: + A list of Suggestion objects. If with_scores was False, the + score of all suggestions is 1. + + For more information see `FT.SUGGET `_. + """ # noqa + args = [SUGGET_COMMAND, key, prefix, "MAX", num] + if fuzzy: + args.append(FUZZY) + if with_scores: + args.append(WITHSCORES) + if with_payloads: + args.append(WITHPAYLOADS) + + ret = await self.execute_command(*args) + results = [] + if not ret: + return results + + parser = SuggestionParser(with_scores, with_payloads, ret) + return [s for s in parser] diff --git a/.venv/Lib/site-packages/redis/commands/search/document.py b/.venv/Lib/site-packages/redis/commands/search/document.py new file mode 100644 index 00000000..47534ec2 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/search/document.py @@ -0,0 +1,17 @@ +class Document: + """ + Represents a single document in a result set + """ + + def __init__(self, id, payload=None, **fields): + self.id = id + self.payload = payload + for k, v in fields.items(): + setattr(self, k, v) + + def __repr__(self): + return f"Document {self.__dict__}" + + def __getitem__(self, item): + value = getattr(self, item) + return value diff --git a/.venv/Lib/site-packages/redis/commands/search/field.py b/.venv/Lib/site-packages/redis/commands/search/field.py new file mode 100644 index 00000000..76eb58c2 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/search/field.py @@ -0,0 +1,168 @@ +from typing import List + +from redis import DataError + + +class Field: + NUMERIC = "NUMERIC" + TEXT = "TEXT" + WEIGHT = "WEIGHT" + GEO = "GEO" + TAG = "TAG" + VECTOR = "VECTOR" + SORTABLE = "SORTABLE" + NOINDEX = "NOINDEX" + AS = "AS" + + def __init__( + self, + name: str, + args: List[str] = None, + sortable: bool = False, + no_index: bool = False, + as_name: str = None, + ): + if args is None: + args = [] + self.name = name + self.args = args + self.args_suffix = list() + self.as_name = as_name + + if sortable: + self.args_suffix.append(Field.SORTABLE) + if no_index: + self.args_suffix.append(Field.NOINDEX) + + if no_index and not sortable: + raise ValueError("Non-Sortable non-Indexable fields are ignored") + + def append_arg(self, value): + self.args.append(value) + + def redis_args(self): + args = [self.name] + if self.as_name: + args += [self.AS, self.as_name] + args += self.args + args += self.args_suffix + return args + + +class TextField(Field): + """ + TextField is used to define a text field in a schema definition + """ + + NOSTEM = "NOSTEM" + PHONETIC = "PHONETIC" + + def __init__( + self, + name: str, + weight: float = 1.0, + no_stem: bool = False, + phonetic_matcher: str = None, + withsuffixtrie: bool = False, + **kwargs, + ): + Field.__init__(self, name, args=[Field.TEXT, Field.WEIGHT, weight], **kwargs) + + if no_stem: + Field.append_arg(self, self.NOSTEM) + if phonetic_matcher and phonetic_matcher in [ + "dm:en", + "dm:fr", + "dm:pt", + "dm:es", + ]: + Field.append_arg(self, self.PHONETIC) + Field.append_arg(self, phonetic_matcher) + if withsuffixtrie: + Field.append_arg(self, "WITHSUFFIXTRIE") + + +class NumericField(Field): + """ + NumericField is used to define a numeric field in a schema definition + """ + + def __init__(self, name: str, **kwargs): + Field.__init__(self, name, args=[Field.NUMERIC], **kwargs) + + +class GeoField(Field): + """ + GeoField is used to define a geo-indexing field in a schema definition + """ + + def __init__(self, name: str, **kwargs): + Field.__init__(self, name, args=[Field.GEO], **kwargs) + + +class TagField(Field): + """ + TagField is a tag-indexing field with simpler compression and tokenization. + See http://redisearch.io/Tags/ + """ + + SEPARATOR = "SEPARATOR" + CASESENSITIVE = "CASESENSITIVE" + + def __init__( + self, + name: str, + separator: str = ",", + case_sensitive: bool = False, + withsuffixtrie: bool = False, + **kwargs, + ): + args = [Field.TAG, self.SEPARATOR, separator] + if case_sensitive: + args.append(self.CASESENSITIVE) + if withsuffixtrie: + args.append("WITHSUFFIXTRIE") + + Field.__init__(self, name, args=args, **kwargs) + + +class VectorField(Field): + """ + Allows vector similarity queries against the value in this attribute. + See https://oss.redis.com/redisearch/Vectors/#vector_fields. + """ + + def __init__(self, name: str, algorithm: str, attributes: dict, **kwargs): + """ + Create Vector Field. Notice that Vector cannot have sortable or no_index tag, + although it's also a Field. + + ``name`` is the name of the field. + + ``algorithm`` can be "FLAT" or "HNSW". + + ``attributes`` each algorithm can have specific attributes. Some of them + are mandatory and some of them are optional. See + https://oss.redis.com/redisearch/master/Vectors/#specific_creation_attributes_per_algorithm + for more information. + """ + sort = kwargs.get("sortable", False) + noindex = kwargs.get("no_index", False) + + if sort or noindex: + raise DataError("Cannot set 'sortable' or 'no_index' in Vector fields.") + + if algorithm.upper() not in ["FLAT", "HNSW"]: + raise DataError( + "Realtime vector indexing supporting 2 Indexing Methods:" + "'FLAT' and 'HNSW'." + ) + + attr_li = [] + + for key, value in attributes.items(): + attr_li.extend([key, value]) + + Field.__init__( + self, name, args=[Field.VECTOR, algorithm, len(attr_li), *attr_li], **kwargs + ) diff --git a/.venv/Lib/site-packages/redis/commands/search/indexDefinition.py b/.venv/Lib/site-packages/redis/commands/search/indexDefinition.py new file mode 100644 index 00000000..a668e85b --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/search/indexDefinition.py @@ -0,0 +1,79 @@ +from enum import Enum + + +class IndexType(Enum): + """Enum of the currently supported index types.""" + + HASH = 1 + JSON = 2 + + +class IndexDefinition: + """IndexDefinition is used to define a index definition for automatic + indexing on Hash or Json update.""" + + def __init__( + self, + prefix=[], + filter=None, + language_field=None, + language=None, + score_field=None, + score=1.0, + payload_field=None, + index_type=None, + ): + self.args = [] + self._append_index_type(index_type) + self._append_prefix(prefix) + self._append_filter(filter) + self._append_language(language_field, language) + self._append_score(score_field, score) + self._append_payload(payload_field) + + def _append_index_type(self, index_type): + """Append `ON HASH` or `ON JSON` according to the enum.""" + if index_type is IndexType.HASH: + self.args.extend(["ON", "HASH"]) + elif index_type is IndexType.JSON: + self.args.extend(["ON", "JSON"]) + elif index_type is not None: + raise RuntimeError(f"index_type must be one of {list(IndexType)}") + + def _append_prefix(self, prefix): + """Append PREFIX.""" + if len(prefix) > 0: + self.args.append("PREFIX") + self.args.append(len(prefix)) + for p in prefix: + self.args.append(p) + + def _append_filter(self, filter): + """Append FILTER.""" + if filter is not None: + self.args.append("FILTER") + self.args.append(filter) + + def _append_language(self, language_field, language): + """Append LANGUAGE_FIELD and LANGUAGE.""" + if language_field is not None: + self.args.append("LANGUAGE_FIELD") + self.args.append(language_field) + if language is not None: + self.args.append("LANGUAGE") + self.args.append(language) + + def _append_score(self, score_field, score): + """Append SCORE_FIELD and SCORE.""" + if score_field is not None: + self.args.append("SCORE_FIELD") + self.args.append(score_field) + if score is not None: + self.args.append("SCORE") + self.args.append(score) + + def _append_payload(self, payload_field): + """Append PAYLOAD_FIELD.""" + if payload_field is not None: + self.args.append("PAYLOAD_FIELD") + self.args.append(payload_field) diff --git a/.venv/Lib/site-packages/redis/commands/search/query.py b/.venv/Lib/site-packages/redis/commands/search/query.py new file mode 100644 index 00000000..113ddf9d --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/search/query.py @@ -0,0 +1,362 @@ +from typing import List, Optional, Union + + +class Query: + """ + Query is used to build complex queries that have more parameters than just + the query string. The query string is set in the constructor, and other + options have setter functions. + + The setter functions return the query object, so they can be chained, + i.e. `Query("foo").verbatim().filter(...)` etc. + """ + + def __init__(self, query_string: str) -> None: + """ + Create a new query object. + The query string is set in the constructor, and other options have + setter functions. + """ + + self._query_string: str = query_string + self._offset: int = 0 + self._num: int = 10 + self._no_content: bool = False + self._no_stopwords: bool = False + self._fields: Optional[List[str]] = None + self._verbatim: bool = False + self._with_payloads: bool = False + self._with_scores: bool = False + self._scorer: Optional[str] = None + self._filters: List = list() + self._ids: Optional[List[str]] = None + self._slop: int = -1 + self._timeout: Optional[float] = None + self._in_order: bool = False + self._sortby: Optional[SortbyField] = None + self._return_fields: List = [] + self._summarize_fields: List = [] + self._highlight_fields: List = [] + self._language: Optional[str] = None + self._expander: Optional[str] = None + self._dialect: Optional[int] = None + + def query_string(self) -> str: + """Return the query string of this query only.""" + return self._query_string + + def limit_ids(self, *ids) -> "Query": + """Limit the results to a specific set of pre-known document + ids of any length.""" + self._ids = ids + return self + + def return_fields(self, *fields) -> "Query": + """Add fields to return fields.""" + self._return_fields += fields + return self + + def return_field(self, field: str, as_field: Optional[str] = None) -> "Query": + """Add field to return fields (Optional: add 'AS' name + to the field).""" + self._return_fields.append(field) + if as_field is not None: + self._return_fields += ("AS", as_field) + return self + + def _mk_field_list(self, fields: List[str]) -> List: + if not fields: + return [] + return [fields] if isinstance(fields, str) else list(fields) + + def summarize( + self, + fields: Optional[List] = None, + context_len: Optional[int] = None, + num_frags: Optional[int] = None, + sep: Optional[str] = None, + ) -> "Query": + """ + Return an abridged format of the field, containing only the segments of + the field which contain the matching term(s). + + If `fields` is specified, then only the mentioned fields are + summarized; otherwise all results are summarized. + + Server side defaults are used for each option (except `fields`) + if not specified + + - **fields** List of fields to summarize. All fields are summarized + if not specified + - **context_len** Amount of context to include with each fragment + - **num_frags** Number of fragments per document + - **sep** Separator string to separate fragments + """ + args = ["SUMMARIZE"] + fields = self._mk_field_list(fields) + if fields: + args += ["FIELDS", str(len(fields))] + fields + + if context_len is not None: + args += ["LEN", str(context_len)] + if num_frags is not None: + args += ["FRAGS", str(num_frags)] + if sep is not None: + args += ["SEPARATOR", sep] + + self._summarize_fields = args + return self + + def highlight( + self, fields: Optional[List[str]] = None, tags: Optional[List[str]] = None + ) -> None: + """ + Apply specified markup to matched term(s) within the returned field(s). + + - **fields** If specified then only those mentioned fields are + highlighted, otherwise all fields are highlighted + - **tags** A list of two strings to surround the match. + """ + args = ["HIGHLIGHT"] + fields = self._mk_field_list(fields) + if fields: + args += ["FIELDS", str(len(fields))] + fields + if tags: + args += ["TAGS"] + list(tags) + + self._highlight_fields = args + return self + + def language(self, language: str) -> "Query": + """ + Analyze the query as being in the specified language. + + :param language: The language (e.g. `chinese` or `english`) + """ + self._language = language + return self + + def slop(self, slop: int) -> "Query": + """Allow a maximum of N intervening non matched terms between + phrase terms (0 means exact phrase). + """ + self._slop = slop + return self + + def timeout(self, timeout: float) -> "Query": + """overrides the timeout parameter of the module""" + self._timeout = timeout + return self + + def in_order(self) -> "Query": + """ + Match only documents where the query terms appear in + the same order in the document. + i.e. for the query "hello world", we do not match "world hello" + """ + self._in_order = True + return self + + def scorer(self, scorer: str) -> "Query": + """ + Use a different scoring function to evaluate document relevance. + Default is `TFIDF`. + + :param scorer: The scoring function to use + (e.g. `TFIDF.DOCNORM` or `BM25`) + """ + self._scorer = scorer + return self + + def get_args(self) -> List[str]: + """Format the redis arguments for this query and return them.""" + args = [self._query_string] + args += self._get_args_tags() + args += self._summarize_fields + self._highlight_fields + args += ["LIMIT", self._offset, self._num] + return args + + def _get_args_tags(self) -> List[str]: + args = [] + if self._no_content: + args.append("NOCONTENT") + if self._fields: + args.append("INFIELDS") + args.append(len(self._fields)) + args += self._fields + if self._verbatim: + args.append("VERBATIM") + if self._no_stopwords: + args.append("NOSTOPWORDS") + if self._filters: + for flt in self._filters: + if not isinstance(flt, Filter): + raise AttributeError("Did not receive a Filter object.") + args += flt.args + if self._with_payloads: + args.append("WITHPAYLOADS") + if self._scorer: + args += ["SCORER", self._scorer] + if self._with_scores: + args.append("WITHSCORES") + if self._ids: + args.append("INKEYS") + args.append(len(self._ids)) + args += self._ids + if self._slop >= 0: + args += ["SLOP", self._slop] + if self._timeout is not None: + args += ["TIMEOUT", self._timeout] + if self._in_order: + args.append("INORDER") + if self._return_fields: + args.append("RETURN") + args.append(len(self._return_fields)) + args += self._return_fields + if self._sortby: + if not isinstance(self._sortby, SortbyField): + raise AttributeError("Did not receive a SortByField.") + args.append("SORTBY") + args += self._sortby.args + if self._language: + args += ["LANGUAGE", self._language] + if self._expander: + args += ["EXPANDER", self._expander] + if self._dialect: + args += ["DIALECT", self._dialect] + + return args + + def paging(self, offset: int, num: int) -> "Query": + """ + Set the paging for the query (defaults to 0..10). + + - **offset**: Paging offset for the results. Defaults to 0 + - **num**: How many results do we want + """ + self._offset = offset + self._num = num + return self + + def verbatim(self) -> "Query": + """Set the query to be verbatim, i.e. use no query expansion + or stemming. + """ + self._verbatim = True + return self + + def no_content(self) -> "Query": + """Set the query to only return ids and not the document content.""" + self._no_content = True + return self + + def no_stopwords(self) -> "Query": + """ + Prevent the query from being filtered for stopwords. + Only useful in very big queries that you are certain contain + no stopwords. + """ + self._no_stopwords = True + return self + + def with_payloads(self) -> "Query": + """Ask the engine to return document payloads.""" + self._with_payloads = True + return self + + def with_scores(self) -> "Query": + """Ask the engine to return document search scores.""" + self._with_scores = True + return self + + def limit_fields(self, *fields: List[str]) -> "Query": + """ + Limit the search to specific TEXT fields only. + + - **fields**: A list of strings, case sensitive field names + from the defined schema. + """ + self._fields = fields + return self + + def add_filter(self, flt: "Filter") -> "Query": + """ + Add a numeric or geo filter to the query. + **Currently only one of each filter is supported by the engine** + + - **flt**: A NumericFilter or GeoFilter object, used on a + corresponding field + """ + + self._filters.append(flt) + return self + + def sort_by(self, field: str, asc: bool = True) -> "Query": + """ + Add a sortby field to the query. + + - **field** - the name of the field to sort by + - **asc** - when `True`, sorting will be done in asceding order + """ + self._sortby = SortbyField(field, asc) + return self + + def expander(self, expander: str) -> "Query": + """ + Add a expander field to the query. + + - **expander** - the name of the expander + """ + self._expander = expander + return self + + def dialect(self, dialect: int) -> "Query": + """ + Add a dialect field to the query. + + - **dialect** - dialect version to execute the query under + """ + self._dialect = dialect + return self + + +class Filter: + def __init__(self, keyword: str, field: str, *args: List[str]) -> None: + self.args = [keyword, field] + list(args) + + +class NumericFilter(Filter): + INF = "+inf" + NEG_INF = "-inf" + + def __init__( + self, + field: str, + minval: Union[int, str], + maxval: Union[int, str], + minExclusive: bool = False, + maxExclusive: bool = False, + ) -> None: + args = [ + minval if not minExclusive else f"({minval}", + maxval if not maxExclusive else f"({maxval}", + ] + + Filter.__init__(self, "FILTER", field, *args) + + +class GeoFilter(Filter): + METERS = "m" + KILOMETERS = "km" + FEET = "ft" + MILES = "mi" + + def __init__( + self, field: str, lon: float, lat: float, radius: float, unit: str = KILOMETERS + ) -> None: + Filter.__init__(self, "GEOFILTER", field, lon, lat, radius, unit) + + +class SortbyField: + def __init__(self, field: str, asc=True) -> None: + self.args = [field, "ASC" if asc else "DESC"] diff --git a/.venv/Lib/site-packages/redis/commands/search/querystring.py b/.venv/Lib/site-packages/redis/commands/search/querystring.py new file mode 100644 index 00000000..3ff13209 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/search/querystring.py @@ -0,0 +1,317 @@ +def tags(*t): + """ + Indicate that the values should be matched to a tag field + + ### Parameters + + - **t**: Tags to search for + """ + if not t: + raise ValueError("At least one tag must be specified") + return TagValue(*t) + + +def between(a, b, inclusive_min=True, inclusive_max=True): + """ + Indicate that value is a numeric range + """ + return RangeValue(a, b, inclusive_min=inclusive_min, inclusive_max=inclusive_max) + + +def equal(n): + """ + Match a numeric value + """ + return between(n, n) + + +def lt(n): + """ + Match any value less than n + """ + return between(None, n, inclusive_max=False) + + +def le(n): + """ + Match any value less or equal to n + """ + return between(None, n, inclusive_max=True) + + +def gt(n): + """ + Match any value greater than n + """ + return between(n, None, inclusive_min=False) + + +def ge(n): + """ + Match any value greater or equal to n + """ + return between(n, None, inclusive_min=True) + + +def geo(lat, lon, radius, unit="km"): + """ + Indicate that value is a geo region + """ + return GeoValue(lat, lon, radius, unit) + + +class Value: + @property + def combinable(self): + """ + Whether this type of value may be combined with other values + for the same field. This makes the filter potentially more efficient + """ + return False + + @staticmethod + def make_value(v): + """ + Convert an object to a value, if it is not a value already + """ + if isinstance(v, Value): + return v + return ScalarValue(v) + + def to_string(self): + raise NotImplementedError() + + def __str__(self): + return self.to_string() + + +class RangeValue(Value): + combinable = False + + def __init__(self, a, b, inclusive_min=False, inclusive_max=False): + if a is None: + a = "-inf" + if b is None: + b = "inf" + self.range = [str(a), str(b)] + self.inclusive_min = inclusive_min + self.inclusive_max = inclusive_max + + def to_string(self): + return "[{1}{0[0]} {2}{0[1]}]".format( + self.range, + "(" if not self.inclusive_min else "", + "(" if not self.inclusive_max else "", + ) + + +class ScalarValue(Value): + combinable = True + + def __init__(self, v): + self.v = str(v) + + def to_string(self): + return self.v + + +class TagValue(Value): + combinable = False + + def __init__(self, *tags): + self.tags = tags + + def to_string(self): + return "{" + " | ".join(str(t) for t in self.tags) + "}" + + +class GeoValue(Value): + def __init__(self, lon, lat, radius, unit="km"): + self.lon = lon + self.lat = lat + self.radius = radius + self.unit = unit + + def to_string(self): + return f"[{self.lon} {self.lat} {self.radius} {self.unit}]" + + +class Node: + def __init__(self, *children, **kwparams): + """ + Create a node + + ### Parameters + + - **children**: One or more sub-conditions. These can be additional + `intersect`, `disjunct`, `union`, `optional`, or any other `Node` + type. + + The semantics of multiple conditions are dependent on the type of + query. For an `intersection` node, this amounts to a logical AND, + for a `union` node, this amounts to a logical `OR`. + + - **kwparams**: key-value parameters. Each key is the name of a field, + and the value should be a field value. This can be one of the + following: + + - Simple string (for text field matches) + - value returned by one of the helper functions + - list of either a string or a value + + + ### Examples + + Field `num` should be between 1 and 10 + ``` + intersect(num=between(1, 10) + ``` + + Name can either be `bob` or `john` + + ``` + union(name=("bob", "john")) + ``` + + Don't select countries in Israel, Japan, or US + + ``` + disjunct_union(country=("il", "jp", "us")) + ``` + """ + + self.params = [] + + kvparams = {} + for k, v in kwparams.items(): + curvals = kvparams.setdefault(k, []) + if isinstance(v, (str, int, float)): + curvals.append(Value.make_value(v)) + elif isinstance(v, Value): + curvals.append(v) + else: + curvals.extend(Value.make_value(subv) for subv in v) + + self.params += [Node.to_node(p) for p in children] + + for k, v in kvparams.items(): + self.params.extend(self.join_fields(k, v)) + + def join_fields(self, key, vals): + if len(vals) == 1: + return [BaseNode(f"@{key}:{vals[0].to_string()}")] + if not vals[0].combinable: + return [BaseNode(f"@{key}:{v.to_string()}") for v in vals] + s = BaseNode(f"@{key}:({self.JOINSTR.join(v.to_string() for v in vals)})") + return [s] + + @classmethod + def to_node(cls, obj): # noqa + if isinstance(obj, Node): + return obj + return BaseNode(obj) + + @property + def JOINSTR(self): + raise NotImplementedError() + + def to_string(self, with_parens=None): + with_parens = self._should_use_paren(with_parens) + pre, post = ("(", ")") if with_parens else ("", "") + return f"{pre}{self.JOINSTR.join(n.to_string() for n in self.params)}{post}" + + def _should_use_paren(self, optval): + if optval is not None: + return optval + return len(self.params) > 1 + + def __str__(self): + return self.to_string() + + +class BaseNode(Node): + def __init__(self, s): + super().__init__() + self.s = str(s) + + def to_string(self, with_parens=None): + return self.s + + +class IntersectNode(Node): + """ + Create an intersection node. All children need to be satisfied in order for + this node to evaluate as true + """ + + JOINSTR = " " + + +class UnionNode(Node): + """ + Create a union node. Any of the children need to be satisfied in order for + this node to evaluate as true + """ + + JOINSTR = "|" + + +class DisjunctNode(IntersectNode): + """ + Create a disjunct node. In order for this node to be true, all of its + children must evaluate to false + """ + + def to_string(self, with_parens=None): + with_parens = self._should_use_paren(with_parens) + ret = super().to_string(with_parens=False) + if with_parens: + return "(-" + ret + ")" + else: + return "-" + ret + + +class DistjunctUnion(DisjunctNode): + """ + This node is true if *all* of its children are false. This is equivalent to + ``` + disjunct(union(...)) + ``` + """ + + JOINSTR = "|" + + +class OptionalNode(IntersectNode): + """ + Create an optional node. If this nodes evaluates to true, then the document + will be rated higher in score/rank. + """ + + def to_string(self, with_parens=None): + with_parens = self._should_use_paren(with_parens) + ret = super().to_string(with_parens=False) + if with_parens: + return "(~" + ret + ")" + else: + return "~" + ret + + +def intersect(*args, **kwargs): + return IntersectNode(*args, **kwargs) + + +def union(*args, **kwargs): + return UnionNode(*args, **kwargs) + + +def disjunct(*args, **kwargs): + return DisjunctNode(*args, **kwargs) + + +def disjunct_union(*args, **kwargs): + return DistjunctUnion(*args, **kwargs) + + +def querystring(*args, **kwargs): + return intersect(*args, **kwargs).to_string() diff --git a/.venv/Lib/site-packages/redis/commands/search/reducers.py b/.venv/Lib/site-packages/redis/commands/search/reducers.py new file mode 100644 index 00000000..8b60f232 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/search/reducers.py @@ -0,0 +1,182 @@ +from typing import Union + +from .aggregation import Asc, Desc, Reducer, SortDirection + + +class FieldOnlyReducer(Reducer): + """See https://redis.io/docs/interact/search-and-query/search/aggregations/""" + + def __init__(self, field: str) -> None: + super().__init__(field) + self._field = field + + +class count(Reducer): + """ + Counts the number of results in the group + """ + + NAME = "COUNT" + + def __init__(self) -> None: + super().__init__() + + +class sum(FieldOnlyReducer): + """ + Calculates the sum of all the values in the given fields within the group + """ + + NAME = "SUM" + + def __init__(self, field: str) -> None: + super().__init__(field) + + +class min(FieldOnlyReducer): + """ + Calculates the smallest value in the given field within the group + """ + + NAME = "MIN" + + def __init__(self, field: str) -> None: + super().__init__(field) + + +class max(FieldOnlyReducer): + """ + Calculates the largest value in the given field within the group + """ + + NAME = "MAX" + + def __init__(self, field: str) -> None: + super().__init__(field) + + +class avg(FieldOnlyReducer): + """ + Calculates the mean value in the given field within the group + """ + + NAME = "AVG" + + def __init__(self, field: str) -> None: + super().__init__(field) + + +class tolist(FieldOnlyReducer): + """ + Returns all the matched properties in a list + """ + + NAME = "TOLIST" + + def __init__(self, field: str) -> None: + super().__init__(field) + + +class count_distinct(FieldOnlyReducer): + """ + Calculate the number of distinct values contained in all the results in + the group for the given field + """ + + NAME = "COUNT_DISTINCT" + + def __init__(self, field: str) -> None: + super().__init__(field) + + +class count_distinctish(FieldOnlyReducer): + """ + Calculate the number of distinct values contained in all the results in the + group for the given field. This uses a faster algorithm than + `count_distinct` but is less accurate + """ + + NAME = "COUNT_DISTINCTISH" + + +class quantile(Reducer): + """ + Return the value for the nth percentile within the range of values for the + field within the group. + """ + + NAME = "QUANTILE" + + def __init__(self, field: str, pct: float) -> None: + super().__init__(field, str(pct)) + self._field = field + + +class stddev(FieldOnlyReducer): + """ + Return the standard deviation for the values within the group + """ + + NAME = "STDDEV" + + def __init__(self, field: str) -> None: + super().__init__(field) + + +class first_value(Reducer): + """ + Selects the first value within the group according to sorting parameters + """ + + NAME = "FIRST_VALUE" + + def __init__(self, field: str, *byfields: Union[Asc, Desc]) -> None: + """ + Selects the first value of the given field within the group. + + ### Parameter + + - **field**: Source field used for the value + - **byfields**: How to sort the results. This can be either the + *class* of `aggregation.Asc` or `aggregation.Desc` in which + case the field `field` is also used as the sort input. + + `byfields` can also be one or more *instances* of `Asc` or `Desc` + indicating the sort order for these fields + """ + + fieldstrs = [] + if ( + len(byfields) == 1 + and isinstance(byfields[0], type) + and issubclass(byfields[0], SortDirection) + ): + byfields = [byfields[0](field)] + + for f in byfields: + fieldstrs += [f.field, f.DIRSTRING] + + args = [field] + if fieldstrs: + args += ["BY"] + fieldstrs + super().__init__(*args) + self._field = field + + +class random_sample(Reducer): + """ + Returns a random sample of items from the dataset, from the given property + """ + + NAME = "RANDOM_SAMPLE" + + def __init__(self, field: str, size: int) -> None: + """ + ### Parameter + + **field**: Field to sample from + **size**: Return this many items (can be less) + """ + args = [field, str(size)] + super().__init__(*args) + self._field = field diff --git a/.venv/Lib/site-packages/redis/commands/search/result.py b/.venv/Lib/site-packages/redis/commands/search/result.py new file mode 100644 index 00000000..5b19e6fa --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/search/result.py @@ -0,0 +1,73 @@ +from ._util import to_string +from .document import Document + + +class Result: + """ + Represents the result of a search query, and has an array of Document + objects + """ + + def __init__( + self, res, hascontent, duration=0, has_payload=False, with_scores=False + ): + """ + - **snippets**: An optional dictionary of the form + {field: snippet_size} for snippet formatting + """ + + self.total = res[0] + self.duration = duration + self.docs = [] + + step = 1 + if hascontent: + step = step + 1 + if has_payload: + step = step + 1 + if with_scores: + step = step + 1 + + offset = 2 if with_scores else 1 + + for i in range(1, len(res), step): + id = to_string(res[i]) + payload = to_string(res[i + offset]) if has_payload else None + # fields_offset = 2 if has_payload else 1 + fields_offset = offset + 1 if has_payload else offset + score = float(res[i + 1]) if with_scores else None + + fields = {} + if hascontent and res[i + fields_offset] is not None: + fields = ( + dict( + dict( + zip( + map(to_string, res[i + fields_offset][::2]), + map(to_string, res[i + fields_offset][1::2]), + ) + ) + ) + if hascontent + else {} + ) + try: + del fields["id"] + except KeyError: + pass + + try: + fields["json"] = fields["$"] + del fields["$"] + except KeyError: + pass + + doc = ( + Document(id, score=score, payload=payload, **fields) + if with_scores + else Document(id, payload=payload, **fields) + ) + self.docs.append(doc) + + def __repr__(self) -> str: + return f"Result{{{self.total} total, docs: {self.docs}}}" diff --git a/.venv/Lib/site-packages/redis/commands/search/suggestion.py b/.venv/Lib/site-packages/redis/commands/search/suggestion.py new file mode 100644 index 00000000..499c8d91 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/search/suggestion.py @@ -0,0 +1,55 @@ +from typing import Optional + +from ._util import to_string + + +class Suggestion: + """ + Represents a single suggestion being sent or returned from the + autocomplete server + """ + + def __init__( + self, string: str, score: float = 1.0, payload: Optional[str] = None + ) -> None: + self.string = to_string(string) + self.payload = to_string(payload) + self.score = score + + def __repr__(self) -> str: + return self.string + + +class SuggestionParser: + """ + Internal class used to parse results from the `SUGGET` command. + This needs to consume either 1, 2, or 3 values at a time from + the return value depending on what objects were requested + """ + + def __init__(self, with_scores: bool, with_payloads: bool, ret) -> None: + self.with_scores = with_scores + self.with_payloads = with_payloads + + if with_scores and with_payloads: + self.sugsize = 3 + self._scoreidx = 1 + self._payloadidx = 2 + elif with_scores: + self.sugsize = 2 + self._scoreidx = 1 + elif with_payloads: + self.sugsize = 2 + self._payloadidx = 1 + else: + self.sugsize = 1 + self._scoreidx = -1 + + self._sugs = ret + + def __iter__(self): + for i in range(0, len(self._sugs), self.sugsize): + ss = self._sugs[i] + score = float(self._sugs[i + self._scoreidx]) if self.with_scores else 1.0 + payload = self._sugs[i + self._payloadidx] if self.with_payloads else None + yield Suggestion(ss, score, payload) diff --git a/.venv/Lib/site-packages/redis/commands/sentinel.py b/.venv/Lib/site-packages/redis/commands/sentinel.py new file mode 100644 index 00000000..f7457579 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/sentinel.py @@ -0,0 +1,99 @@ +import warnings + + +class SentinelCommands: + """ + A class containing the commands specific to redis sentinel. This class is + to be used as a mixin. + """ + + def sentinel(self, *args): + """Redis Sentinel's SENTINEL command.""" + warnings.warn(DeprecationWarning("Use the individual sentinel_* methods")) + + def sentinel_get_master_addr_by_name(self, service_name): + """Returns a (host, port) pair for the given ``service_name``""" + return self.execute_command("SENTINEL GET-MASTER-ADDR-BY-NAME", service_name) + + def sentinel_master(self, service_name): + """Returns a dictionary containing the specified masters state.""" + return self.execute_command("SENTINEL MASTER", service_name) + + def sentinel_masters(self): + """Returns a list of dictionaries containing each master's state.""" + return self.execute_command("SENTINEL MASTERS") + + def sentinel_monitor(self, name, ip, port, quorum): + """Add a new master to Sentinel to be monitored""" + return self.execute_command("SENTINEL MONITOR", name, ip, port, quorum) + + def sentinel_remove(self, name): + """Remove a master from Sentinel's monitoring""" + return self.execute_command("SENTINEL REMOVE", name) + + def sentinel_sentinels(self, service_name): + """Returns a list of sentinels for ``service_name``""" + return self.execute_command("SENTINEL SENTINELS", service_name) + + def sentinel_set(self, name, option, value): + """Set Sentinel monitoring parameters for a given master""" + return self.execute_command("SENTINEL SET", name, option, value) + + def sentinel_slaves(self, service_name): + """Returns a list of slaves for ``service_name``""" + return self.execute_command("SENTINEL SLAVES", service_name) + + def sentinel_reset(self, pattern): + """ + This command will reset all the masters with matching name. + The pattern argument is a glob-style pattern. + + The reset process clears any previous state in a master (including a + failover in progress), and removes every slave and sentinel already + discovered and associated with the master. + """ + return self.execute_command("SENTINEL RESET", pattern, once=True) + + def sentinel_failover(self, new_master_name): + """ + Force a failover as if the master was not reachable, and without + asking for agreement to other Sentinels (however a new version of the + configuration will be published so that the other Sentinels will + update their configurations). + """ + return self.execute_command("SENTINEL FAILOVER", new_master_name) + + def sentinel_ckquorum(self, new_master_name): + """ + Check if the current Sentinel configuration is able to reach the + quorum needed to failover a master, and the majority needed to + authorize the failover. + + This command should be used in monitoring systems to check if a + Sentinel deployment is ok. + """ + return self.execute_command("SENTINEL CKQUORUM", new_master_name, once=True) + + def sentinel_flushconfig(self): + """ + Force Sentinel to rewrite its configuration on disk, including the + current Sentinel state. + + Normally Sentinel rewrites the configuration every time something + changes in its state (in the context of the subset of the state which + is persisted on disk across restart). + However sometimes it is possible that the configuration file is lost + because of operation errors, disk failures, package upgrade scripts or + configuration managers. In those cases a way to to force Sentinel to + rewrite the configuration file is handy. + + This command works even if the previous configuration file is + completely missing. + """ + return self.execute_command("SENTINEL FLUSHCONFIG") + + +class AsyncSentinelCommands(SentinelCommands): + async def sentinel(self, *args) -> None: + """Redis Sentinel's SENTINEL command.""" + super().sentinel(*args) diff --git a/.venv/Lib/site-packages/redis/commands/timeseries/__init__.py b/.venv/Lib/site-packages/redis/commands/timeseries/__init__.py new file mode 100644 index 00000000..4188b93d --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/timeseries/__init__.py @@ -0,0 +1,108 @@ +import redis +from redis._parsers.helpers import bool_ok + +from ..helpers import get_protocol_version, parse_to_list +from .commands import ( + ALTER_CMD, + CREATE_CMD, + CREATERULE_CMD, + DEL_CMD, + DELETERULE_CMD, + GET_CMD, + INFO_CMD, + MGET_CMD, + MRANGE_CMD, + MREVRANGE_CMD, + QUERYINDEX_CMD, + RANGE_CMD, + REVRANGE_CMD, + TimeSeriesCommands, +) +from .info import TSInfo +from .utils import parse_get, parse_m_get, parse_m_range, parse_range + + +class TimeSeries(TimeSeriesCommands): + """ + This class subclasses redis-py's `Redis` and implements RedisTimeSeries's + commands (prefixed with "ts"). + The client allows to interact with RedisTimeSeries and use all of it's + functionality. + """ + + def __init__(self, client=None, **kwargs): + """Create a new RedisTimeSeries client.""" + # Set the module commands' callbacks + self._MODULE_CALLBACKS = { + ALTER_CMD: bool_ok, + CREATE_CMD: bool_ok, + CREATERULE_CMD: bool_ok, + DELETERULE_CMD: bool_ok, + } + + _RESP2_MODULE_CALLBACKS = { + DEL_CMD: int, + GET_CMD: parse_get, + INFO_CMD: TSInfo, + MGET_CMD: parse_m_get, + MRANGE_CMD: parse_m_range, + MREVRANGE_CMD: parse_m_range, + RANGE_CMD: parse_range, + REVRANGE_CMD: parse_range, + QUERYINDEX_CMD: parse_to_list, + } + _RESP3_MODULE_CALLBACKS = {} + + self.client = client + self.execute_command = client.execute_command + + if get_protocol_version(self.client) in ["3", 3]: + self._MODULE_CALLBACKS.update(_RESP3_MODULE_CALLBACKS) + else: + self._MODULE_CALLBACKS.update(_RESP2_MODULE_CALLBACKS) + + for k, v in self._MODULE_CALLBACKS.items(): + self.client.set_response_callback(k, v) + + def pipeline(self, transaction=True, shard_hint=None): + """Creates a pipeline for the TimeSeries module, that can be used + for executing only TimeSeries commands and core commands. + + Usage example: + + r = redis.Redis() + pipe = r.ts().pipeline() + for i in range(100): + pipeline.add("with_pipeline", i, 1.1 * i) + pipeline.execute() + + """ + if isinstance(self.client, redis.RedisCluster): + p = ClusterPipeline( + nodes_manager=self.client.nodes_manager, + commands_parser=self.client.commands_parser, + startup_nodes=self.client.nodes_manager.startup_nodes, + result_callbacks=self.client.result_callbacks, + cluster_response_callbacks=self.client.cluster_response_callbacks, + cluster_error_retry_attempts=self.client.cluster_error_retry_attempts, + read_from_replicas=self.client.read_from_replicas, + reinitialize_steps=self.client.reinitialize_steps, + lock=self.client._lock, + ) + + else: + p = Pipeline( + connection_pool=self.client.connection_pool, + response_callbacks=self._MODULE_CALLBACKS, + transaction=transaction, + shard_hint=shard_hint, + ) + return p + + +class ClusterPipeline(TimeSeriesCommands, redis.cluster.ClusterPipeline): + """Cluster pipeline for the module.""" + + +class Pipeline(TimeSeriesCommands, redis.client.Pipeline): + """Pipeline for the module.""" diff --git a/.venv/Lib/site-packages/redis/commands/timeseries/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/timeseries/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b6d35ccbccc8c64af999e303dad6552f5df66d84 GIT binary patch literal 4854 zcmd5<+fN(W89(C-_%h}a4B=K7AXzX8&TW&;=F*CQmrVogE|97_OEo)q1{m+$&W zcfQNH&G-Gz=fB2c5d!Uxz5mev5F_ND*l}A!h1qWs2zf{}q6rxy})mKzwA1XyLDk7SZFoenOtY z*J*Mu*F`}m>T#W{{le9(^|{<`06gI9G`Wv^#K5D8d-S`SHOb`;cu1NsPZG_qQ9YXw z?8c>BE~DhuU;99i@Y(Sd-BR*2XXVl$zok=VOxlr&xzzYVit|klKX-H5={HWMrX2+^De&+VQ>g{62wk83=o5#Vab=O2x$)U4 zXN1_yTK&>_3Uyk z5wOF~wqVP4)L~5pJC*I43RSZ!x~t=zG#;GW@XWC74+42ebRr8Hk$svV`?Utm|Fs|o zv_>rmzd_9h#~!jH)fH_PBNDWQRf9?CjLMkAHkLS}Gl}Y&!N&4;hne){9P(dEuzJZb z^BLXLvlf%Mv^v@_EdDELb6kYkionsve*Od$6McnbPAk4;crwIGKDl?x$Y%uG+99{I*;Ylnq$?bN z#W1+Z$vyI8h{QS`+};yA9yRWX-H)a?DTjlDk)1#>)c0cxiNznx?}=>>KHn4L50;Uv zqj_vk?0R%{Pi%ki`#rJq(Ft^%DYr$2B85Eny*q*X(Nh2MV*hy@u=iil z{>OnQ(dW^V#puZ&LWSr>cuHbRQ5<|JCSHh%!sz&O@mf*5R^ZR8cc@;)JB#trm+{jt z;-{a-&lcln%R~sj&&fBFJL5ZF!JzkVycEY?h-2TWKeRp<&lSaU1^$%%uIWA;1zAXA zn7R#P5&Qdh;Di8vy>#bL;Pqdjmy<)t4EQ76Sc^HwMIu7Wx#W+-pZgk6~9sW;EIKRal7<=253Fo$`AvAnAU zz}WZ9S6^&x`?vgX>-*JdI4lQsn50U1Bd=$StS&9*sAR3`QZ=q6GpB82^phY~Eh(*L zr6pa0n^)sEH>Mo=I7k3VC*`u4yS46aGVvQbouhEmR|eL-ce*cdoJP%wkDw7r)NhIC%*BIcc3@9QbUL%d1Iej{D$@9i#yFN)((?$ldBvD+^ z;7Q3iDV<54kwzt>eoj24WCizNHgCj4*p6j$n$8rc>0mR|Zg%&n@H&p#F=naM+Q=*1 z&TauT+Q?WQBr>}@o!MYe^c;puX7{=}ozfgySoE%Dlja!BWzWrnz9PF zNTSt_7|h7Rb^uEq1P^lLv_<}!CY){9%@yX;N_0`Y_vu+A=a9UQqNyTq1KI+4i)3fKERvSioe(_*D^3Wr3E#qOq5&_UtZM3tVn-Ck$xq-#Mfqw& z%~UjvilXJxib9j%N>f0-Cwv%wN)!u4PVl~GQ$X%{pRz9)43!CzCMgK0Ur#25fnaNy zyn{G%;P7eqddDvg+rz>5h%3M_taGZ{D+NXi?&G+i_5Zk9jHAs?H$V@ql1_vE;G)onB3Xy;p+yZA z0+q*E6dEQ5=&#_%?%?T_tRM+XuIiaQ{14^@pxx;9@FsIAw2+HEPMwICh*KisRmAH= zrxfH>ATI!U?Z?YLUgz=JkC%PzIDf!^f2X`$w1XR#kzq~|$*V?QF!C}HU%K5`0V;m_ z931$T51hqMp)1Y{{Uu!hFN_ZMcc4%^2ttX7_xPtoMho@NEAnCC=bo~!S@4y~|1Xh< z&{ZIvwNHtp3jgUTH{1{eNVcD+h1Q`rT=llrV9_TCC!kb2L<$`v-yMH8RvevrgW9)M flaL?`p~pc|XdZZc{>hc%&_(nZLXU$cJXrq?1@mGJ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/timeseries/__pycache__/commands.cpython-311.pyc b/.venv/Lib/site-packages/redis/commands/timeseries/__pycache__/commands.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5f3887d3671a0d1c87b84d398750e8d2b5fea84d GIT binary patch literal 39324 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%0DmyXF#A<`?(IN*WHd5LDl}5?Pw7&2GqFZcDJNO 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/redis/commands/timeseries/commands.py b/.venv/Lib/site-packages/redis/commands/timeseries/commands.py new file mode 100644 index 00000000..13e3cdf4 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/timeseries/commands.py @@ -0,0 +1,896 @@ +from typing import Dict, List, Optional, Tuple, Union + +from redis.exceptions import DataError +from redis.typing import KeyT, Number + +ADD_CMD = "TS.ADD" +ALTER_CMD = "TS.ALTER" +CREATERULE_CMD = "TS.CREATERULE" +CREATE_CMD = "TS.CREATE" +DECRBY_CMD = "TS.DECRBY" +DELETERULE_CMD = "TS.DELETERULE" +DEL_CMD = "TS.DEL" +GET_CMD = "TS.GET" +INCRBY_CMD = "TS.INCRBY" +INFO_CMD = "TS.INFO" +MADD_CMD = "TS.MADD" +MGET_CMD = "TS.MGET" +MRANGE_CMD = "TS.MRANGE" +MREVRANGE_CMD = "TS.MREVRANGE" +QUERYINDEX_CMD = "TS.QUERYINDEX" +RANGE_CMD = "TS.RANGE" +REVRANGE_CMD = "TS.REVRANGE" + + +class TimeSeriesCommands: + """RedisTimeSeries Commands.""" + + def create( + self, + key: KeyT, + retention_msecs: Optional[int] = None, + uncompressed: Optional[bool] = False, + labels: Optional[Dict[str, str]] = None, + chunk_size: Optional[int] = None, + duplicate_policy: Optional[str] = None, + ): + """ + Create a new time-series. + + Args: + + key: + time-series key + retention_msecs: + Maximum age for samples compared to highest reported timestamp (in milliseconds). + If None or 0 is passed then the series is not trimmed at all. + uncompressed: + Changes data storage from compressed (by default) to uncompressed + labels: + Set of label-value pairs that represent metadata labels of the key. + chunk_size: + Memory size, in bytes, allocated for each data chunk. + Must be a multiple of 8 in the range [128 .. 1048576]. + duplicate_policy: + Policy for handling multiple samples with identical timestamps. + Can be one of: + - 'block': an error will occur for any out of order sample. + - 'first': ignore the new value. + - 'last': override with latest value. + - 'min': only override if the value is lower than the existing value. + - 'max': only override if the value is higher than the existing value. + + For more information: https://redis.io/commands/ts.create/ + """ # noqa + params = [key] + self._append_retention(params, retention_msecs) + self._append_uncompressed(params, uncompressed) + self._append_chunk_size(params, chunk_size) + self._append_duplicate_policy(params, CREATE_CMD, duplicate_policy) + self._append_labels(params, labels) + + return self.execute_command(CREATE_CMD, *params) + + def alter( + self, + key: KeyT, + retention_msecs: Optional[int] = None, + labels: Optional[Dict[str, str]] = None, + chunk_size: Optional[int] = None, + duplicate_policy: Optional[str] = None, + ): + """ + Update the retention, chunk size, duplicate policy, and labels of an existing + time series. + + Args: + + key: + time-series key + retention_msecs: + Maximum retention period, compared to maximal existing timestamp (in milliseconds). + If None or 0 is passed then the series is not trimmed at all. + labels: + Set of label-value pairs that represent metadata labels of the key. + chunk_size: + Memory size, in bytes, allocated for each data chunk. + Must be a multiple of 8 in the range [128 .. 1048576]. + duplicate_policy: + Policy for handling multiple samples with identical timestamps. + Can be one of: + - 'block': an error will occur for any out of order sample. + - 'first': ignore the new value. + - 'last': override with latest value. + - 'min': only override if the value is lower than the existing value. + - 'max': only override if the value is higher than the existing value. + + For more information: https://redis.io/commands/ts.alter/ + """ # noqa + params = [key] + self._append_retention(params, retention_msecs) + self._append_chunk_size(params, chunk_size) + self._append_duplicate_policy(params, ALTER_CMD, duplicate_policy) + self._append_labels(params, labels) + + return self.execute_command(ALTER_CMD, *params) + + def add( + self, + key: KeyT, + timestamp: Union[int, str], + value: Number, + retention_msecs: Optional[int] = None, + uncompressed: Optional[bool] = False, + labels: Optional[Dict[str, str]] = None, + chunk_size: Optional[int] = None, + duplicate_policy: Optional[str] = None, + ): + """ + Append (or create and append) a new sample to a time series. + + Args: + + key: + time-series key + timestamp: + Timestamp of the sample. * can be used for automatic timestamp (using the system clock). + value: + Numeric data value of the sample + retention_msecs: + Maximum retention period, compared to maximal existing timestamp (in milliseconds). + If None or 0 is passed then the series is not trimmed at all. + uncompressed: + Changes data storage from compressed (by default) to uncompressed + labels: + Set of label-value pairs that represent metadata labels of the key. + chunk_size: + Memory size, in bytes, allocated for each data chunk. + Must be a multiple of 8 in the range [128 .. 1048576]. + duplicate_policy: + Policy for handling multiple samples with identical timestamps. + Can be one of: + - 'block': an error will occur for any out of order sample. + - 'first': ignore the new value. + - 'last': override with latest value. + - 'min': only override if the value is lower than the existing value. + - 'max': only override if the value is higher than the existing value. + + For more information: https://redis.io/commands/ts.add/ + """ # noqa + params = [key, timestamp, value] + self._append_retention(params, retention_msecs) + self._append_uncompressed(params, uncompressed) + self._append_chunk_size(params, chunk_size) + self._append_duplicate_policy(params, ADD_CMD, duplicate_policy) + self._append_labels(params, labels) + + return self.execute_command(ADD_CMD, *params) + + def madd(self, ktv_tuples: List[Tuple[KeyT, Union[int, str], Number]]): + """ + Append (or create and append) a new `value` to series + `key` with `timestamp`. + Expects a list of `tuples` as (`key`,`timestamp`, `value`). + Return value is an array with timestamps of insertions. + + For more information: https://redis.io/commands/ts.madd/ + """ # noqa + params = [] + for ktv in ktv_tuples: + params.extend(ktv) + + return self.execute_command(MADD_CMD, *params) + + def incrby( + self, + key: KeyT, + value: Number, + timestamp: Optional[Union[int, str]] = None, + retention_msecs: Optional[int] = None, + uncompressed: Optional[bool] = False, + labels: Optional[Dict[str, str]] = None, + chunk_size: Optional[int] = None, + ): + """ + Increment (or create an time-series and increment) the latest sample's of a series. + This command can be used as a counter or gauge that automatically gets history as a time series. + + Args: + + key: + time-series key + value: + Numeric data value of the sample + timestamp: + Timestamp of the sample. * can be used for automatic timestamp (using the system clock). + retention_msecs: + Maximum age for samples compared to last event time (in milliseconds). + If None or 0 is passed then the series is not trimmed at all. + uncompressed: + Changes data storage from compressed (by default) to uncompressed + labels: + Set of label-value pairs that represent metadata labels of the key. + chunk_size: + Memory size, in bytes, allocated for each data chunk. + + For more information: https://redis.io/commands/ts.incrby/ + """ # noqa + params = [key, value] + self._append_timestamp(params, timestamp) + self._append_retention(params, retention_msecs) + self._append_uncompressed(params, uncompressed) + self._append_chunk_size(params, chunk_size) + self._append_labels(params, labels) + + return self.execute_command(INCRBY_CMD, *params) + + def decrby( + self, + key: KeyT, + value: Number, + timestamp: Optional[Union[int, str]] = None, + retention_msecs: Optional[int] = None, + uncompressed: Optional[bool] = False, + labels: Optional[Dict[str, str]] = None, + chunk_size: Optional[int] = None, + ): + """ + Decrement (or create an time-series and decrement) the latest sample's of a series. + This command can be used as a counter or gauge that automatically gets history as a time series. + + Args: + + key: + time-series key + value: + Numeric data value of the sample + timestamp: + Timestamp of the sample. * can be used for automatic timestamp (using the system clock). + retention_msecs: + Maximum age for samples compared to last event time (in milliseconds). + If None or 0 is passed then the series is not trimmed at all. + uncompressed: + Changes data storage from compressed (by default) to uncompressed + labels: + Set of label-value pairs that represent metadata labels of the key. + chunk_size: + Memory size, in bytes, allocated for each data chunk. + + For more information: https://redis.io/commands/ts.decrby/ + """ # noqa + params = [key, value] + self._append_timestamp(params, timestamp) + self._append_retention(params, retention_msecs) + self._append_uncompressed(params, uncompressed) + self._append_chunk_size(params, chunk_size) + self._append_labels(params, labels) + + return self.execute_command(DECRBY_CMD, *params) + + def delete(self, key: KeyT, from_time: int, to_time: int): + """ + Delete all samples between two timestamps for a given time series. + + Args: + + key: + time-series key. + from_time: + Start timestamp for the range deletion. + to_time: + End timestamp for the range deletion. + + For more information: https://redis.io/commands/ts.del/ + """ # noqa + return self.execute_command(DEL_CMD, key, from_time, to_time) + + def createrule( + self, + source_key: KeyT, + dest_key: KeyT, + aggregation_type: str, + bucket_size_msec: int, + align_timestamp: Optional[int] = None, + ): + """ + Create a compaction rule from values added to `source_key` into `dest_key`. + + Args: + + source_key: + Key name for source time series + dest_key: + Key name for destination (compacted) time series + aggregation_type: + Aggregation type: One of the following: + [`avg`, `sum`, `min`, `max`, `range`, `count`, `first`, `last`, `std.p`, + `std.s`, `var.p`, `var.s`, `twa`] + bucket_size_msec: + Duration of each bucket, in milliseconds + align_timestamp: + Assure that there is a bucket that starts at exactly align_timestamp and + align all other buckets accordingly. + + For more information: https://redis.io/commands/ts.createrule/ + """ # noqa + params = [source_key, dest_key] + self._append_aggregation(params, aggregation_type, bucket_size_msec) + if align_timestamp is not None: + params.append(align_timestamp) + + return self.execute_command(CREATERULE_CMD, *params) + + def deleterule(self, source_key: KeyT, dest_key: KeyT): + """ + Delete a compaction rule from `source_key` to `dest_key`.. + + For more information: https://redis.io/commands/ts.deleterule/ + """ # noqa + return self.execute_command(DELETERULE_CMD, source_key, dest_key) + + def __range_params( + self, + key: KeyT, + from_time: Union[int, str], + to_time: Union[int, str], + count: Optional[int], + aggregation_type: Optional[str], + bucket_size_msec: Optional[int], + filter_by_ts: Optional[List[int]], + filter_by_min_value: Optional[int], + filter_by_max_value: Optional[int], + align: Optional[Union[int, str]], + latest: Optional[bool], + bucket_timestamp: Optional[str], + empty: Optional[bool], + ): + """Create TS.RANGE and TS.REVRANGE arguments.""" + params = [key, from_time, to_time] + self._append_latest(params, latest) + self._append_filer_by_ts(params, filter_by_ts) + self._append_filer_by_value(params, filter_by_min_value, filter_by_max_value) + self._append_count(params, count) + self._append_align(params, align) + self._append_aggregation(params, aggregation_type, bucket_size_msec) + self._append_bucket_timestamp(params, bucket_timestamp) + self._append_empty(params, empty) + + return params + + def range( + self, + key: KeyT, + from_time: Union[int, str], + to_time: Union[int, str], + count: Optional[int] = None, + aggregation_type: Optional[str] = None, + bucket_size_msec: Optional[int] = 0, + filter_by_ts: Optional[List[int]] = None, + filter_by_min_value: Optional[int] = None, + filter_by_max_value: Optional[int] = None, + align: Optional[Union[int, str]] = None, + latest: Optional[bool] = False, + bucket_timestamp: Optional[str] = None, + empty: Optional[bool] = False, + ): + """ + Query a range in forward direction for a specific time-serie. + + Args: + + key: + Key name for timeseries. + from_time: + Start timestamp for the range query. - can be used to express the minimum possible timestamp (0). + to_time: + End timestamp for range query, + can be used to express the maximum possible timestamp. + count: + Limits the number of returned samples. + aggregation_type: + Optional aggregation type. Can be one of [`avg`, `sum`, `min`, `max`, + `range`, `count`, `first`, `last`, `std.p`, `std.s`, `var.p`, `var.s`, `twa`] + bucket_size_msec: + Time bucket for aggregation in milliseconds. + filter_by_ts: + List of timestamps to filter the result by specific timestamps. + filter_by_min_value: + Filter result by minimum value (must mention also filter by_max_value). + filter_by_max_value: + Filter result by maximum value (must mention also filter by_min_value). + align: + Timestamp for alignment control for aggregation. + latest: + Used when a time series is a compaction, reports the compacted value of the + latest possibly partial bucket + bucket_timestamp: + Controls how bucket timestamps are reported. Can be one of [`-`, `low`, `+`, + `high`, `~`, `mid`]. + empty: + Reports aggregations for empty buckets. + + For more information: https://redis.io/commands/ts.range/ + """ # noqa + params = self.__range_params( + key, + from_time, + to_time, + count, + aggregation_type, + bucket_size_msec, + filter_by_ts, + filter_by_min_value, + filter_by_max_value, + align, + latest, + bucket_timestamp, + empty, + ) + return self.execute_command(RANGE_CMD, *params) + + def revrange( + self, + key: KeyT, + from_time: Union[int, str], + to_time: Union[int, str], + count: Optional[int] = None, + aggregation_type: Optional[str] = None, + bucket_size_msec: Optional[int] = 0, + filter_by_ts: Optional[List[int]] = None, + filter_by_min_value: Optional[int] = None, + filter_by_max_value: Optional[int] = None, + align: Optional[Union[int, str]] = None, + latest: Optional[bool] = False, + bucket_timestamp: Optional[str] = None, + empty: Optional[bool] = False, + ): + """ + Query a range in reverse direction for a specific time-series. + + **Note**: This command is only available since RedisTimeSeries >= v1.4 + + Args: + + key: + Key name for timeseries. + from_time: + Start timestamp for the range query. - can be used to express the minimum possible timestamp (0). + to_time: + End timestamp for range query, + can be used to express the maximum possible timestamp. + count: + Limits the number of returned samples. + aggregation_type: + Optional aggregation type. Can be one of [`avg`, `sum`, `min`, `max`, + `range`, `count`, `first`, `last`, `std.p`, `std.s`, `var.p`, `var.s`, `twa`] + bucket_size_msec: + Time bucket for aggregation in milliseconds. + filter_by_ts: + List of timestamps to filter the result by specific timestamps. + filter_by_min_value: + Filter result by minimum value (must mention also filter_by_max_value). + filter_by_max_value: + Filter result by maximum value (must mention also filter_by_min_value). + align: + Timestamp for alignment control for aggregation. + latest: + Used when a time series is a compaction, reports the compacted value of the + latest possibly partial bucket + bucket_timestamp: + Controls how bucket timestamps are reported. Can be one of [`-`, `low`, `+`, + `high`, `~`, `mid`]. + empty: + Reports aggregations for empty buckets. + + For more information: https://redis.io/commands/ts.revrange/ + """ # noqa + params = self.__range_params( + key, + from_time, + to_time, + count, + aggregation_type, + bucket_size_msec, + filter_by_ts, + filter_by_min_value, + filter_by_max_value, + align, + latest, + bucket_timestamp, + empty, + ) + return self.execute_command(REVRANGE_CMD, *params) + + def __mrange_params( + self, + aggregation_type: Optional[str], + bucket_size_msec: Optional[int], + count: Optional[int], + filters: List[str], + from_time: Union[int, str], + to_time: Union[int, str], + with_labels: Optional[bool], + filter_by_ts: Optional[List[int]], + filter_by_min_value: Optional[int], + filter_by_max_value: Optional[int], + groupby: Optional[str], + reduce: Optional[str], + select_labels: Optional[List[str]], + align: Optional[Union[int, str]], + latest: Optional[bool], + bucket_timestamp: Optional[str], + empty: Optional[bool], + ): + """Create TS.MRANGE and TS.MREVRANGE arguments.""" + params = [from_time, to_time] + self._append_latest(params, latest) + self._append_filer_by_ts(params, filter_by_ts) + self._append_filer_by_value(params, filter_by_min_value, filter_by_max_value) + self._append_with_labels(params, with_labels, select_labels) + self._append_count(params, count) + self._append_align(params, align) + self._append_aggregation(params, aggregation_type, bucket_size_msec) + self._append_bucket_timestamp(params, bucket_timestamp) + self._append_empty(params, empty) + params.extend(["FILTER"]) + params += filters + self._append_groupby_reduce(params, groupby, reduce) + return params + + def mrange( + self, + from_time: Union[int, str], + to_time: Union[int, str], + filters: List[str], + count: Optional[int] = None, + aggregation_type: Optional[str] = None, + bucket_size_msec: Optional[int] = 0, + with_labels: Optional[bool] = False, + filter_by_ts: Optional[List[int]] = None, + filter_by_min_value: Optional[int] = None, + filter_by_max_value: Optional[int] = None, + groupby: Optional[str] = None, + reduce: Optional[str] = None, + select_labels: Optional[List[str]] = None, + align: Optional[Union[int, str]] = None, + latest: Optional[bool] = False, + bucket_timestamp: Optional[str] = None, + empty: Optional[bool] = False, + ): + """ + Query a range across multiple time-series by filters in forward direction. + + Args: + + from_time: + Start timestamp for the range query. `-` can be used to express the minimum possible timestamp (0). + to_time: + End timestamp for range query, `+` can be used to express the maximum possible timestamp. + filters: + filter to match the time-series labels. + count: + Limits the number of returned samples. + aggregation_type: + Optional aggregation type. Can be one of [`avg`, `sum`, `min`, `max`, + `range`, `count`, `first`, `last`, `std.p`, `std.s`, `var.p`, `var.s`, `twa`] + bucket_size_msec: + Time bucket for aggregation in milliseconds. + with_labels: + Include in the reply all label-value pairs representing metadata labels of the time series. + filter_by_ts: + List of timestamps to filter the result by specific timestamps. + filter_by_min_value: + Filter result by minimum value (must mention also filter_by_max_value). + filter_by_max_value: + Filter result by maximum value (must mention also filter_by_min_value). + groupby: + Grouping by fields the results (must mention also reduce). + reduce: + Applying reducer functions on each group. Can be one of [`avg` `sum`, `min`, + `max`, `range`, `count`, `std.p`, `std.s`, `var.p`, `var.s`]. + select_labels: + Include in the reply only a subset of the key-value pair labels of a series. + align: + Timestamp for alignment control for aggregation. + latest: + Used when a time series is a compaction, reports the compacted + value of the latest possibly partial bucket + bucket_timestamp: + Controls how bucket timestamps are reported. Can be one of [`-`, `low`, `+`, + `high`, `~`, `mid`]. + empty: + Reports aggregations for empty buckets. + + For more information: https://redis.io/commands/ts.mrange/ + """ # noqa + params = self.__mrange_params( + aggregation_type, + bucket_size_msec, + count, + filters, + from_time, + to_time, + with_labels, + filter_by_ts, + filter_by_min_value, + filter_by_max_value, + groupby, + reduce, + select_labels, + align, + latest, + bucket_timestamp, + empty, + ) + + return self.execute_command(MRANGE_CMD, *params) + + def mrevrange( + self, + from_time: Union[int, str], + to_time: Union[int, str], + filters: List[str], + count: Optional[int] = None, + aggregation_type: Optional[str] = None, + bucket_size_msec: Optional[int] = 0, + with_labels: Optional[bool] = False, + filter_by_ts: Optional[List[int]] = None, + filter_by_min_value: Optional[int] = None, + filter_by_max_value: Optional[int] = None, + groupby: Optional[str] = None, + reduce: Optional[str] = None, + select_labels: Optional[List[str]] = None, + align: Optional[Union[int, str]] = None, + latest: Optional[bool] = False, + bucket_timestamp: Optional[str] = None, + empty: Optional[bool] = False, + ): + """ + Query a range across multiple time-series by filters in reverse direction. + + Args: + + from_time: + Start timestamp for the range query. - can be used to express the minimum possible timestamp (0). + to_time: + End timestamp for range query, + can be used to express the maximum possible timestamp. + filters: + Filter to match the time-series labels. + count: + Limits the number of returned samples. + aggregation_type: + Optional aggregation type. Can be one of [`avg`, `sum`, `min`, `max`, + `range`, `count`, `first`, `last`, `std.p`, `std.s`, `var.p`, `var.s`, `twa`] + bucket_size_msec: + Time bucket for aggregation in milliseconds. + with_labels: + Include in the reply all label-value pairs representing metadata labels of the time series. + filter_by_ts: + List of timestamps to filter the result by specific timestamps. + filter_by_min_value: + Filter result by minimum value (must mention also filter_by_max_value). + filter_by_max_value: + Filter result by maximum value (must mention also filter_by_min_value). + groupby: + Grouping by fields the results (must mention also reduce). + reduce: + Applying reducer functions on each group. Can be one of [`avg` `sum`, `min`, + `max`, `range`, `count`, `std.p`, `std.s`, `var.p`, `var.s`]. + select_labels: + Include in the reply only a subset of the key-value pair labels of a series. + align: + Timestamp for alignment control for aggregation. + latest: + Used when a time series is a compaction, reports the compacted + value of the latest possibly partial bucket + bucket_timestamp: + Controls how bucket timestamps are reported. Can be one of [`-`, `low`, `+`, + `high`, `~`, `mid`]. + empty: + Reports aggregations for empty buckets. + + For more information: https://redis.io/commands/ts.mrevrange/ + """ # noqa + params = self.__mrange_params( + aggregation_type, + bucket_size_msec, + count, + filters, + from_time, + to_time, + with_labels, + filter_by_ts, + filter_by_min_value, + filter_by_max_value, + groupby, + reduce, + select_labels, + align, + latest, + bucket_timestamp, + empty, + ) + + return self.execute_command(MREVRANGE_CMD, *params) + + def get(self, key: KeyT, latest: Optional[bool] = False): + """# noqa + Get the last sample of `key`. + `latest` used when a time series is a compaction, reports the compacted + value of the latest (possibly partial) bucket + + For more information: https://redis.io/commands/ts.get/ + """ # noqa + params = [key] + self._append_latest(params, latest) + return self.execute_command(GET_CMD, *params) + + def mget( + self, + filters: List[str], + with_labels: Optional[bool] = False, + select_labels: Optional[List[str]] = None, + latest: Optional[bool] = False, + ): + """# noqa + Get the last samples matching the specific `filter`. + + Args: + + filters: + Filter to match the time-series labels. + with_labels: + Include in the reply all label-value pairs representing metadata + labels of the time series. + select_labels: + Include in the reply only a subset of the key-value pair labels of a series. + latest: + Used when a time series is a compaction, reports the compacted + value of the latest possibly partial bucket + + For more information: https://redis.io/commands/ts.mget/ + """ # noqa + params = [] + self._append_latest(params, latest) + self._append_with_labels(params, with_labels, select_labels) + params.extend(["FILTER"]) + params += filters + return self.execute_command(MGET_CMD, *params) + + def info(self, key: KeyT): + """# noqa + Get information of `key`. + + For more information: https://redis.io/commands/ts.info/ + """ # noqa + return self.execute_command(INFO_CMD, key) + + def queryindex(self, filters: List[str]): + """# noqa + Get all time series keys matching the `filter` list. + + For more information: https://redis.io/commands/ts.queryindex/ + """ # noq + return self.execute_command(QUERYINDEX_CMD, *filters) + + @staticmethod + def _append_uncompressed(params: List[str], uncompressed: Optional[bool]): + """Append UNCOMPRESSED tag to params.""" + if uncompressed: + params.extend(["UNCOMPRESSED"]) + + @staticmethod + def _append_with_labels( + params: List[str], + with_labels: Optional[bool], + select_labels: Optional[List[str]], + ): + """Append labels behavior to params.""" + if with_labels and select_labels: + raise DataError( + "with_labels and select_labels cannot be provided together." + ) + + if with_labels: + params.extend(["WITHLABELS"]) + if select_labels: + params.extend(["SELECTED_LABELS", *select_labels]) + + @staticmethod + def _append_groupby_reduce( + params: List[str], groupby: Optional[str], reduce: Optional[str] + ): + """Append GROUPBY REDUCE property to params.""" + if groupby is not None and reduce is not None: + params.extend(["GROUPBY", groupby, "REDUCE", reduce.upper()]) + + @staticmethod + def _append_retention(params: List[str], retention: Optional[int]): + """Append RETENTION property to params.""" + if retention is not None: + params.extend(["RETENTION", retention]) + + @staticmethod + def _append_labels(params: List[str], labels: Optional[List[str]]): + """Append LABELS property to params.""" + if labels: + params.append("LABELS") + for k, v in labels.items(): + params.extend([k, v]) + + @staticmethod + def _append_count(params: List[str], count: Optional[int]): + """Append COUNT property to params.""" + if count is not None: + params.extend(["COUNT", count]) + + @staticmethod + def _append_timestamp(params: List[str], timestamp: Optional[int]): + """Append TIMESTAMP property to params.""" + if timestamp is not None: + params.extend(["TIMESTAMP", timestamp]) + + @staticmethod + def _append_align(params: List[str], align: Optional[Union[int, str]]): + """Append ALIGN property to params.""" + if align is not None: + params.extend(["ALIGN", align]) + + @staticmethod + def _append_aggregation( + params: List[str], + aggregation_type: Optional[str], + bucket_size_msec: Optional[int], + ): + """Append AGGREGATION property to params.""" + if aggregation_type is not None: + params.extend(["AGGREGATION", aggregation_type, bucket_size_msec]) + + @staticmethod + def _append_chunk_size(params: List[str], chunk_size: Optional[int]): + """Append CHUNK_SIZE property to params.""" + if chunk_size is not None: + params.extend(["CHUNK_SIZE", chunk_size]) + + @staticmethod + def _append_duplicate_policy( + params: List[str], command: Optional[str], duplicate_policy: Optional[str] + ): + """Append DUPLICATE_POLICY property to params on CREATE + and ON_DUPLICATE on ADD. + """ + if duplicate_policy is not None: + if command == "TS.ADD": + params.extend(["ON_DUPLICATE", duplicate_policy]) + else: + params.extend(["DUPLICATE_POLICY", duplicate_policy]) + + @staticmethod + def _append_filer_by_ts(params: List[str], ts_list: Optional[List[int]]): + """Append FILTER_BY_TS property to params.""" + if ts_list is not None: + params.extend(["FILTER_BY_TS", *ts_list]) + + @staticmethod + def _append_filer_by_value( + params: List[str], min_value: Optional[int], max_value: Optional[int] + ): + """Append FILTER_BY_VALUE property to params.""" + if min_value is not None and max_value is not None: + params.extend(["FILTER_BY_VALUE", min_value, max_value]) + + @staticmethod + def _append_latest(params: List[str], latest: Optional[bool]): + """Append LATEST property to params.""" + if latest: + params.append("LATEST") + + @staticmethod + def _append_bucket_timestamp(params: List[str], bucket_timestamp: Optional[str]): + """Append BUCKET_TIMESTAMP property to params.""" + if bucket_timestamp is not None: + params.extend(["BUCKETTIMESTAMP", bucket_timestamp]) + + @staticmethod + def _append_empty(params: List[str], empty: Optional[bool]): + """Append EMPTY property to params.""" + if empty: + params.append("EMPTY") diff --git a/.venv/Lib/site-packages/redis/commands/timeseries/info.py b/.venv/Lib/site-packages/redis/commands/timeseries/info.py new file mode 100644 index 00000000..3a384dc0 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/timeseries/info.py @@ -0,0 +1,91 @@ +from ..helpers import nativestr +from .utils import list_to_dict + + +class TSInfo: + """ + Hold information and statistics on the time-series. + Can be created using ``tsinfo`` command + https://oss.redis.com/redistimeseries/commands/#tsinfo. + """ + + rules = [] + labels = [] + sourceKey = None + chunk_count = None + memory_usage = None + total_samples = None + retention_msecs = None + last_time_stamp = None + first_time_stamp = None + + max_samples_per_chunk = None + chunk_size = None + duplicate_policy = None + + def __init__(self, args): + """ + Hold information and statistics on the time-series. + + The supported params that can be passed as args: + + rules: + A list of compaction rules of the time series. + sourceKey: + Key name for source time series in case the current series + is a target of a rule. + chunkCount: + Number of Memory Chunks used for the time series. + memoryUsage: + Total number of bytes allocated for the time series. + totalSamples: + Total number of samples in the time series. + labels: + A list of label-value pairs that represent the metadata + labels of the time series. + retentionTime: + Retention time, in milliseconds, for the time series. + lastTimestamp: + Last timestamp present in the time series. + firstTimestamp: + First timestamp present in the time series. + maxSamplesPerChunk: + Deprecated. + chunkSize: + Amount of memory, in bytes, allocated for data. + duplicatePolicy: + Policy that will define handling of duplicate samples. + + Can read more about on + https://oss.redis.com/redistimeseries/configuration/#duplicate_policy + """ + response = dict(zip(map(nativestr, args[::2]), args[1::2])) + self.rules = response.get("rules") + self.source_key = response.get("sourceKey") + self.chunk_count = response.get("chunkCount") + self.memory_usage = response.get("memoryUsage") + self.total_samples = response.get("totalSamples") + self.labels = list_to_dict(response.get("labels")) + self.retention_msecs = response.get("retentionTime") + self.last_timestamp = response.get("lastTimestamp") + self.first_timestamp = response.get("firstTimestamp") + if "maxSamplesPerChunk" in response: + self.max_samples_per_chunk = response["maxSamplesPerChunk"] + self.chunk_size = ( + self.max_samples_per_chunk * 16 + ) # backward compatible changes + if "chunkSize" in response: + self.chunk_size = response["chunkSize"] + if "duplicatePolicy" in response: + self.duplicate_policy = response["duplicatePolicy"] + if type(self.duplicate_policy) == bytes: + self.duplicate_policy = self.duplicate_policy.decode() + + def get(self, item): + try: + return self.__getitem__(item) + except AttributeError: + return None + + def __getitem__(self, item): + return getattr(self, item) diff --git a/.venv/Lib/site-packages/redis/commands/timeseries/utils.py b/.venv/Lib/site-packages/redis/commands/timeseries/utils.py new file mode 100644 index 00000000..c49b0402 --- /dev/null +++ b/.venv/Lib/site-packages/redis/commands/timeseries/utils.py @@ -0,0 +1,44 @@ +from ..helpers import nativestr + + +def list_to_dict(aList): + return {nativestr(aList[i][0]): nativestr(aList[i][1]) for i in range(len(aList))} + + +def parse_range(response): + """Parse range response. Used by TS.RANGE and TS.REVRANGE.""" + return [tuple((r[0], float(r[1]))) for r in response] + + +def parse_m_range(response): + """Parse multi range response. Used by TS.MRANGE and TS.MREVRANGE.""" + res = [] + for item in response: + res.append({nativestr(item[0]): [list_to_dict(item[1]), parse_range(item[2])]}) + return sorted(res, key=lambda d: list(d.keys())) + + +def parse_get(response): + """Parse get response. Used by TS.GET.""" + if not response: + return None + return int(response[0]), float(response[1]) + + +def parse_m_get(response): + """Parse multi get response. Used by TS.MGET.""" + res = [] + for item in response: + if not item[2]: + res.append({nativestr(item[0]): [list_to_dict(item[1]), None, None]}) + else: + res.append( + { + nativestr(item[0]): [ + list_to_dict(item[1]), + int(item[2][0]), + float(item[2][1]), + ] + } + ) + return sorted(res, key=lambda d: list(d.keys())) diff --git a/.venv/Lib/site-packages/redis/compat.py b/.venv/Lib/site-packages/redis/compat.py new file mode 100644 index 00000000..e4784934 --- /dev/null +++ b/.venv/Lib/site-packages/redis/compat.py @@ -0,0 +1,6 @@ +# flake8: noqa +try: + from typing import Literal, Protocol, TypedDict # lgtm [py/unused-import] +except ImportError: + from typing_extensions import Literal # lgtm [py/unused-import] + from typing_extensions import Protocol, TypedDict diff --git a/.venv/Lib/site-packages/redis/connection.py b/.venv/Lib/site-packages/redis/connection.py new file mode 100644 index 00000000..b39ba28f --- /dev/null +++ b/.venv/Lib/site-packages/redis/connection.py @@ -0,0 +1,1336 @@ +import copy +import os +import socket +import ssl +import sys +import threading +import weakref +from abc import abstractmethod +from itertools import chain +from queue import Empty, Full, LifoQueue +from time import time +from typing import Any, Callable, List, Optional, Type, Union +from urllib.parse import parse_qs, unquote, urlparse + +from ._parsers import Encoder, _HiredisParser, _RESP2Parser, _RESP3Parser +from .backoff import NoBackoff +from .credentials import CredentialProvider, UsernamePasswordCredentialProvider +from .exceptions import ( + AuthenticationError, + AuthenticationWrongNumberOfArgsError, + ChildDeadlockedError, + ConnectionError, + DataError, + RedisError, + ResponseError, + TimeoutError, +) +from .retry import Retry +from .utils import ( + CRYPTOGRAPHY_AVAILABLE, + HIREDIS_AVAILABLE, + HIREDIS_PACK_AVAILABLE, + SSL_AVAILABLE, + get_lib_version, + str_if_bytes, +) + +if HIREDIS_AVAILABLE: + import hiredis + +SYM_STAR = b"*" +SYM_DOLLAR = b"$" +SYM_CRLF = b"\r\n" +SYM_EMPTY = b"" + +DEFAULT_RESP_VERSION = 2 + +SENTINEL = object() + +DefaultParser: Type[Union[_RESP2Parser, _RESP3Parser, _HiredisParser]] +if HIREDIS_AVAILABLE: + DefaultParser = _HiredisParser +else: + DefaultParser = _RESP2Parser + + +class HiredisRespSerializer: + def pack(self, *args: List): + """Pack a series of arguments into the Redis protocol""" + output = [] + + if isinstance(args[0], str): + args = tuple(args[0].encode().split()) + args[1:] + elif b" " in args[0]: + args = tuple(args[0].split()) + args[1:] + try: + output.append(hiredis.pack_command(args)) + except TypeError: + _, value, traceback = sys.exc_info() + raise DataError(value).with_traceback(traceback) + + return output + + +class PythonRespSerializer: + def __init__(self, buffer_cutoff, encode) -> None: + self._buffer_cutoff = buffer_cutoff + self.encode = encode + + def pack(self, *args): + """Pack a series of arguments into the Redis protocol""" + output = [] + # the client might have included 1 or more literal arguments in + # the command name, e.g., 'CONFIG GET'. The Redis server expects these + # arguments to be sent separately, so split the first argument + # manually. These arguments should be bytestrings so that they are + # not encoded. + if isinstance(args[0], str): + args = tuple(args[0].encode().split()) + args[1:] + elif b" " in args[0]: + args = tuple(args[0].split()) + args[1:] + + buff = SYM_EMPTY.join((SYM_STAR, str(len(args)).encode(), SYM_CRLF)) + + buffer_cutoff = self._buffer_cutoff + for arg in map(self.encode, args): + # to avoid large string mallocs, chunk the command into the + # output list if we're sending large values or memoryviews + arg_length = len(arg) + if ( + len(buff) > buffer_cutoff + or arg_length > buffer_cutoff + or isinstance(arg, memoryview) + ): + buff = SYM_EMPTY.join( + (buff, SYM_DOLLAR, str(arg_length).encode(), SYM_CRLF) + ) + output.append(buff) + output.append(arg) + buff = SYM_CRLF + else: + buff = SYM_EMPTY.join( + ( + buff, + SYM_DOLLAR, + str(arg_length).encode(), + SYM_CRLF, + arg, + SYM_CRLF, + ) + ) + output.append(buff) + return output + + +class AbstractConnection: + "Manages communication to and from a Redis server" + + def __init__( + self, + db: int = 0, + password: Optional[str] = None, + socket_timeout: Optional[float] = None, + socket_connect_timeout: Optional[float] = None, + retry_on_timeout: bool = False, + retry_on_error=SENTINEL, + encoding: str = "utf-8", + encoding_errors: str = "strict", + decode_responses: bool = False, + parser_class=DefaultParser, + socket_read_size: int = 65536, + health_check_interval: int = 0, + client_name: Optional[str] = None, + lib_name: Optional[str] = "redis-py", + lib_version: Optional[str] = get_lib_version(), + username: Optional[str] = None, + retry: Union[Any, None] = None, + redis_connect_func: Optional[Callable[[], None]] = None, + credential_provider: Optional[CredentialProvider] = None, + protocol: Optional[int] = 2, + command_packer: Optional[Callable[[], None]] = None, + ): + """ + Initialize a new Connection. + To specify a retry policy for specific errors, first set + `retry_on_error` to a list of the error/s to retry on, then set + `retry` to a valid `Retry` object. + To retry on TimeoutError, `retry_on_timeout` can also be set to `True`. + """ + if (username or password) and credential_provider is not None: + raise DataError( + "'username' and 'password' cannot be passed along with 'credential_" + "provider'. Please provide only one of the following arguments: \n" + "1. 'password' and (optional) 'username'\n" + "2. 'credential_provider'" + ) + self.pid = os.getpid() + self.db = db + self.client_name = client_name + self.lib_name = lib_name + self.lib_version = lib_version + self.credential_provider = credential_provider + self.password = password + self.username = username + self.socket_timeout = socket_timeout + if socket_connect_timeout is None: + socket_connect_timeout = socket_timeout + self.socket_connect_timeout = socket_connect_timeout + self.retry_on_timeout = retry_on_timeout + if retry_on_error is SENTINEL: + retry_on_error = [] + if retry_on_timeout: + # Add TimeoutError to the errors list to retry on + retry_on_error.append(TimeoutError) + self.retry_on_error = retry_on_error + if retry or retry_on_error: + if retry is None: + self.retry = Retry(NoBackoff(), 1) + else: + # deep-copy the Retry object as it is mutable + self.retry = copy.deepcopy(retry) + # Update the retry's supported errors with the specified errors + self.retry.update_supported_errors(retry_on_error) + else: + self.retry = Retry(NoBackoff(), 0) + self.health_check_interval = health_check_interval + self.next_health_check = 0 + self.redis_connect_func = redis_connect_func + self.encoder = Encoder(encoding, encoding_errors, decode_responses) + self._sock = None + self._socket_read_size = socket_read_size + self.set_parser(parser_class) + self._connect_callbacks = [] + self._buffer_cutoff = 6000 + try: + p = int(protocol) + except TypeError: + p = DEFAULT_RESP_VERSION + except ValueError: + raise ConnectionError("protocol must be an integer") + finally: + if p < 2 or p > 3: + raise ConnectionError("protocol must be either 2 or 3") + # p = DEFAULT_RESP_VERSION + self.protocol = p + self._command_packer = self._construct_command_packer(command_packer) + + def __repr__(self): + repr_args = ",".join([f"{k}={v}" for k, v in self.repr_pieces()]) + return f"{self.__class__.__name__}<{repr_args}>" + + @abstractmethod + def repr_pieces(self): + pass + + def __del__(self): + try: + self.disconnect() + except Exception: + pass + + def _construct_command_packer(self, packer): + if packer is not None: + return packer + elif HIREDIS_PACK_AVAILABLE: + return HiredisRespSerializer() + else: + return PythonRespSerializer(self._buffer_cutoff, self.encoder.encode) + + def _register_connect_callback(self, callback): + wm = weakref.WeakMethod(callback) + if wm not in self._connect_callbacks: + self._connect_callbacks.append(wm) + + def _deregister_connect_callback(self, callback): + try: + self._connect_callbacks.remove(weakref.WeakMethod(callback)) + except ValueError: + pass + + def set_parser(self, parser_class): + """ + Creates a new instance of parser_class with socket size: + _socket_read_size and assigns it to the parser for the connection + :param parser_class: The required parser class + """ + self._parser = parser_class(socket_read_size=self._socket_read_size) + + def connect(self): + "Connects to the Redis server if not already connected" + if self._sock: + return + try: + sock = self.retry.call_with_retry( + lambda: self._connect(), lambda error: self.disconnect(error) + ) + except socket.timeout: + raise TimeoutError("Timeout connecting to server") + except OSError as e: + raise ConnectionError(self._error_message(e)) + + self._sock = sock + try: + if self.redis_connect_func is None: + # Use the default on_connect function + self.on_connect() + else: + # Use the passed function redis_connect_func + self.redis_connect_func(self) + except RedisError: + # clean up after any error in on_connect + self.disconnect() + raise + + # run any user callbacks. right now the only internal callback + # is for pubsub channel/pattern resubscription + # first, remove any dead weakrefs + self._connect_callbacks = [ref for ref in self._connect_callbacks if ref()] + for ref in self._connect_callbacks: + callback = ref() + if callback: + callback(self) + + @abstractmethod + def _connect(self): + pass + + @abstractmethod + def _host_error(self): + pass + + @abstractmethod + def _error_message(self, exception): + pass + + def on_connect(self): + "Initialize the connection, authenticate and select a database" + self._parser.on_connect(self) + parser = self._parser + + auth_args = None + # if credential provider or username and/or password are set, authenticate + if self.credential_provider or (self.username or self.password): + cred_provider = ( + self.credential_provider + or UsernamePasswordCredentialProvider(self.username, self.password) + ) + auth_args = cred_provider.get_credentials() + + # if resp version is specified and we have auth args, + # we need to send them via HELLO + if auth_args and self.protocol not in [2, "2"]: + if isinstance(self._parser, _RESP2Parser): + self.set_parser(_RESP3Parser) + # update cluster exception classes + self._parser.EXCEPTION_CLASSES = parser.EXCEPTION_CLASSES + self._parser.on_connect(self) + if len(auth_args) == 1: + auth_args = ["default", auth_args[0]] + self.send_command("HELLO", self.protocol, "AUTH", *auth_args) + response = self.read_response() + # if response.get(b"proto") != self.protocol and response.get( + # "proto" + # ) != self.protocol: + # raise ConnectionError("Invalid RESP version") + elif auth_args: + # avoid checking health here -- PING will fail if we try + # to check the health prior to the AUTH + self.send_command("AUTH", *auth_args, check_health=False) + + try: + auth_response = self.read_response() + except AuthenticationWrongNumberOfArgsError: + # a username and password were specified but the Redis + # server seems to be < 6.0.0 which expects a single password + # arg. retry auth with just the password. + # https://github.com/andymccurdy/redis-py/issues/1274 + self.send_command("AUTH", auth_args[-1], check_health=False) + auth_response = self.read_response() + + if str_if_bytes(auth_response) != "OK": + raise AuthenticationError("Invalid Username or Password") + + # if resp version is specified, switch to it + elif self.protocol not in [2, "2"]: + if isinstance(self._parser, _RESP2Parser): + self.set_parser(_RESP3Parser) + # update cluster exception classes + self._parser.EXCEPTION_CLASSES = parser.EXCEPTION_CLASSES + self._parser.on_connect(self) + self.send_command("HELLO", self.protocol) + response = self.read_response() + if ( + response.get(b"proto") != self.protocol + and response.get("proto") != self.protocol + ): + raise ConnectionError("Invalid RESP version") + + # if a client_name is given, set it + if self.client_name: + self.send_command("CLIENT", "SETNAME", self.client_name) + if str_if_bytes(self.read_response()) != "OK": + raise ConnectionError("Error setting client name") + + try: + # set the library name and version + if self.lib_name: + self.send_command("CLIENT", "SETINFO", "LIB-NAME", self.lib_name) + self.read_response() + except ResponseError: + pass + + try: + if self.lib_version: + self.send_command("CLIENT", "SETINFO", "LIB-VER", self.lib_version) + self.read_response() + except ResponseError: + pass + + # if a database is specified, switch to it + if self.db: + self.send_command("SELECT", self.db) + if str_if_bytes(self.read_response()) != "OK": + raise ConnectionError("Invalid Database") + + def disconnect(self, *args): + "Disconnects from the Redis server" + self._parser.on_disconnect() + + conn_sock = self._sock + self._sock = None + if conn_sock is None: + return + + if os.getpid() == self.pid: + try: + conn_sock.shutdown(socket.SHUT_RDWR) + except OSError: + pass + + try: + conn_sock.close() + except OSError: + pass + + def _send_ping(self): + """Send PING, expect PONG in return""" + self.send_command("PING", check_health=False) + if str_if_bytes(self.read_response()) != "PONG": + raise ConnectionError("Bad response from PING health check") + + def _ping_failed(self, error): + """Function to call when PING fails""" + self.disconnect() + + def check_health(self): + """Check the health of the connection with a PING/PONG""" + if self.health_check_interval and time() > self.next_health_check: + self.retry.call_with_retry(self._send_ping, self._ping_failed) + + def send_packed_command(self, command, check_health=True): + """Send an already packed command to the Redis server""" + if not self._sock: + self.connect() + # guard against health check recursion + if check_health: + self.check_health() + try: + if isinstance(command, str): + command = [command] + for item in command: + self._sock.sendall(item) + except socket.timeout: + self.disconnect() + raise TimeoutError("Timeout writing to socket") + except OSError as e: + self.disconnect() + if len(e.args) == 1: + errno, errmsg = "UNKNOWN", e.args[0] + else: + errno = e.args[0] + errmsg = e.args[1] + raise ConnectionError(f"Error {errno} while writing to socket. {errmsg}.") + except BaseException: + # BaseExceptions can be raised when a socket send operation is not + # finished, e.g. due to a timeout. Ideally, a caller could then re-try + # to send un-sent data. However, the send_packed_command() API + # does not support it so there is no point in keeping the connection open. + self.disconnect() + raise + + def send_command(self, *args, **kwargs): + """Pack and send a command to the Redis server""" + self.send_packed_command( + self._command_packer.pack(*args), + check_health=kwargs.get("check_health", True), + ) + + def can_read(self, timeout=0): + """Poll the socket to see if there's data that can be read.""" + sock = self._sock + if not sock: + self.connect() + + host_error = self._host_error() + + try: + return self._parser.can_read(timeout) + except OSError as e: + self.disconnect() + raise ConnectionError(f"Error while reading from {host_error}: {e.args}") + + def read_response( + self, + disable_decoding=False, + *, + disconnect_on_error=True, + push_request=False, + ): + """Read the response from a previously sent command""" + + host_error = self._host_error() + + try: + if self.protocol in ["3", 3] and not HIREDIS_AVAILABLE: + response = self._parser.read_response( + disable_decoding=disable_decoding, push_request=push_request + ) + else: + response = self._parser.read_response(disable_decoding=disable_decoding) + except socket.timeout: + if disconnect_on_error: + self.disconnect() + raise TimeoutError(f"Timeout reading from {host_error}") + except OSError as e: + if disconnect_on_error: + self.disconnect() + raise ConnectionError( + f"Error while reading from {host_error}" f" : {e.args}" + ) + except BaseException: + # Also by default close in case of BaseException. A lot of code + # relies on this behaviour when doing Command/Response pairs. + # See #1128. + if disconnect_on_error: + self.disconnect() + raise + + if self.health_check_interval: + self.next_health_check = time() + self.health_check_interval + + if isinstance(response, ResponseError): + try: + raise response + finally: + del response # avoid creating ref cycles + return response + + def pack_command(self, *args): + """Pack a series of arguments into the Redis protocol""" + return self._command_packer.pack(*args) + + def pack_commands(self, commands): + """Pack multiple commands into the Redis protocol""" + output = [] + pieces = [] + buffer_length = 0 + buffer_cutoff = self._buffer_cutoff + + for cmd in commands: + for chunk in self._command_packer.pack(*cmd): + chunklen = len(chunk) + if ( + buffer_length > buffer_cutoff + or chunklen > buffer_cutoff + or isinstance(chunk, memoryview) + ): + if pieces: + output.append(SYM_EMPTY.join(pieces)) + buffer_length = 0 + pieces = [] + + if chunklen > buffer_cutoff or isinstance(chunk, memoryview): + output.append(chunk) + else: + pieces.append(chunk) + buffer_length += chunklen + + if pieces: + output.append(SYM_EMPTY.join(pieces)) + return output + + +class Connection(AbstractConnection): + "Manages TCP communication to and from a Redis server" + + def __init__( + self, + host="localhost", + port=6379, + socket_keepalive=False, + socket_keepalive_options=None, + socket_type=0, + **kwargs, + ): + self.host = host + self.port = int(port) + self.socket_keepalive = socket_keepalive + self.socket_keepalive_options = socket_keepalive_options or {} + self.socket_type = socket_type + super().__init__(**kwargs) + + def repr_pieces(self): + pieces = [("host", self.host), ("port", self.port), ("db", self.db)] + if self.client_name: + pieces.append(("client_name", self.client_name)) + return pieces + + def _connect(self): + "Create a TCP socket connection" + # we want to mimic what socket.create_connection does to support + # ipv4/ipv6, but we want to set options prior to calling + # socket.connect() + err = None + for res in socket.getaddrinfo( + self.host, self.port, self.socket_type, socket.SOCK_STREAM + ): + family, socktype, proto, canonname, socket_address = res + sock = None + try: + sock = socket.socket(family, socktype, proto) + # TCP_NODELAY + sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + + # TCP_KEEPALIVE + if self.socket_keepalive: + sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) + for k, v in self.socket_keepalive_options.items(): + sock.setsockopt(socket.IPPROTO_TCP, k, v) + + # set the socket_connect_timeout before we connect + sock.settimeout(self.socket_connect_timeout) + + # connect + sock.connect(socket_address) + + # set the socket_timeout now that we're connected + sock.settimeout(self.socket_timeout) + return sock + + except OSError as _: + err = _ + if sock is not None: + sock.close() + + if err is not None: + raise err + raise OSError("socket.getaddrinfo returned an empty list") + + def _host_error(self): + return f"{self.host}:{self.port}" + + def _error_message(self, exception): + # args for socket.error can either be (errno, "message") + # or just "message" + + host_error = self._host_error() + + if len(exception.args) == 1: + try: + return f"Error connecting to {host_error}. \ + {exception.args[0]}." + except AttributeError: + return f"Connection Error: {exception.args[0]}" + else: + try: + return ( + f"Error {exception.args[0]} connecting to " + f"{host_error}. {exception.args[1]}." + ) + except AttributeError: + return f"Connection Error: {exception.args[0]}" + + +class SSLConnection(Connection): + """Manages SSL connections to and from the Redis server(s). + This class extends the Connection class, adding SSL functionality, and making + use of ssl.SSLContext (https://docs.python.org/3/library/ssl.html#ssl.SSLContext) + """ # noqa + + def __init__( + self, + ssl_keyfile=None, + ssl_certfile=None, + ssl_cert_reqs="required", + ssl_ca_certs=None, + ssl_ca_data=None, + ssl_check_hostname=False, + ssl_ca_path=None, + ssl_password=None, + ssl_validate_ocsp=False, + ssl_validate_ocsp_stapled=False, + ssl_ocsp_context=None, + ssl_ocsp_expected_cert=None, + **kwargs, + ): + """Constructor + + Args: + ssl_keyfile: Path to an ssl private key. Defaults to None. + ssl_certfile: Path to an ssl certificate. Defaults to None. + ssl_cert_reqs: The string value for the SSLContext.verify_mode (none, optional, required). Defaults to "required". + ssl_ca_certs: The path to a file of concatenated CA certificates in PEM format. Defaults to None. + ssl_ca_data: Either an ASCII string of one or more PEM-encoded certificates or a bytes-like object of DER-encoded certificates. + ssl_check_hostname: If set, match the hostname during the SSL handshake. Defaults to False. + ssl_ca_path: The path to a directory containing several CA certificates in PEM format. Defaults to None. + ssl_password: Password for unlocking an encrypted private key. Defaults to None. + + ssl_validate_ocsp: If set, perform a full ocsp validation (i.e not a stapled verification) + ssl_validate_ocsp_stapled: If set, perform a validation on a stapled ocsp response + ssl_ocsp_context: A fully initialized OpenSSL.SSL.Context object to be used in verifying the ssl_ocsp_expected_cert + ssl_ocsp_expected_cert: A PEM armoured string containing the expected certificate to be returned from the ocsp verification service. + + Raises: + RedisError + """ # noqa + if not SSL_AVAILABLE: + raise RedisError("Python wasn't built with SSL support") + + self.keyfile = ssl_keyfile + self.certfile = ssl_certfile + if ssl_cert_reqs is None: + ssl_cert_reqs = ssl.CERT_NONE + elif isinstance(ssl_cert_reqs, str): + CERT_REQS = { + "none": ssl.CERT_NONE, + "optional": ssl.CERT_OPTIONAL, + "required": ssl.CERT_REQUIRED, + } + if ssl_cert_reqs not in CERT_REQS: + raise RedisError( + f"Invalid SSL Certificate Requirements Flag: {ssl_cert_reqs}" + ) + ssl_cert_reqs = CERT_REQS[ssl_cert_reqs] + self.cert_reqs = ssl_cert_reqs + self.ca_certs = ssl_ca_certs + self.ca_data = ssl_ca_data + self.ca_path = ssl_ca_path + self.check_hostname = ssl_check_hostname + self.certificate_password = ssl_password + self.ssl_validate_ocsp = ssl_validate_ocsp + self.ssl_validate_ocsp_stapled = ssl_validate_ocsp_stapled + self.ssl_ocsp_context = ssl_ocsp_context + self.ssl_ocsp_expected_cert = ssl_ocsp_expected_cert + super().__init__(**kwargs) + + def _connect(self): + "Wrap the socket with SSL support" + sock = super()._connect() + context = ssl.create_default_context() + context.check_hostname = self.check_hostname + context.verify_mode = self.cert_reqs + if self.certfile or self.keyfile: + context.load_cert_chain( + certfile=self.certfile, + keyfile=self.keyfile, + password=self.certificate_password, + ) + if ( + self.ca_certs is not None + or self.ca_path is not None + or self.ca_data is not None + ): + context.load_verify_locations( + cafile=self.ca_certs, capath=self.ca_path, cadata=self.ca_data + ) + sslsock = context.wrap_socket(sock, server_hostname=self.host) + if self.ssl_validate_ocsp is True and CRYPTOGRAPHY_AVAILABLE is False: + raise RedisError("cryptography is not installed.") + + if self.ssl_validate_ocsp_stapled and self.ssl_validate_ocsp: + raise RedisError( + "Either an OCSP staple or pure OCSP connection must be validated " + "- not both." + ) + + # validation for the stapled case + if self.ssl_validate_ocsp_stapled: + import OpenSSL + + from .ocsp import ocsp_staple_verifier + + # if a context is provided use it - otherwise, a basic context + if self.ssl_ocsp_context is None: + staple_ctx = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD) + staple_ctx.use_certificate_file(self.certfile) + staple_ctx.use_privatekey_file(self.keyfile) + else: + staple_ctx = self.ssl_ocsp_context + + staple_ctx.set_ocsp_client_callback( + ocsp_staple_verifier, self.ssl_ocsp_expected_cert + ) + + # need another socket + con = OpenSSL.SSL.Connection(staple_ctx, socket.socket()) + con.request_ocsp() + con.connect((self.host, self.port)) + con.do_handshake() + con.shutdown() + return sslsock + + # pure ocsp validation + if self.ssl_validate_ocsp is True and CRYPTOGRAPHY_AVAILABLE: + from .ocsp import OCSPVerifier + + o = OCSPVerifier(sslsock, self.host, self.port, self.ca_certs) + if o.is_valid(): + return sslsock + else: + raise ConnectionError("ocsp validation error") + return sslsock + + +class UnixDomainSocketConnection(AbstractConnection): + "Manages UDS communication to and from a Redis server" + + def __init__(self, path="", socket_timeout=None, **kwargs): + self.path = path + self.socket_timeout = socket_timeout + super().__init__(**kwargs) + + def repr_pieces(self): + pieces = [("path", self.path), ("db", self.db)] + if self.client_name: + pieces.append(("client_name", self.client_name)) + return pieces + + def _connect(self): + "Create a Unix domain socket connection" + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + sock.settimeout(self.socket_connect_timeout) + sock.connect(self.path) + sock.settimeout(self.socket_timeout) + return sock + + def _host_error(self): + return self.path + + def _error_message(self, exception): + # args for socket.error can either be (errno, "message") + # or just "message" + host_error = self._host_error() + if len(exception.args) == 1: + return ( + f"Error connecting to unix socket: {host_error}. {exception.args[0]}." + ) + else: + return ( + f"Error {exception.args[0]} connecting to unix socket: " + f"{host_error}. {exception.args[1]}." + ) + + +FALSE_STRINGS = ("0", "F", "FALSE", "N", "NO") + + +def to_bool(value): + if value is None or value == "": + return None + if isinstance(value, str) and value.upper() in FALSE_STRINGS: + return False + return bool(value) + + +URL_QUERY_ARGUMENT_PARSERS = { + "db": int, + "socket_timeout": float, + "socket_connect_timeout": float, + "socket_keepalive": to_bool, + "retry_on_timeout": to_bool, + "retry_on_error": list, + "max_connections": int, + "health_check_interval": int, + "ssl_check_hostname": to_bool, +} + + +def parse_url(url): + if not ( + url.startswith("redis://") + or url.startswith("rediss://") + or url.startswith("unix://") + ): + raise ValueError( + "Redis URL must specify one of the following " + "schemes (redis://, rediss://, unix://)" + ) + + url = urlparse(url) + kwargs = {} + + for name, value in parse_qs(url.query).items(): + if value and len(value) > 0: + value = unquote(value[0]) + parser = URL_QUERY_ARGUMENT_PARSERS.get(name) + if parser: + try: + kwargs[name] = parser(value) + except (TypeError, ValueError): + raise ValueError(f"Invalid value for `{name}` in connection URL.") + else: + kwargs[name] = value + + if url.username: + kwargs["username"] = unquote(url.username) + if url.password: + kwargs["password"] = unquote(url.password) + + # We only support redis://, rediss:// and unix:// schemes. + if url.scheme == "unix": + if url.path: + kwargs["path"] = unquote(url.path) + kwargs["connection_class"] = UnixDomainSocketConnection + + else: # implied: url.scheme in ("redis", "rediss"): + if url.hostname: + kwargs["host"] = unquote(url.hostname) + if url.port: + kwargs["port"] = int(url.port) + + # If there's a path argument, use it as the db argument if a + # querystring value wasn't specified + if url.path and "db" not in kwargs: + try: + kwargs["db"] = int(unquote(url.path).replace("/", "")) + except (AttributeError, ValueError): + pass + + if url.scheme == "rediss": + kwargs["connection_class"] = SSLConnection + + return kwargs + + +class ConnectionPool: + """ + Create a connection pool. ``If max_connections`` is set, then this + object raises :py:class:`~redis.exceptions.ConnectionError` when the pool's + limit is reached. + + By default, TCP connections are created unless ``connection_class`` + is specified. Use class:`.UnixDomainSocketConnection` for + unix sockets. + + Any additional keyword arguments are passed to the constructor of + ``connection_class``. + """ + + @classmethod + def from_url(cls, url, **kwargs): + """ + Return a connection pool configured from the given URL. + + For example:: + + redis://[[username]:[password]]@localhost:6379/0 + rediss://[[username]:[password]]@localhost:6379/0 + unix://[username@]/path/to/socket.sock?db=0[&password=password] + + Three URL schemes are supported: + + - `redis://` creates a TCP socket connection. See more at: + + - `rediss://` creates a SSL wrapped TCP socket connection. See more at: + + - ``unix://``: creates a Unix Domain Socket connection. + + The username, password, hostname, path and all querystring values + are passed through urllib.parse.unquote in order to replace any + percent-encoded values with their corresponding characters. + + There are several ways to specify a database number. The first value + found will be used: + + 1. A ``db`` querystring option, e.g. redis://localhost?db=0 + 2. If using the redis:// or rediss:// schemes, the path argument + of the url, e.g. redis://localhost/0 + 3. A ``db`` keyword argument to this function. + + If none of these options are specified, the default db=0 is used. + + All querystring options are cast to their appropriate Python types. + Boolean arguments can be specified with string values "True"/"False" + or "Yes"/"No". Values that cannot be properly cast cause a + ``ValueError`` to be raised. Once parsed, the querystring arguments + and keyword arguments are passed to the ``ConnectionPool``'s + class initializer. In the case of conflicting arguments, querystring + arguments always win. + """ + url_options = parse_url(url) + + if "connection_class" in kwargs: + url_options["connection_class"] = kwargs["connection_class"] + + kwargs.update(url_options) + return cls(**kwargs) + + def __init__( + self, + connection_class=Connection, + max_connections: Optional[int] = None, + **connection_kwargs, + ): + max_connections = max_connections or 2**31 + if not isinstance(max_connections, int) or max_connections < 0: + raise ValueError('"max_connections" must be a positive integer') + + self.connection_class = connection_class + self.connection_kwargs = connection_kwargs + self.max_connections = max_connections + + # a lock to protect the critical section in _checkpid(). + # this lock is acquired when the process id changes, such as + # after a fork. during this time, multiple threads in the child + # process could attempt to acquire this lock. the first thread + # to acquire the lock will reset the data structures and lock + # object of this pool. subsequent threads acquiring this lock + # will notice the first thread already did the work and simply + # release the lock. + self._fork_lock = threading.Lock() + self.reset() + + def __repr__(self) -> (str, str): + return ( + f"{type(self).__name__}" + f"<{repr(self.connection_class(**self.connection_kwargs))}>" + ) + + def reset(self) -> None: + self._lock = threading.Lock() + self._created_connections = 0 + self._available_connections = [] + self._in_use_connections = set() + + # this must be the last operation in this method. while reset() is + # called when holding _fork_lock, other threads in this process + # can call _checkpid() which compares self.pid and os.getpid() without + # holding any lock (for performance reasons). keeping this assignment + # as the last operation ensures that those other threads will also + # notice a pid difference and block waiting for the first thread to + # release _fork_lock. when each of these threads eventually acquire + # _fork_lock, they will notice that another thread already called + # reset() and they will immediately release _fork_lock and continue on. + self.pid = os.getpid() + + def _checkpid(self) -> None: + # _checkpid() attempts to keep ConnectionPool fork-safe on modern + # systems. this is called by all ConnectionPool methods that + # manipulate the pool's state such as get_connection() and release(). + # + # _checkpid() determines whether the process has forked by comparing + # the current process id to the process id saved on the ConnectionPool + # instance. if these values are the same, _checkpid() simply returns. + # + # when the process ids differ, _checkpid() assumes that the process + # has forked and that we're now running in the child process. the child + # process cannot use the parent's file descriptors (e.g., sockets). + # therefore, when _checkpid() sees the process id change, it calls + # reset() in order to reinitialize the child's ConnectionPool. this + # will cause the child to make all new connection objects. + # + # _checkpid() is protected by self._fork_lock to ensure that multiple + # threads in the child process do not call reset() multiple times. + # + # there is an extremely small chance this could fail in the following + # scenario: + # 1. process A calls _checkpid() for the first time and acquires + # self._fork_lock. + # 2. while holding self._fork_lock, process A forks (the fork() + # could happen in a different thread owned by process A) + # 3. process B (the forked child process) inherits the + # ConnectionPool's state from the parent. that state includes + # a locked _fork_lock. process B will not be notified when + # process A releases the _fork_lock and will thus never be + # able to acquire the _fork_lock. + # + # to mitigate this possible deadlock, _checkpid() will only wait 5 + # seconds to acquire _fork_lock. if _fork_lock cannot be acquired in + # that time it is assumed that the child is deadlocked and a + # redis.ChildDeadlockedError error is raised. + if self.pid != os.getpid(): + acquired = self._fork_lock.acquire(timeout=5) + if not acquired: + raise ChildDeadlockedError + # reset() the instance for the new process if another thread + # hasn't already done so + try: + if self.pid != os.getpid(): + self.reset() + finally: + self._fork_lock.release() + + def get_connection(self, command_name: str, *keys, **options) -> "Connection": + "Get a connection from the pool" + self._checkpid() + with self._lock: + try: + connection = self._available_connections.pop() + except IndexError: + connection = self.make_connection() + self._in_use_connections.add(connection) + + try: + # ensure this connection is connected to Redis + connection.connect() + # connections that the pool provides should be ready to send + # a command. if not, the connection was either returned to the + # pool before all data has been read or the socket has been + # closed. either way, reconnect and verify everything is good. + try: + if connection.can_read(): + raise ConnectionError("Connection has data") + except (ConnectionError, OSError): + connection.disconnect() + connection.connect() + if connection.can_read(): + raise ConnectionError("Connection not ready") + except BaseException: + # release the connection back to the pool so that we don't + # leak it + self.release(connection) + raise + + return connection + + def get_encoder(self) -> Encoder: + "Return an encoder based on encoding settings" + kwargs = self.connection_kwargs + return Encoder( + encoding=kwargs.get("encoding", "utf-8"), + encoding_errors=kwargs.get("encoding_errors", "strict"), + decode_responses=kwargs.get("decode_responses", False), + ) + + def make_connection(self) -> "Connection": + "Create a new connection" + if self._created_connections >= self.max_connections: + raise ConnectionError("Too many connections") + self._created_connections += 1 + return self.connection_class(**self.connection_kwargs) + + def release(self, connection: "Connection") -> None: + "Releases the connection back to the pool" + self._checkpid() + with self._lock: + try: + self._in_use_connections.remove(connection) + except KeyError: + # Gracefully fail when a connection is returned to this pool + # that the pool doesn't actually own + pass + + if self.owns_connection(connection): + self._available_connections.append(connection) + else: + # pool doesn't own this connection. do not add it back + # to the pool and decrement the count so that another + # connection can take its place if needed + self._created_connections -= 1 + connection.disconnect() + return + + def owns_connection(self, connection: "Connection") -> int: + return connection.pid == self.pid + + def disconnect(self, inuse_connections: bool = True) -> None: + """ + Disconnects connections in the pool + + If ``inuse_connections`` is True, disconnect connections that are + current in use, potentially by other threads. Otherwise only disconnect + connections that are idle in the pool. + """ + self._checkpid() + with self._lock: + if inuse_connections: + connections = chain( + self._available_connections, self._in_use_connections + ) + else: + connections = self._available_connections + + for connection in connections: + connection.disconnect() + + def close(self) -> None: + """Close the pool, disconnecting all connections""" + self.disconnect() + + def set_retry(self, retry: "Retry") -> None: + self.connection_kwargs.update({"retry": retry}) + for conn in self._available_connections: + conn.retry = retry + for conn in self._in_use_connections: + conn.retry = retry + + +class BlockingConnectionPool(ConnectionPool): + """ + Thread-safe blocking connection pool:: + + >>> from redis.client import Redis + >>> client = Redis(connection_pool=BlockingConnectionPool()) + + It performs the same function as the default + :py:class:`~redis.ConnectionPool` implementation, in that, + it maintains a pool of reusable connections that can be shared by + multiple redis clients (safely across threads if required). + + The difference is that, in the event that a client tries to get a + connection from the pool when all of connections are in use, rather than + raising a :py:class:`~redis.ConnectionError` (as the default + :py:class:`~redis.ConnectionPool` implementation does), it + makes the client wait ("blocks") for a specified number of seconds until + a connection becomes available. + + Use ``max_connections`` to increase / decrease the pool size:: + + >>> pool = BlockingConnectionPool(max_connections=10) + + Use ``timeout`` to tell it either how many seconds to wait for a connection + to become available, or to block forever: + + >>> # Block forever. + >>> pool = BlockingConnectionPool(timeout=None) + + >>> # Raise a ``ConnectionError`` after five seconds if a connection is + >>> # not available. + >>> pool = BlockingConnectionPool(timeout=5) + """ + + def __init__( + self, + max_connections=50, + timeout=20, + connection_class=Connection, + queue_class=LifoQueue, + **connection_kwargs, + ): + self.queue_class = queue_class + self.timeout = timeout + super().__init__( + connection_class=connection_class, + max_connections=max_connections, + **connection_kwargs, + ) + + def reset(self): + # Create and fill up a thread safe queue with ``None`` values. + self.pool = self.queue_class(self.max_connections) + while True: + try: + self.pool.put_nowait(None) + except Full: + break + + # Keep a list of actual connection instances so that we can + # disconnect them later. + self._connections = [] + + # this must be the last operation in this method. while reset() is + # called when holding _fork_lock, other threads in this process + # can call _checkpid() which compares self.pid and os.getpid() without + # holding any lock (for performance reasons). keeping this assignment + # as the last operation ensures that those other threads will also + # notice a pid difference and block waiting for the first thread to + # release _fork_lock. when each of these threads eventually acquire + # _fork_lock, they will notice that another thread already called + # reset() and they will immediately release _fork_lock and continue on. + self.pid = os.getpid() + + def make_connection(self): + "Make a fresh connection." + connection = self.connection_class(**self.connection_kwargs) + self._connections.append(connection) + return connection + + def get_connection(self, command_name, *keys, **options): + """ + Get a connection, blocking for ``self.timeout`` until a connection + is available from the pool. + + If the connection returned is ``None`` then creates a new connection. + Because we use a last-in first-out queue, the existing connections + (having been returned to the pool after the initial ``None`` values + were added) will be returned before ``None`` values. This means we only + create new connections when we need to, i.e.: the actual number of + connections will only increase in response to demand. + """ + # Make sure we haven't changed process. + self._checkpid() + + # Try and get a connection from the pool. If one isn't available within + # self.timeout then raise a ``ConnectionError``. + connection = None + try: + connection = self.pool.get(block=True, timeout=self.timeout) + except Empty: + # Note that this is not caught by the redis client and will be + # raised unless handled by application code. If you want never to + raise ConnectionError("No connection available.") + + # If the ``connection`` is actually ``None`` then that's a cue to make + # a new connection to add to the pool. + if connection is None: + connection = self.make_connection() + + try: + # ensure this connection is connected to Redis + connection.connect() + # connections that the pool provides should be ready to send + # a command. if not, the connection was either returned to the + # pool before all data has been read or the socket has been + # closed. either way, reconnect and verify everything is good. + try: + if connection.can_read(): + raise ConnectionError("Connection has data") + except (ConnectionError, OSError): + connection.disconnect() + connection.connect() + if connection.can_read(): + raise ConnectionError("Connection not ready") + except BaseException: + # release the connection back to the pool so that we don't leak it + self.release(connection) + raise + + return connection + + def release(self, connection): + "Releases the connection back to the pool." + # Make sure we haven't changed process. + self._checkpid() + if not self.owns_connection(connection): + # pool doesn't own this connection. do not add it back + # to the pool. instead add a None value which is a placeholder + # that will cause the pool to recreate the connection if + # its needed. + connection.disconnect() + self.pool.put_nowait(None) + return + + # Put the connection back into the pool. + try: + self.pool.put_nowait(connection) + except Full: + # perhaps the pool has been reset() after a fork? regardless, + # we don't want this connection + pass + + def disconnect(self): + "Disconnects all connections in the pool." + self._checkpid() + for connection in self._connections: + connection.disconnect() diff --git a/.venv/Lib/site-packages/redis/crc.py b/.venv/Lib/site-packages/redis/crc.py new file mode 100644 index 00000000..e2612411 --- /dev/null +++ b/.venv/Lib/site-packages/redis/crc.py @@ -0,0 +1,23 @@ +from binascii import crc_hqx + +from redis.typing import EncodedT + +# Redis Cluster's key space is divided into 16384 slots. +# For more information see: https://github.com/redis/redis/issues/2576 +REDIS_CLUSTER_HASH_SLOTS = 16384 + +__all__ = ["key_slot", "REDIS_CLUSTER_HASH_SLOTS"] + + +def key_slot(key: EncodedT, bucket: int = REDIS_CLUSTER_HASH_SLOTS) -> int: + """Calculate key slot for a given key. + See Keys distribution model in https://redis.io/topics/cluster-spec + :param key - bytes + :param bucket - int + """ + start = key.find(b"{") + if start > -1: + end = key.find(b"}", start + 1) + if end > -1 and end != start + 1: + key = key[start + 1 : end] + return crc_hqx(key, 0) % bucket diff --git a/.venv/Lib/site-packages/redis/credentials.py b/.venv/Lib/site-packages/redis/credentials.py new file mode 100644 index 00000000..7ba26dcd --- /dev/null +++ b/.venv/Lib/site-packages/redis/credentials.py @@ -0,0 +1,26 @@ +from typing import Optional, Tuple, Union + + +class CredentialProvider: + """ + Credentials Provider. + """ + + def get_credentials(self) -> Union[Tuple[str], Tuple[str, str]]: + raise NotImplementedError("get_credentials must be implemented") + + +class UsernamePasswordCredentialProvider(CredentialProvider): + """ + Simple implementation of CredentialProvider that just wraps static + username and password. + """ + + def __init__(self, username: Optional[str] = None, password: Optional[str] = None): + self.username = username or "" + self.password = password or "" + + def get_credentials(self): + if self.username: + return self.username, self.password + return (self.password,) diff --git a/.venv/Lib/site-packages/redis/exceptions.py b/.venv/Lib/site-packages/redis/exceptions.py new file mode 100644 index 00000000..7cf15a7d --- /dev/null +++ b/.venv/Lib/site-packages/redis/exceptions.py @@ -0,0 +1,218 @@ +"Core exceptions raised by the Redis client" + + +class RedisError(Exception): + pass + + +class ConnectionError(RedisError): + pass + + +class TimeoutError(RedisError): + pass + + +class AuthenticationError(ConnectionError): + pass + + +class AuthorizationError(ConnectionError): + pass + + +class BusyLoadingError(ConnectionError): + pass + + +class InvalidResponse(RedisError): + pass + + +class ResponseError(RedisError): + pass + + +class DataError(RedisError): + pass + + +class PubSubError(RedisError): + pass + + +class WatchError(RedisError): + pass + + +class NoScriptError(ResponseError): + pass + + +class OutOfMemoryError(ResponseError): + """ + Indicates the database is full. Can only occur when either: + * Redis maxmemory-policy=noeviction + * Redis maxmemory-policy=volatile* and there are no evictable keys + + For more information see `Memory optimization in Redis `_. # noqa + """ + + pass + + +class ExecAbortError(ResponseError): + pass + + +class ReadOnlyError(ResponseError): + pass + + +class NoPermissionError(ResponseError): + pass + + +class ModuleError(ResponseError): + pass + + +class LockError(RedisError, ValueError): + "Errors acquiring or releasing a lock" + # NOTE: For backwards compatibility, this class derives from ValueError. + # This was originally chosen to behave like threading.Lock. + pass + + +class LockNotOwnedError(LockError): + "Error trying to extend or release a lock that is (no longer) owned" + pass + + +class ChildDeadlockedError(Exception): + "Error indicating that a child process is deadlocked after a fork()" + pass + + +class AuthenticationWrongNumberOfArgsError(ResponseError): + """ + An error to indicate that the wrong number of args + were sent to the AUTH command + """ + + pass + + +class RedisClusterException(Exception): + """ + Base exception for the RedisCluster client + """ + + pass + + +class ClusterError(RedisError): + """ + Cluster errors occurred multiple times, resulting in an exhaustion of the + command execution TTL + """ + + pass + + +class ClusterDownError(ClusterError, ResponseError): + """ + Error indicated CLUSTERDOWN error received from cluster. + By default Redis Cluster nodes stop accepting queries if they detect there + is at least a hash slot uncovered (no available node is serving it). + This way if the cluster is partially down (for example a range of hash + slots are no longer covered) the entire cluster eventually becomes + unavailable. It automatically returns available as soon as all the slots + are covered again. + """ + + def __init__(self, resp): + self.args = (resp,) + self.message = resp + + +class AskError(ResponseError): + """ + Error indicated ASK error received from cluster. + When a slot is set as MIGRATING, the node will accept all queries that + pertain to this hash slot, but only if the key in question exists, + otherwise the query is forwarded using a -ASK redirection to the node that + is target of the migration. + + src node: MIGRATING to dst node + get > ASK error + ask dst node > ASKING command + dst node: IMPORTING from src node + asking command only affects next command + any op will be allowed after asking command + """ + + def __init__(self, resp): + """should only redirect to master node""" + self.args = (resp,) + self.message = resp + slot_id, new_node = resp.split(" ") + host, port = new_node.rsplit(":", 1) + self.slot_id = int(slot_id) + self.node_addr = self.host, self.port = host, int(port) + + +class TryAgainError(ResponseError): + """ + Error indicated TRYAGAIN error received from cluster. + Operations on keys that don't exist or are - during resharding - split + between the source and destination nodes, will generate a -TRYAGAIN error. + """ + + def __init__(self, *args, **kwargs): + pass + + +class ClusterCrossSlotError(ResponseError): + """ + Error indicated CROSSSLOT error received from cluster. + A CROSSSLOT error is generated when keys in a request don't hash to the + same slot. + """ + + message = "Keys in request don't hash to the same slot" + + +class MovedError(AskError): + """ + Error indicated MOVED error received from cluster. + A request sent to a node that doesn't serve this key will be replayed with + a MOVED error that points to the correct node. + """ + + pass + + +class MasterDownError(ClusterDownError): + """ + Error indicated MASTERDOWN error received from cluster. + Link with MASTER is down and replica-serve-stale-data is set to 'no'. + """ + + pass + + +class SlotNotCoveredError(RedisClusterException): + """ + This error only happens in the case where the connection pool will try to + fetch what node that is covered by a given slot. + + If this error is raised the client should drop the current node layout and + attempt to reconnect and refresh the node layout again + """ + + pass + + +class MaxConnectionsError(ConnectionError): + ... diff --git a/.venv/Lib/site-packages/redis/lock.py b/.venv/Lib/site-packages/redis/lock.py new file mode 100644 index 00000000..4cca102d --- /dev/null +++ b/.venv/Lib/site-packages/redis/lock.py @@ -0,0 +1,308 @@ +import threading +import time as mod_time +import uuid +from types import SimpleNamespace, TracebackType +from typing import Optional, Type + +from redis.exceptions import LockError, LockNotOwnedError +from redis.typing import Number + + +class Lock: + """ + A shared, distributed Lock. Using Redis for locking allows the Lock + to be shared across processes and/or machines. + + It's left to the user to resolve deadlock issues and make sure + multiple clients play nicely together. + """ + + lua_release = None + lua_extend = None + lua_reacquire = None + + # KEYS[1] - lock name + # ARGV[1] - token + # return 1 if the lock was released, otherwise 0 + LUA_RELEASE_SCRIPT = """ + local token = redis.call('get', KEYS[1]) + if not token or token ~= ARGV[1] then + return 0 + end + redis.call('del', KEYS[1]) + return 1 + """ + + # KEYS[1] - lock name + # ARGV[1] - token + # ARGV[2] - additional milliseconds + # ARGV[3] - "0" if the additional time should be added to the lock's + # existing ttl or "1" if the existing ttl should be replaced + # return 1 if the locks time was extended, otherwise 0 + LUA_EXTEND_SCRIPT = """ + local token = redis.call('get', KEYS[1]) + if not token or token ~= ARGV[1] then + return 0 + end + local expiration = redis.call('pttl', KEYS[1]) + if not expiration then + expiration = 0 + end + if expiration < 0 then + return 0 + end + + local newttl = ARGV[2] + if ARGV[3] == "0" then + newttl = ARGV[2] + expiration + end + redis.call('pexpire', KEYS[1], newttl) + return 1 + """ + + # KEYS[1] - lock name + # ARGV[1] - token + # ARGV[2] - milliseconds + # return 1 if the locks time was reacquired, otherwise 0 + LUA_REACQUIRE_SCRIPT = """ + local token = redis.call('get', KEYS[1]) + if not token or token ~= ARGV[1] then + return 0 + end + redis.call('pexpire', KEYS[1], ARGV[2]) + return 1 + """ + + def __init__( + self, + redis, + name: str, + timeout: Optional[Number] = None, + sleep: Number = 0.1, + blocking: bool = True, + blocking_timeout: Optional[Number] = None, + thread_local: bool = True, + ): + """ + Create a new Lock instance named ``name`` using the Redis client + supplied by ``redis``. + + ``timeout`` indicates a maximum life for the lock in seconds. + By default, it will remain locked until release() is called. + ``timeout`` can be specified as a float or integer, both representing + the number of seconds to wait. + + ``sleep`` indicates the amount of time to sleep in seconds per loop + iteration when the lock is in blocking mode and another client is + currently holding the lock. + + ``blocking`` indicates whether calling ``acquire`` should block until + the lock has been acquired or to fail immediately, causing ``acquire`` + to return False and the lock not being acquired. Defaults to True. + Note this value can be overridden by passing a ``blocking`` + argument to ``acquire``. + + ``blocking_timeout`` indicates the maximum amount of time in seconds to + spend trying to acquire the lock. A value of ``None`` indicates + continue trying forever. ``blocking_timeout`` can be specified as a + float or integer, both representing the number of seconds to wait. + + ``thread_local`` indicates whether the lock token is placed in + thread-local storage. By default, the token is placed in thread local + storage so that a thread only sees its token, not a token set by + another thread. Consider the following timeline: + + time: 0, thread-1 acquires `my-lock`, with a timeout of 5 seconds. + thread-1 sets the token to "abc" + time: 1, thread-2 blocks trying to acquire `my-lock` using the + Lock instance. + time: 5, thread-1 has not yet completed. redis expires the lock + key. + time: 5, thread-2 acquired `my-lock` now that it's available. + thread-2 sets the token to "xyz" + time: 6, thread-1 finishes its work and calls release(). if the + token is *not* stored in thread local storage, then + thread-1 would see the token value as "xyz" and would be + able to successfully release the thread-2's lock. + + In some use cases it's necessary to disable thread local storage. For + example, if you have code where one thread acquires a lock and passes + that lock instance to a worker thread to release later. If thread + local storage isn't disabled in this case, the worker thread won't see + the token set by the thread that acquired the lock. Our assumption + is that these cases aren't common and as such default to using + thread local storage. + """ + self.redis = redis + self.name = name + self.timeout = timeout + self.sleep = sleep + self.blocking = blocking + self.blocking_timeout = blocking_timeout + self.thread_local = bool(thread_local) + self.local = threading.local() if self.thread_local else SimpleNamespace() + self.local.token = None + self.register_scripts() + + def register_scripts(self) -> None: + cls = self.__class__ + client = self.redis + if cls.lua_release is None: + cls.lua_release = client.register_script(cls.LUA_RELEASE_SCRIPT) + if cls.lua_extend is None: + cls.lua_extend = client.register_script(cls.LUA_EXTEND_SCRIPT) + if cls.lua_reacquire is None: + cls.lua_reacquire = client.register_script(cls.LUA_REACQUIRE_SCRIPT) + + def __enter__(self) -> "Lock": + if self.acquire(): + return self + raise LockError("Unable to acquire lock within the time specified") + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_value: Optional[BaseException], + traceback: Optional[TracebackType], + ) -> None: + self.release() + + def acquire( + self, + sleep: Optional[Number] = None, + blocking: Optional[bool] = None, + blocking_timeout: Optional[Number] = None, + token: Optional[str] = None, + ): + """ + Use Redis to hold a shared, distributed lock named ``name``. + Returns True once the lock is acquired. + + If ``blocking`` is False, always return immediately. If the lock + was acquired, return True, otherwise return False. + + ``blocking_timeout`` specifies the maximum number of seconds to + wait trying to acquire the lock. + + ``token`` specifies the token value to be used. If provided, token + must be a bytes object or a string that can be encoded to a bytes + object with the default encoding. If a token isn't specified, a UUID + will be generated. + """ + if sleep is None: + sleep = self.sleep + if token is None: + token = uuid.uuid1().hex.encode() + else: + encoder = self.redis.get_encoder() + token = encoder.encode(token) + if blocking is None: + blocking = self.blocking + if blocking_timeout is None: + blocking_timeout = self.blocking_timeout + stop_trying_at = None + if blocking_timeout is not None: + stop_trying_at = mod_time.monotonic() + blocking_timeout + while True: + if self.do_acquire(token): + self.local.token = token + return True + if not blocking: + return False + next_try_at = mod_time.monotonic() + sleep + if stop_trying_at is not None and next_try_at > stop_trying_at: + return False + mod_time.sleep(sleep) + + def do_acquire(self, token: str) -> bool: + if self.timeout: + # convert to milliseconds + timeout = int(self.timeout * 1000) + else: + timeout = None + if self.redis.set(self.name, token, nx=True, px=timeout): + return True + return False + + def locked(self) -> bool: + """ + Returns True if this key is locked by any process, otherwise False. + """ + return self.redis.get(self.name) is not None + + def owned(self) -> bool: + """ + Returns True if this key is locked by this lock, otherwise False. + """ + stored_token = self.redis.get(self.name) + # need to always compare bytes to bytes + # TODO: this can be simplified when the context manager is finished + if stored_token and not isinstance(stored_token, bytes): + encoder = self.redis.get_encoder() + stored_token = encoder.encode(stored_token) + return self.local.token is not None and stored_token == self.local.token + + def release(self) -> None: + """ + Releases the already acquired lock + """ + expected_token = self.local.token + if expected_token is None: + raise LockError("Cannot release an unlocked lock") + self.local.token = None + self.do_release(expected_token) + + def do_release(self, expected_token: str) -> None: + if not bool( + self.lua_release(keys=[self.name], args=[expected_token], client=self.redis) + ): + raise LockNotOwnedError("Cannot release a lock that's no longer owned") + + def extend(self, additional_time: int, replace_ttl: bool = False) -> bool: + """ + Adds more time to an already acquired lock. + + ``additional_time`` can be specified as an integer or a float, both + representing the number of seconds to add. + + ``replace_ttl`` if False (the default), add `additional_time` to + the lock's existing ttl. If True, replace the lock's ttl with + `additional_time`. + """ + if self.local.token is None: + raise LockError("Cannot extend an unlocked lock") + if self.timeout is None: + raise LockError("Cannot extend a lock with no timeout") + return self.do_extend(additional_time, replace_ttl) + + def do_extend(self, additional_time: int, replace_ttl: bool) -> bool: + additional_time = int(additional_time * 1000) + if not bool( + self.lua_extend( + keys=[self.name], + args=[self.local.token, additional_time, "1" if replace_ttl else "0"], + client=self.redis, + ) + ): + raise LockNotOwnedError("Cannot extend a lock that's no longer owned") + return True + + def reacquire(self) -> bool: + """ + Resets a TTL of an already acquired lock back to a timeout value. + """ + if self.local.token is None: + raise LockError("Cannot reacquire an unlocked lock") + if self.timeout is None: + raise LockError("Cannot reacquire a lock with no timeout") + return self.do_reacquire() + + def do_reacquire(self) -> bool: + timeout = int(self.timeout * 1000) + if not bool( + self.lua_reacquire( + keys=[self.name], args=[self.local.token, timeout], client=self.redis + ) + ): + raise LockNotOwnedError("Cannot reacquire a lock that's no longer owned") + return True diff --git a/.venv/Lib/site-packages/redis/ocsp.py b/.venv/Lib/site-packages/redis/ocsp.py new file mode 100644 index 00000000..b0420b47 --- /dev/null +++ b/.venv/Lib/site-packages/redis/ocsp.py @@ -0,0 +1,307 @@ +import base64 +import datetime +import ssl +from urllib.parse import urljoin, urlparse + +import cryptography.hazmat.primitives.hashes +import requests +from cryptography import hazmat, x509 +from cryptography.exceptions import InvalidSignature +from cryptography.hazmat import backends +from cryptography.hazmat.primitives.asymmetric.dsa import DSAPublicKey +from cryptography.hazmat.primitives.asymmetric.ec import ECDSA, EllipticCurvePublicKey +from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15 +from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey +from cryptography.hazmat.primitives.hashes import SHA1, Hash +from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat +from cryptography.x509 import ocsp +from redis.exceptions import AuthorizationError, ConnectionError + + +def _verify_response(issuer_cert, ocsp_response): + pubkey = issuer_cert.public_key() + try: + if isinstance(pubkey, RSAPublicKey): + pubkey.verify( + ocsp_response.signature, + ocsp_response.tbs_response_bytes, + PKCS1v15(), + ocsp_response.signature_hash_algorithm, + ) + elif isinstance(pubkey, DSAPublicKey): + pubkey.verify( + ocsp_response.signature, + ocsp_response.tbs_response_bytes, + ocsp_response.signature_hash_algorithm, + ) + elif isinstance(pubkey, EllipticCurvePublicKey): + pubkey.verify( + ocsp_response.signature, + ocsp_response.tbs_response_bytes, + ECDSA(ocsp_response.signature_hash_algorithm), + ) + else: + pubkey.verify(ocsp_response.signature, ocsp_response.tbs_response_bytes) + except InvalidSignature: + raise ConnectionError("failed to valid ocsp response") + + +def _check_certificate(issuer_cert, ocsp_bytes, validate=True): + """A wrapper the return the validity of a known ocsp certificate""" + + ocsp_response = ocsp.load_der_ocsp_response(ocsp_bytes) + + if ocsp_response.response_status == ocsp.OCSPResponseStatus.UNAUTHORIZED: + raise AuthorizationError("you are not authorized to view this ocsp certificate") + if ocsp_response.response_status == ocsp.OCSPResponseStatus.SUCCESSFUL: + if ocsp_response.certificate_status != ocsp.OCSPCertStatus.GOOD: + raise ConnectionError( + f'Received an {str(ocsp_response.certificate_status).split(".")[1]} ' + "ocsp certificate status" + ) + else: + raise ConnectionError( + "failed to retrieve a sucessful response from the ocsp responder" + ) + + if ocsp_response.this_update >= datetime.datetime.now(): + raise ConnectionError("ocsp certificate was issued in the future") + + if ( + ocsp_response.next_update + and ocsp_response.next_update < datetime.datetime.now() + ): + raise ConnectionError("ocsp certificate has invalid update - in the past") + + responder_name = ocsp_response.responder_name + issuer_hash = ocsp_response.issuer_key_hash + responder_hash = ocsp_response.responder_key_hash + + cert_to_validate = issuer_cert + if ( + responder_name is not None + and responder_name == issuer_cert.subject + or responder_hash == issuer_hash + ): + cert_to_validate = issuer_cert + else: + certs = ocsp_response.certificates + responder_certs = _get_certificates( + certs, issuer_cert, responder_name, responder_hash + ) + + try: + responder_cert = responder_certs[0] + except IndexError: + raise ConnectionError("no certificates found for the responder") + + ext = responder_cert.extensions.get_extension_for_class(x509.ExtendedKeyUsage) + if ext is None or x509.oid.ExtendedKeyUsageOID.OCSP_SIGNING not in ext.value: + raise ConnectionError("delegate not autorized for ocsp signing") + cert_to_validate = responder_cert + + if validate: + _verify_response(cert_to_validate, ocsp_response) + return True + + +def _get_certificates(certs, issuer_cert, responder_name, responder_hash): + if responder_name is None: + certificates = [ + c + for c in certs + if _get_pubkey_hash(c) == responder_hash and c.issuer == issuer_cert.subject + ] + else: + certificates = [ + c + for c in certs + if c.subject == responder_name and c.issuer == issuer_cert.subject + ] + + return certificates + + +def _get_pubkey_hash(certificate): + pubkey = certificate.public_key() + + # https://stackoverflow.com/a/46309453/600498 + if isinstance(pubkey, RSAPublicKey): + h = pubkey.public_bytes(Encoding.DER, PublicFormat.PKCS1) + elif isinstance(pubkey, EllipticCurvePublicKey): + h = pubkey.public_bytes(Encoding.X962, PublicFormat.UncompressedPoint) + else: + h = pubkey.public_bytes(Encoding.DER, PublicFormat.SubjectPublicKeyInfo) + + sha1 = Hash(SHA1(), backend=backends.default_backend()) + sha1.update(h) + return sha1.finalize() + + +def ocsp_staple_verifier(con, ocsp_bytes, expected=None): + """An implemention of a function for set_ocsp_client_callback in PyOpenSSL. + + This function validates that the provide ocsp_bytes response is valid, + and matches the expected, stapled responses. + """ + if ocsp_bytes in [b"", None]: + raise ConnectionError("no ocsp response present") + + issuer_cert = None + peer_cert = con.get_peer_certificate().to_cryptography() + for c in con.get_peer_cert_chain(): + cert = c.to_cryptography() + if cert.subject == peer_cert.issuer: + issuer_cert = cert + break + + if issuer_cert is None: + raise ConnectionError("no matching issuer cert found in certificate chain") + + if expected is not None: + e = x509.load_pem_x509_certificate(expected) + if peer_cert != e: + raise ConnectionError("received and expected certificates do not match") + + return _check_certificate(issuer_cert, ocsp_bytes) + + +class OCSPVerifier: + """A class to verify ssl sockets for RFC6960/RFC6961. This can be used + when using direct validation of OCSP responses and certificate revocations. + + @see https://datatracker.ietf.org/doc/html/rfc6960 + @see https://datatracker.ietf.org/doc/html/rfc6961 + """ + + def __init__(self, sock, host, port, ca_certs=None): + self.SOCK = sock + self.HOST = host + self.PORT = port + self.CA_CERTS = ca_certs + + def _bin2ascii(self, der): + """Convert SSL certificates in a binary (DER) format to ASCII PEM.""" + + pem = ssl.DER_cert_to_PEM_cert(der) + cert = x509.load_pem_x509_certificate(pem.encode(), backends.default_backend()) + return cert + + def components_from_socket(self): + """This function returns the certificate, primary issuer, and primary ocsp + server in the chain for a socket already wrapped with ssl. + """ + + # convert the binary certifcate to text + der = self.SOCK.getpeercert(True) + if der is False: + raise ConnectionError("no certificate found for ssl peer") + cert = self._bin2ascii(der) + return self._certificate_components(cert) + + def _certificate_components(self, cert): + """Given an SSL certificate, retract the useful components for + validating the certificate status with an OCSP server. + + Args: + cert ([bytes]): A PEM encoded ssl certificate + """ + + try: + aia = cert.extensions.get_extension_for_oid( + x509.oid.ExtensionOID.AUTHORITY_INFORMATION_ACCESS + ).value + except cryptography.x509.extensions.ExtensionNotFound: + raise ConnectionError("No AIA information present in ssl certificate") + + # fetch certificate issuers + issuers = [ + i + for i in aia + if i.access_method == x509.oid.AuthorityInformationAccessOID.CA_ISSUERS + ] + try: + issuer = issuers[0].access_location.value + except IndexError: + issuer = None + + # now, the series of ocsp server entries + ocsps = [ + i + for i in aia + if i.access_method == x509.oid.AuthorityInformationAccessOID.OCSP + ] + + try: + ocsp = ocsps[0].access_location.value + except IndexError: + raise ConnectionError("no ocsp servers in certificate") + + return cert, issuer, ocsp + + def components_from_direct_connection(self): + """Return the certificate, primary issuer, and primary ocsp server + from the host defined by the socket. This is useful in cases where + different certificates are occasionally presented. + """ + + pem = ssl.get_server_certificate((self.HOST, self.PORT), ca_certs=self.CA_CERTS) + cert = x509.load_pem_x509_certificate(pem.encode(), backends.default_backend()) + return self._certificate_components(cert) + + def build_certificate_url(self, server, cert, issuer_cert): + """Return the complete url to the ocsp""" + orb = ocsp.OCSPRequestBuilder() + + # add_certificate returns an initialized OCSPRequestBuilder + orb = orb.add_certificate( + cert, issuer_cert, cryptography.hazmat.primitives.hashes.SHA256() + ) + request = orb.build() + + path = base64.b64encode( + request.public_bytes(hazmat.primitives.serialization.Encoding.DER) + ) + url = urljoin(server, path.decode("ascii")) + return url + + def check_certificate(self, server, cert, issuer_url): + """Checks the validitity of an ocsp server for an issuer""" + + r = requests.get(issuer_url) + if not r.ok: + raise ConnectionError("failed to fetch issuer certificate") + der = r.content + issuer_cert = self._bin2ascii(der) + + ocsp_url = self.build_certificate_url(server, cert, issuer_cert) + + # HTTP 1.1 mandates the addition of the Host header in ocsp responses + header = { + "Host": urlparse(ocsp_url).netloc, + "Content-Type": "application/ocsp-request", + } + r = requests.get(ocsp_url, headers=header) + if not r.ok: + raise ConnectionError("failed to fetch ocsp certificate") + return _check_certificate(issuer_cert, r.content, True) + + def is_valid(self): + """Returns the validity of the certificate wrapping our socket. + This first retrieves for validate the certificate, issuer_url, + and ocsp_server for certificate validate. Then retrieves the + issuer certificate from the issuer_url, and finally checks + the validity of OCSP revocation status. + """ + + # validate the certificate + try: + cert, issuer_url, ocsp_server = self.components_from_socket() + if issuer_url is None: + raise ConnectionError("no issuers found in certificate chain") + return self.check_certificate(ocsp_server, cert, issuer_url) + except AuthorizationError: + cert, issuer_url, ocsp_server = self.components_from_direct_connection() + if issuer_url is None: + raise ConnectionError("no issuers found in certificate chain") + return self.check_certificate(ocsp_server, cert, issuer_url) diff --git a/.venv/Lib/site-packages/redis/py.typed b/.venv/Lib/site-packages/redis/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/.venv/Lib/site-packages/redis/retry.py b/.venv/Lib/site-packages/redis/retry.py new file mode 100644 index 00000000..60644305 --- /dev/null +++ b/.venv/Lib/site-packages/redis/retry.py @@ -0,0 +1,54 @@ +import socket +from time import sleep + +from redis.exceptions import ConnectionError, TimeoutError + + +class Retry: + """Retry a specific number of times after a failure""" + + def __init__( + self, + backoff, + retries, + supported_errors=(ConnectionError, TimeoutError, socket.timeout), + ): + """ + Initialize a `Retry` object with a `Backoff` object + that retries a maximum of `retries` times. + `retries` can be negative to retry forever. + You can specify the types of supported errors which trigger + a retry with the `supported_errors` parameter. + """ + self._backoff = backoff + self._retries = retries + self._supported_errors = supported_errors + + def update_supported_errors(self, specified_errors: list): + """ + Updates the supported errors with the specified error types + """ + self._supported_errors = tuple( + set(self._supported_errors + tuple(specified_errors)) + ) + + def call_with_retry(self, do, fail): + """ + Execute an operation that might fail and returns its result, or + raise the exception that was thrown depending on the `Backoff` object. + `do`: the operation to call. Expects no argument. + `fail`: the failure handler, expects the last error that was thrown + """ + self._backoff.reset() + failures = 0 + while True: + try: + return do() + except self._supported_errors as error: + failures += 1 + fail(error) + if self._retries >= 0 and failures > self._retries: + raise error + backoff = self._backoff.compute(failures) + if backoff > 0: + sleep(backoff) diff --git a/.venv/Lib/site-packages/redis/sentinel.py b/.venv/Lib/site-packages/redis/sentinel.py new file mode 100644 index 00000000..41f308d1 --- /dev/null +++ b/.venv/Lib/site-packages/redis/sentinel.py @@ -0,0 +1,389 @@ +import random +import weakref +from typing import Optional + +from redis.client import Redis +from redis.commands import SentinelCommands +from redis.connection import Connection, ConnectionPool, SSLConnection +from redis.exceptions import ConnectionError, ReadOnlyError, ResponseError, TimeoutError +from redis.utils import str_if_bytes + + +class MasterNotFoundError(ConnectionError): + pass + + +class SlaveNotFoundError(ConnectionError): + pass + + +class SentinelManagedConnection(Connection): + def __init__(self, **kwargs): + self.connection_pool = kwargs.pop("connection_pool") + super().__init__(**kwargs) + + def __repr__(self): + pool = self.connection_pool + s = f"{type(self).__name__}" + if self.host: + host_info = f",host={self.host},port={self.port}" + s = s % host_info + return s + + def connect_to(self, address): + self.host, self.port = address + super().connect() + if self.connection_pool.check_connection: + self.send_command("PING") + if str_if_bytes(self.read_response()) != "PONG": + raise ConnectionError("PING failed") + + def _connect_retry(self): + if self._sock: + return # already connected + if self.connection_pool.is_master: + self.connect_to(self.connection_pool.get_master_address()) + else: + for slave in self.connection_pool.rotate_slaves(): + try: + return self.connect_to(slave) + except ConnectionError: + continue + raise SlaveNotFoundError # Never be here + + def connect(self): + return self.retry.call_with_retry(self._connect_retry, lambda error: None) + + def read_response( + self, + disable_decoding=False, + *, + disconnect_on_error: Optional[bool] = False, + push_request: Optional[bool] = False, + ): + try: + return super().read_response( + disable_decoding=disable_decoding, + disconnect_on_error=disconnect_on_error, + push_request=push_request, + ) + except ReadOnlyError: + if self.connection_pool.is_master: + # When talking to a master, a ReadOnlyError when likely + # indicates that the previous master that we're still connected + # to has been demoted to a slave and there's a new master. + # calling disconnect will force the connection to re-query + # sentinel during the next connect() attempt. + self.disconnect() + raise ConnectionError("The previous master is now a slave") + raise + + +class SentinelManagedSSLConnection(SentinelManagedConnection, SSLConnection): + pass + + +class SentinelConnectionPoolProxy: + def __init__( + self, + connection_pool, + is_master, + check_connection, + service_name, + sentinel_manager, + ): + self.connection_pool_ref = weakref.ref(connection_pool) + self.is_master = is_master + self.check_connection = check_connection + self.service_name = service_name + self.sentinel_manager = sentinel_manager + self.reset() + + def reset(self): + self.master_address = None + self.slave_rr_counter = None + + def get_master_address(self): + master_address = self.sentinel_manager.discover_master(self.service_name) + if self.is_master and self.master_address != master_address: + self.master_address = master_address + # disconnect any idle connections so that they reconnect + # to the new master the next time that they are used. + connection_pool = self.connection_pool_ref() + if connection_pool is not None: + connection_pool.disconnect(inuse_connections=False) + return master_address + + def rotate_slaves(self): + slaves = self.sentinel_manager.discover_slaves(self.service_name) + if slaves: + if self.slave_rr_counter is None: + self.slave_rr_counter = random.randint(0, len(slaves) - 1) + for _ in range(len(slaves)): + self.slave_rr_counter = (self.slave_rr_counter + 1) % len(slaves) + slave = slaves[self.slave_rr_counter] + yield slave + # Fallback to the master connection + try: + yield self.get_master_address() + except MasterNotFoundError: + pass + raise SlaveNotFoundError(f"No slave found for {self.service_name!r}") + + +class SentinelConnectionPool(ConnectionPool): + """ + Sentinel backed connection pool. + + If ``check_connection`` flag is set to True, SentinelManagedConnection + sends a PING command right after establishing the connection. + """ + + def __init__(self, service_name, sentinel_manager, **kwargs): + kwargs["connection_class"] = kwargs.get( + "connection_class", + SentinelManagedSSLConnection + if kwargs.pop("ssl", False) + else SentinelManagedConnection, + ) + self.is_master = kwargs.pop("is_master", True) + self.check_connection = kwargs.pop("check_connection", False) + self.proxy = SentinelConnectionPoolProxy( + connection_pool=self, + is_master=self.is_master, + check_connection=self.check_connection, + service_name=service_name, + sentinel_manager=sentinel_manager, + ) + super().__init__(**kwargs) + self.connection_kwargs["connection_pool"] = self.proxy + self.service_name = service_name + self.sentinel_manager = sentinel_manager + + def __repr__(self): + role = "master" if self.is_master else "slave" + return f"{type(self).__name__}>> from redis.sentinel import Sentinel + >>> sentinel = Sentinel([('localhost', 26379)], socket_timeout=0.1) + >>> master = sentinel.master_for('mymaster', socket_timeout=0.1) + >>> master.set('foo', 'bar') + >>> slave = sentinel.slave_for('mymaster', socket_timeout=0.1) + >>> slave.get('foo') + b'bar' + + ``sentinels`` is a list of sentinel nodes. Each node is represented by + a pair (hostname, port). + + ``min_other_sentinels`` defined a minimum number of peers for a sentinel. + When querying a sentinel, if it doesn't meet this threshold, responses + from that sentinel won't be considered valid. + + ``sentinel_kwargs`` is a dictionary of connection arguments used when + connecting to sentinel instances. Any argument that can be passed to + a normal Redis connection can be specified here. If ``sentinel_kwargs`` is + not specified, any socket_timeout and socket_keepalive options specified + in ``connection_kwargs`` will be used. + + ``connection_kwargs`` are keyword arguments that will be used when + establishing a connection to a Redis server. + """ + + def __init__( + self, + sentinels, + min_other_sentinels=0, + sentinel_kwargs=None, + **connection_kwargs, + ): + # if sentinel_kwargs isn't defined, use the socket_* options from + # connection_kwargs + if sentinel_kwargs is None: + sentinel_kwargs = { + k: v for k, v in connection_kwargs.items() if k.startswith("socket_") + } + self.sentinel_kwargs = sentinel_kwargs + + self.sentinels = [ + Redis(hostname, port, **self.sentinel_kwargs) + for hostname, port in sentinels + ] + self.min_other_sentinels = min_other_sentinels + self.connection_kwargs = connection_kwargs + + def execute_command(self, *args, **kwargs): + """ + Execute Sentinel command in sentinel nodes. + once - If set to True, then execute the resulting command on a single + node at random, rather than across the entire sentinel cluster. + """ + once = bool(kwargs.get("once", False)) + if "once" in kwargs.keys(): + kwargs.pop("once") + + if once: + random.choice(self.sentinels).execute_command(*args, **kwargs) + else: + for sentinel in self.sentinels: + sentinel.execute_command(*args, **kwargs) + return True + + def __repr__(self): + sentinel_addresses = [] + for sentinel in self.sentinels: + sentinel_addresses.append( + "{host}:{port}".format_map(sentinel.connection_pool.connection_kwargs) + ) + return f'{type(self).__name__}' + + def check_master_state(self, state, service_name): + if not state["is_master"] or state["is_sdown"] or state["is_odown"]: + return False + # Check if our sentinel doesn't see other nodes + if state["num-other-sentinels"] < self.min_other_sentinels: + return False + return True + + def discover_master(self, service_name): + """ + Asks sentinel servers for the Redis master's address corresponding + to the service labeled ``service_name``. + + Returns a pair (address, port) or raises MasterNotFoundError if no + master is found. + """ + collected_errors = list() + for sentinel_no, sentinel in enumerate(self.sentinels): + try: + masters = sentinel.sentinel_masters() + except (ConnectionError, TimeoutError) as e: + collected_errors.append(f"{sentinel} - {e!r}") + continue + state = masters.get(service_name) + if state and self.check_master_state(state, service_name): + # Put this sentinel at the top of the list + self.sentinels[0], self.sentinels[sentinel_no] = ( + sentinel, + self.sentinels[0], + ) + return state["ip"], state["port"] + + error_info = "" + if len(collected_errors) > 0: + error_info = f" : {', '.join(collected_errors)}" + raise MasterNotFoundError(f"No master found for {service_name!r}{error_info}") + + def filter_slaves(self, slaves): + "Remove slaves that are in an ODOWN or SDOWN state" + slaves_alive = [] + for slave in slaves: + if slave["is_odown"] or slave["is_sdown"]: + continue + slaves_alive.append((slave["ip"], slave["port"])) + return slaves_alive + + def discover_slaves(self, service_name): + "Returns a list of alive slaves for service ``service_name``" + for sentinel in self.sentinels: + try: + slaves = sentinel.sentinel_slaves(service_name) + except (ConnectionError, ResponseError, TimeoutError): + continue + slaves = self.filter_slaves(slaves) + if slaves: + return slaves + return [] + + def master_for( + self, + service_name, + redis_class=Redis, + connection_pool_class=SentinelConnectionPool, + **kwargs, + ): + """ + Returns a redis client instance for the ``service_name`` master. + + A :py:class:`~redis.sentinel.SentinelConnectionPool` class is + used to retrieve the master's address before establishing a new + connection. + + NOTE: If the master's address has changed, any cached connections to + the old master are closed. + + By default clients will be a :py:class:`~redis.Redis` instance. + Specify a different class to the ``redis_class`` argument if you + desire something different. + + The ``connection_pool_class`` specifies the connection pool to + use. The :py:class:`~redis.sentinel.SentinelConnectionPool` + will be used by default. + + All other keyword arguments are merged with any connection_kwargs + passed to this class and passed to the connection pool as keyword + arguments to be used to initialize Redis connections. + """ + kwargs["is_master"] = True + connection_kwargs = dict(self.connection_kwargs) + connection_kwargs.update(kwargs) + return redis_class.from_pool( + connection_pool_class(service_name, self, **connection_kwargs) + ) + + def slave_for( + self, + service_name, + redis_class=Redis, + connection_pool_class=SentinelConnectionPool, + **kwargs, + ): + """ + Returns redis client instance for the ``service_name`` slave(s). + + A SentinelConnectionPool class is used to retrieve the slave's + address before establishing a new connection. + + By default clients will be a :py:class:`~redis.Redis` instance. + Specify a different class to the ``redis_class`` argument if you + desire something different. + + The ``connection_pool_class`` specifies the connection pool to use. + The SentinelConnectionPool will be used by default. + + All other keyword arguments are merged with any connection_kwargs + passed to this class and passed to the connection pool as keyword + arguments to be used to initialize Redis connections. + """ + kwargs["is_master"] = False + connection_kwargs = dict(self.connection_kwargs) + connection_kwargs.update(kwargs) + return redis_class.from_pool( + connection_pool_class(service_name, self, **connection_kwargs) + ) diff --git a/.venv/Lib/site-packages/redis/typing.py b/.venv/Lib/site-packages/redis/typing.py new file mode 100644 index 00000000..56a1e99b --- /dev/null +++ b/.venv/Lib/site-packages/redis/typing.py @@ -0,0 +1,65 @@ +# from __future__ import annotations + +from datetime import datetime, timedelta +from typing import ( + TYPE_CHECKING, + Any, + Awaitable, + Iterable, + Mapping, + Type, + TypeVar, + Union, +) + +from redis.compat import Protocol + +if TYPE_CHECKING: + from redis._parsers import Encoder + from redis.asyncio.connection import ConnectionPool as AsyncConnectionPool + from redis.connection import ConnectionPool + + +Number = Union[int, float] +EncodedT = Union[bytes, memoryview] +DecodedT = Union[str, int, float] +EncodableT = Union[EncodedT, DecodedT] +AbsExpiryT = Union[int, datetime] +ExpiryT = Union[int, timedelta] +ZScoreBoundT = Union[float, str] # str allows for the [ or ( prefix +BitfieldOffsetT = Union[int, str] # str allows for #x syntax +_StringLikeT = Union[bytes, str, memoryview] +KeyT = _StringLikeT # Main redis key space +PatternT = _StringLikeT # Patterns matched against keys, fields etc +FieldT = EncodableT # Fields within hash tables, streams and geo commands +KeysT = Union[KeyT, Iterable[KeyT]] +ChannelT = _StringLikeT +GroupT = _StringLikeT # Consumer group +ConsumerT = _StringLikeT # Consumer name +StreamIdT = Union[int, _StringLikeT] +ScriptTextT = _StringLikeT +TimeoutSecT = Union[int, float, _StringLikeT] +# Mapping is not covariant in the key type, which prevents +# Mapping[_StringLikeT, X] from accepting arguments of type Dict[str, X]. Using +# a TypeVar instead of a Union allows mappings with any of the permitted types +# to be passed. Care is needed if there is more than one such mapping in a +# type signature because they will all be required to be the same key type. +AnyKeyT = TypeVar("AnyKeyT", bytes, str, memoryview) +AnyFieldT = TypeVar("AnyFieldT", bytes, str, memoryview) +AnyChannelT = TypeVar("AnyChannelT", bytes, str, memoryview) + +ExceptionMappingT = Mapping[str, Union[Type[Exception], Mapping[str, Type[Exception]]]] + + +class CommandsProtocol(Protocol): + connection_pool: Union["AsyncConnectionPool", "ConnectionPool"] + + def execute_command(self, *args, **options): + ... + + +class ClusterCommandsProtocol(CommandsProtocol, Protocol): + encoder: "Encoder" + + def execute_command(self, *args, **options) -> Union[Any, Awaitable]: + ... diff --git a/.venv/Lib/site-packages/redis/utils.py b/.venv/Lib/site-packages/redis/utils.py new file mode 100644 index 00000000..01fdfed7 --- /dev/null +++ b/.venv/Lib/site-packages/redis/utils.py @@ -0,0 +1,147 @@ +import logging +import sys +from contextlib import contextmanager +from functools import wraps +from typing import Any, Dict, Mapping, Union + +try: + import hiredis # noqa + + # Only support Hiredis >= 1.0: + HIREDIS_AVAILABLE = not hiredis.__version__.startswith("0.") + HIREDIS_PACK_AVAILABLE = hasattr(hiredis, "pack_command") +except ImportError: + HIREDIS_AVAILABLE = False + HIREDIS_PACK_AVAILABLE = False + +try: + import ssl # noqa + + SSL_AVAILABLE = True +except ImportError: + SSL_AVAILABLE = False + +try: + import cryptography # noqa + + CRYPTOGRAPHY_AVAILABLE = True +except ImportError: + CRYPTOGRAPHY_AVAILABLE = False + +if sys.version_info >= (3, 8): + from importlib import metadata +else: + import importlib_metadata as metadata + + +def from_url(url, **kwargs): + """ + Returns an active Redis client generated from the given database URL. + + Will attempt to extract the database id from the path url fragment, if + none is provided. + """ + from redis.client import Redis + + return Redis.from_url(url, **kwargs) + + +@contextmanager +def pipeline(redis_obj): + p = redis_obj.pipeline() + yield p + p.execute() + + +def str_if_bytes(value: Union[str, bytes]) -> str: + return ( + value.decode("utf-8", errors="replace") if isinstance(value, bytes) else value + ) + + +def safe_str(value): + return str(str_if_bytes(value)) + + +def dict_merge(*dicts: Mapping[str, Any]) -> Dict[str, Any]: + """ + Merge all provided dicts into 1 dict. + *dicts : `dict` + dictionaries to merge + """ + merged = {} + + for d in dicts: + merged.update(d) + + return merged + + +def list_keys_to_dict(key_list, callback): + return dict.fromkeys(key_list, callback) + + +def merge_result(command, res): + """ + Merge all items in `res` into a list. + + This command is used when sending a command to multiple nodes + and the result from each node should be merged into a single list. + + res : 'dict' + """ + result = set() + + for v in res.values(): + for value in v: + result.add(value) + + return list(result) + + +def warn_deprecated(name, reason="", version="", stacklevel=2): + import warnings + + msg = f"Call to deprecated {name}." + if reason: + msg += f" ({reason})" + if version: + msg += f" -- Deprecated since version {version}." + warnings.warn(msg, category=DeprecationWarning, stacklevel=stacklevel) + + +def deprecated_function(reason="", version="", name=None): + """ + Decorator to mark a function as deprecated. + """ + + def decorator(func): + @wraps(func) + def wrapper(*args, **kwargs): + warn_deprecated(name or func.__name__, reason, version, stacklevel=3) + return func(*args, **kwargs) + + return wrapper + + return decorator + + +def _set_info_logger(): + """ + Set up a logger that log info logs to stdout. + (This is used by the default push response handler) + """ + if "push_response" not in logging.root.manager.loggerDict.keys(): + logger = logging.getLogger("push_response") + logger.setLevel(logging.INFO) + handler = logging.StreamHandler() + handler.setLevel(logging.INFO) + logger.addHandler(handler) + + +def get_lib_version(): + try: + libver = metadata.version("redis") + except metadata.PackageNotFoundError: + libver = "99.99.99" + return libver diff --git a/.venv/Lib/site-packages/six-1.16.0.dist-info/INSTALLER b/.venv/Lib/site-packages/six-1.16.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/.venv/Lib/site-packages/six-1.16.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/Lib/site-packages/six-1.16.0.dist-info/LICENSE b/.venv/Lib/site-packages/six-1.16.0.dist-info/LICENSE new file mode 100644 index 00000000..de663311 --- /dev/null +++ b/.venv/Lib/site-packages/six-1.16.0.dist-info/LICENSE @@ -0,0 +1,18 @@ +Copyright (c) 2010-2020 Benjamin Peterson + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/.venv/Lib/site-packages/six-1.16.0.dist-info/METADATA b/.venv/Lib/site-packages/six-1.16.0.dist-info/METADATA new file mode 100644 index 00000000..6d7525c2 --- /dev/null +++ b/.venv/Lib/site-packages/six-1.16.0.dist-info/METADATA @@ -0,0 +1,49 @@ +Metadata-Version: 2.1 +Name: six +Version: 1.16.0 +Summary: Python 2 and 3 compatibility utilities +Home-page: https://github.com/benjaminp/six +Author: Benjamin Peterson +Author-email: benjamin@python.org +License: MIT +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 3 +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Topic :: Software Development :: Libraries +Classifier: Topic :: Utilities +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.* + +.. image:: https://img.shields.io/pypi/v/six.svg + :target: https://pypi.org/project/six/ + :alt: six on PyPI + +.. image:: https://travis-ci.org/benjaminp/six.svg?branch=master + :target: https://travis-ci.org/benjaminp/six + :alt: six on TravisCI + +.. image:: https://readthedocs.org/projects/six/badge/?version=latest + :target: https://six.readthedocs.io/ + :alt: six's documentation on Read the Docs + +.. image:: https://img.shields.io/badge/license-MIT-green.svg + :target: https://github.com/benjaminp/six/blob/master/LICENSE + :alt: MIT License badge + +Six is a Python 2 and 3 compatibility library. It provides utility functions +for smoothing over the differences between the Python versions with the goal of +writing Python code that is compatible on both Python versions. See the +documentation for more information on what is provided. + +Six supports Python 2.7 and 3.3+. It is contained in only one Python +file, so it can be easily copied into your project. (The copyright and license +notice must be retained.) + +Online documentation is at https://six.readthedocs.io/. + +Bugs can be reported to https://github.com/benjaminp/six. The code can also +be found there. + + diff --git a/.venv/Lib/site-packages/six-1.16.0.dist-info/RECORD b/.venv/Lib/site-packages/six-1.16.0.dist-info/RECORD new file mode 100644 index 00000000..28b18f29 --- /dev/null +++ b/.venv/Lib/site-packages/six-1.16.0.dist-info/RECORD @@ -0,0 +1,8 @@ +__pycache__/six.cpython-311.pyc,, +six-1.16.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +six-1.16.0.dist-info/LICENSE,sha256=i7hQxWWqOJ_cFvOkaWWtI9gq3_YPI5P8J2K2MYXo5sk,1066 +six-1.16.0.dist-info/METADATA,sha256=VQcGIFCAEmfZcl77E5riPCN4v2TIsc_qtacnjxKHJoI,1795 +six-1.16.0.dist-info/RECORD,, +six-1.16.0.dist-info/WHEEL,sha256=Z-nyYpwrcSqxfdux5Mbn_DQ525iP7J2DG3JgGvOYyTQ,110 +six-1.16.0.dist-info/top_level.txt,sha256=_iVH_iYEtEXnD8nYGQYpYFUvkUW9sEO1GYbkeKSAais,4 +six.py,sha256=TOOfQi7nFGfMrIvtdr6wX4wyHH8M7aknmuLfo2cBBrM,34549 diff --git a/.venv/Lib/site-packages/six-1.16.0.dist-info/WHEEL b/.venv/Lib/site-packages/six-1.16.0.dist-info/WHEEL new file mode 100644 index 00000000..01b8fc7d --- /dev/null +++ b/.venv/Lib/site-packages/six-1.16.0.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.36.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/.venv/Lib/site-packages/six-1.16.0.dist-info/top_level.txt b/.venv/Lib/site-packages/six-1.16.0.dist-info/top_level.txt new file mode 100644 index 00000000..ffe2fce4 --- /dev/null +++ b/.venv/Lib/site-packages/six-1.16.0.dist-info/top_level.txt @@ -0,0 +1 @@ +six diff --git a/.venv/Lib/site-packages/six.py b/.venv/Lib/site-packages/six.py new file mode 100644 index 00000000..4e15675d --- /dev/null +++ b/.venv/Lib/site-packages/six.py @@ -0,0 +1,998 @@ +# Copyright (c) 2010-2020 Benjamin Peterson +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""Utilities for writing code that runs on Python 2 and 3""" + +from __future__ import absolute_import + +import functools +import itertools +import operator +import sys +import types + +__author__ = "Benjamin Peterson " +__version__ = "1.16.0" + + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 +PY34 = sys.version_info[0:2] >= (3, 4) + +if PY3: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + +if PY34: + from importlib.util import spec_from_loader +else: + spec_from_loader = None + + +def _add_doc(func, doc): + """Add documentation to a function.""" + func.__doc__ = doc + + +def _import_module(name): + """Import module, returning the module after the last dot.""" + __import__(name) + return sys.modules[name] + + +class _LazyDescr(object): + + def __init__(self, name): + self.name = name + + def __get__(self, obj, tp): + result = self._resolve() + setattr(obj, self.name, result) # Invokes __set__. + try: + # This is a bit ugly, but it avoids running this again by + # removing this descriptor. + delattr(obj.__class__, self.name) + except AttributeError: + pass + return result + + +class MovedModule(_LazyDescr): + + def __init__(self, name, old, new=None): + super(MovedModule, self).__init__(name) + if PY3: + if new is None: + new = name + self.mod = new + else: + self.mod = old + + def _resolve(self): + return _import_module(self.mod) + + def __getattr__(self, attr): + _module = self._resolve() + value = getattr(_module, attr) + setattr(self, attr, value) + return value + + +class _LazyModule(types.ModuleType): + + def __init__(self, name): + super(_LazyModule, self).__init__(name) + self.__doc__ = self.__class__.__doc__ + + def __dir__(self): + attrs = ["__doc__", "__name__"] + attrs += [attr.name for attr in self._moved_attributes] + return attrs + + # Subclasses should override this + _moved_attributes = [] + + +class MovedAttribute(_LazyDescr): + + def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): + super(MovedAttribute, self).__init__(name) + if PY3: + if new_mod is None: + new_mod = name + self.mod = new_mod + if new_attr is None: + if old_attr is None: + new_attr = name + else: + new_attr = old_attr + self.attr = new_attr + else: + self.mod = old_mod + if old_attr is None: + old_attr = name + self.attr = old_attr + + def _resolve(self): + module = _import_module(self.mod) + return getattr(module, self.attr) + + +class _SixMetaPathImporter(object): + + """ + A meta path importer to import six.moves and its submodules. + + This class implements a PEP302 finder and loader. It should be compatible + with Python 2.5 and all existing versions of Python3 + """ + + def __init__(self, six_module_name): + self.name = six_module_name + self.known_modules = {} + + def _add_module(self, mod, *fullnames): + for fullname in fullnames: + self.known_modules[self.name + "." + fullname] = mod + + def _get_module(self, fullname): + return self.known_modules[self.name + "." + fullname] + + def find_module(self, fullname, path=None): + if fullname in self.known_modules: + return self + return None + + def find_spec(self, fullname, path, target=None): + if fullname in self.known_modules: + return spec_from_loader(fullname, self) + return None + + def __get_module(self, fullname): + try: + return self.known_modules[fullname] + except KeyError: + raise ImportError("This loader does not know module " + fullname) + + def load_module(self, fullname): + try: + # in case of a reload + return sys.modules[fullname] + except KeyError: + pass + mod = self.__get_module(fullname) + if isinstance(mod, MovedModule): + mod = mod._resolve() + else: + mod.__loader__ = self + sys.modules[fullname] = mod + return mod + + def is_package(self, fullname): + """ + Return true, if the named module is a package. + + We need this method to get correct spec objects with + Python 3.4 (see PEP451) + """ + return hasattr(self.__get_module(fullname), "__path__") + + def get_code(self, fullname): + """Return None + + Required, if is_package is implemented""" + self.__get_module(fullname) # eventually raises ImportError + return None + get_source = get_code # same as get_code + + def create_module(self, spec): + return self.load_module(spec.name) + + def exec_module(self, module): + pass + +_importer = _SixMetaPathImporter(__name__) + + +class _MovedItems(_LazyModule): + + """Lazy loading of moved objects""" + __path__ = [] # mark as package + + +_moved_attributes = [ + MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), + MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("intern", "__builtin__", "sys"), + MovedAttribute("map", "itertools", "builtins", "imap", "map"), + MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), + MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), + MovedAttribute("getoutput", "commands", "subprocess"), + MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), + MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), + MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserDict", "UserDict", "collections"), + MovedAttribute("UserList", "UserList", "collections"), + MovedAttribute("UserString", "UserString", "collections"), + MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), + MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), + MovedModule("builtins", "__builtin__"), + MovedModule("configparser", "ConfigParser"), + MovedModule("collections_abc", "collections", "collections.abc" if sys.version_info >= (3, 3) else "collections"), + MovedModule("copyreg", "copy_reg"), + MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("dbm_ndbm", "dbm", "dbm.ndbm"), + MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread" if sys.version_info < (3, 9) else "_thread"), + MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), + MovedModule("http_cookies", "Cookie", "http.cookies"), + MovedModule("html_entities", "htmlentitydefs", "html.entities"), + MovedModule("html_parser", "HTMLParser", "html.parser"), + MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("email_mime_image", "email.MIMEImage", "email.mime.image"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), + MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), + MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), + MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), + MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), + MovedModule("cPickle", "cPickle", "pickle"), + MovedModule("queue", "Queue"), + MovedModule("reprlib", "repr"), + MovedModule("socketserver", "SocketServer"), + MovedModule("_thread", "thread", "_thread"), + MovedModule("tkinter", "Tkinter"), + MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), + MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), + MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), + MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), + MovedModule("tkinter_colorchooser", "tkColorChooser", + "tkinter.colorchooser"), + MovedModule("tkinter_commondialog", "tkCommonDialog", + "tkinter.commondialog"), + MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), + MovedModule("tkinter_font", "tkFont", "tkinter.font"), + MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), + MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", + "tkinter.simpledialog"), + MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), + MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), + MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), +] +# Add windows specific modules. +if sys.platform == "win32": + _moved_attributes += [ + MovedModule("winreg", "_winreg"), + ] + +for attr in _moved_attributes: + setattr(_MovedItems, attr.name, attr) + if isinstance(attr, MovedModule): + _importer._add_module(attr, "moves." + attr.name) +del attr + +_MovedItems._moved_attributes = _moved_attributes + +moves = _MovedItems(__name__ + ".moves") +_importer._add_module(moves, "moves") + + +class Module_six_moves_urllib_parse(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_parse""" + + +_urllib_parse_moved_attributes = [ + MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), + MovedAttribute("parse_qs", "urlparse", "urllib.parse"), + MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), + MovedAttribute("urldefrag", "urlparse", "urllib.parse"), + MovedAttribute("urljoin", "urlparse", "urllib.parse"), + MovedAttribute("urlparse", "urlparse", "urllib.parse"), + MovedAttribute("urlsplit", "urlparse", "urllib.parse"), + MovedAttribute("urlunparse", "urlparse", "urllib.parse"), + MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), + MovedAttribute("quote", "urllib", "urllib.parse"), + MovedAttribute("quote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote", "urllib", "urllib.parse"), + MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote_to_bytes", "urllib", "urllib.parse", "unquote", "unquote_to_bytes"), + MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), + MovedAttribute("splittag", "urllib", "urllib.parse"), + MovedAttribute("splituser", "urllib", "urllib.parse"), + MovedAttribute("splitvalue", "urllib", "urllib.parse"), + MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), + MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), + MovedAttribute("uses_params", "urlparse", "urllib.parse"), + MovedAttribute("uses_query", "urlparse", "urllib.parse"), + MovedAttribute("uses_relative", "urlparse", "urllib.parse"), +] +for attr in _urllib_parse_moved_attributes: + setattr(Module_six_moves_urllib_parse, attr.name, attr) +del attr + +Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes + +_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), + "moves.urllib_parse", "moves.urllib.parse") + + +class Module_six_moves_urllib_error(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_error""" + + +_urllib_error_moved_attributes = [ + MovedAttribute("URLError", "urllib2", "urllib.error"), + MovedAttribute("HTTPError", "urllib2", "urllib.error"), + MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), +] +for attr in _urllib_error_moved_attributes: + setattr(Module_six_moves_urllib_error, attr.name, attr) +del attr + +Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes + +_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), + "moves.urllib_error", "moves.urllib.error") + + +class Module_six_moves_urllib_request(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_request""" + + +_urllib_request_moved_attributes = [ + MovedAttribute("urlopen", "urllib2", "urllib.request"), + MovedAttribute("install_opener", "urllib2", "urllib.request"), + MovedAttribute("build_opener", "urllib2", "urllib.request"), + MovedAttribute("pathname2url", "urllib", "urllib.request"), + MovedAttribute("url2pathname", "urllib", "urllib.request"), + MovedAttribute("getproxies", "urllib", "urllib.request"), + MovedAttribute("Request", "urllib2", "urllib.request"), + MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), + MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), + MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), + MovedAttribute("BaseHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), + MovedAttribute("FileHandler", "urllib2", "urllib.request"), + MovedAttribute("FTPHandler", "urllib2", "urllib.request"), + MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), + MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), + MovedAttribute("urlretrieve", "urllib", "urllib.request"), + MovedAttribute("urlcleanup", "urllib", "urllib.request"), + MovedAttribute("URLopener", "urllib", "urllib.request"), + MovedAttribute("FancyURLopener", "urllib", "urllib.request"), + MovedAttribute("proxy_bypass", "urllib", "urllib.request"), + MovedAttribute("parse_http_list", "urllib2", "urllib.request"), + MovedAttribute("parse_keqv_list", "urllib2", "urllib.request"), +] +for attr in _urllib_request_moved_attributes: + setattr(Module_six_moves_urllib_request, attr.name, attr) +del attr + +Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes + +_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), + "moves.urllib_request", "moves.urllib.request") + + +class Module_six_moves_urllib_response(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_response""" + + +_urllib_response_moved_attributes = [ + MovedAttribute("addbase", "urllib", "urllib.response"), + MovedAttribute("addclosehook", "urllib", "urllib.response"), + MovedAttribute("addinfo", "urllib", "urllib.response"), + MovedAttribute("addinfourl", "urllib", "urllib.response"), +] +for attr in _urllib_response_moved_attributes: + setattr(Module_six_moves_urllib_response, attr.name, attr) +del attr + +Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes + +_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), + "moves.urllib_response", "moves.urllib.response") + + +class Module_six_moves_urllib_robotparser(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_robotparser""" + + +_urllib_robotparser_moved_attributes = [ + MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), +] +for attr in _urllib_robotparser_moved_attributes: + setattr(Module_six_moves_urllib_robotparser, attr.name, attr) +del attr + +Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes + +_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), + "moves.urllib_robotparser", "moves.urllib.robotparser") + + +class Module_six_moves_urllib(types.ModuleType): + + """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" + __path__ = [] # mark as package + parse = _importer._get_module("moves.urllib_parse") + error = _importer._get_module("moves.urllib_error") + request = _importer._get_module("moves.urllib_request") + response = _importer._get_module("moves.urllib_response") + robotparser = _importer._get_module("moves.urllib_robotparser") + + def __dir__(self): + return ['parse', 'error', 'request', 'response', 'robotparser'] + +_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), + "moves.urllib") + + +def add_move(move): + """Add an item to six.moves.""" + setattr(_MovedItems, move.name, move) + + +def remove_move(name): + """Remove item from six.moves.""" + try: + delattr(_MovedItems, name) + except AttributeError: + try: + del moves.__dict__[name] + except KeyError: + raise AttributeError("no such move, %r" % (name,)) + + +if PY3: + _meth_func = "__func__" + _meth_self = "__self__" + + _func_closure = "__closure__" + _func_code = "__code__" + _func_defaults = "__defaults__" + _func_globals = "__globals__" +else: + _meth_func = "im_func" + _meth_self = "im_self" + + _func_closure = "func_closure" + _func_code = "func_code" + _func_defaults = "func_defaults" + _func_globals = "func_globals" + + +try: + advance_iterator = next +except NameError: + def advance_iterator(it): + return it.next() +next = advance_iterator + + +try: + callable = callable +except NameError: + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) + + +if PY3: + def get_unbound_function(unbound): + return unbound + + create_bound_method = types.MethodType + + def create_unbound_method(func, cls): + return func + + Iterator = object +else: + def get_unbound_function(unbound): + return unbound.im_func + + def create_bound_method(func, obj): + return types.MethodType(func, obj, obj.__class__) + + def create_unbound_method(func, cls): + return types.MethodType(func, None, cls) + + class Iterator(object): + + def next(self): + return type(self).__next__(self) + + callable = callable +_add_doc(get_unbound_function, + """Get the function out of a possibly unbound function""") + + +get_method_function = operator.attrgetter(_meth_func) +get_method_self = operator.attrgetter(_meth_self) +get_function_closure = operator.attrgetter(_func_closure) +get_function_code = operator.attrgetter(_func_code) +get_function_defaults = operator.attrgetter(_func_defaults) +get_function_globals = operator.attrgetter(_func_globals) + + +if PY3: + def iterkeys(d, **kw): + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + return iter(d.values(**kw)) + + def iteritems(d, **kw): + return iter(d.items(**kw)) + + def iterlists(d, **kw): + return iter(d.lists(**kw)) + + viewkeys = operator.methodcaller("keys") + + viewvalues = operator.methodcaller("values") + + viewitems = operator.methodcaller("items") +else: + def iterkeys(d, **kw): + return d.iterkeys(**kw) + + def itervalues(d, **kw): + return d.itervalues(**kw) + + def iteritems(d, **kw): + return d.iteritems(**kw) + + def iterlists(d, **kw): + return d.iterlists(**kw) + + viewkeys = operator.methodcaller("viewkeys") + + viewvalues = operator.methodcaller("viewvalues") + + viewitems = operator.methodcaller("viewitems") + +_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") +_add_doc(itervalues, "Return an iterator over the values of a dictionary.") +_add_doc(iteritems, + "Return an iterator over the (key, value) pairs of a dictionary.") +_add_doc(iterlists, + "Return an iterator over the (key, [values]) pairs of a dictionary.") + + +if PY3: + def b(s): + return s.encode("latin-1") + + def u(s): + return s + unichr = chr + import struct + int2byte = struct.Struct(">B").pack + del struct + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter + import io + StringIO = io.StringIO + BytesIO = io.BytesIO + del io + _assertCountEqual = "assertCountEqual" + if sys.version_info[1] <= 1: + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + _assertNotRegex = "assertNotRegexpMatches" + else: + _assertRaisesRegex = "assertRaisesRegex" + _assertRegex = "assertRegex" + _assertNotRegex = "assertNotRegex" +else: + def b(s): + return s + # Workaround for standalone backslash + + def u(s): + return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") + unichr = unichr + int2byte = chr + + def byte2int(bs): + return ord(bs[0]) + + def indexbytes(buf, i): + return ord(buf[i]) + iterbytes = functools.partial(itertools.imap, ord) + import StringIO + StringIO = BytesIO = StringIO.StringIO + _assertCountEqual = "assertItemsEqual" + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + _assertNotRegex = "assertNotRegexpMatches" +_add_doc(b, """Byte literal""") +_add_doc(u, """Text literal""") + + +def assertCountEqual(self, *args, **kwargs): + return getattr(self, _assertCountEqual)(*args, **kwargs) + + +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + + +def assertRegex(self, *args, **kwargs): + return getattr(self, _assertRegex)(*args, **kwargs) + + +def assertNotRegex(self, *args, **kwargs): + return getattr(self, _assertNotRegex)(*args, **kwargs) + + +if PY3: + exec_ = getattr(moves.builtins, "exec") + + def reraise(tp, value, tb=None): + try: + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + finally: + value = None + tb = None + +else: + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") + + exec_("""def reraise(tp, value, tb=None): + try: + raise tp, value, tb + finally: + tb = None +""") + + +if sys.version_info[:2] > (3,): + exec_("""def raise_from(value, from_value): + try: + raise value from from_value + finally: + value = None +""") +else: + def raise_from(value, from_value): + raise value + + +print_ = getattr(moves.builtins, "print", None) +if print_ is None: + def print_(*args, **kwargs): + """The new-style print function for Python 2.4 and 2.5.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + + def write(data): + if not isinstance(data, basestring): + data = str(data) + # If the file has an encoding, encode unicode with it. + if (isinstance(fp, file) and + isinstance(data, unicode) and + fp.encoding is not None): + errors = getattr(fp, "errors", None) + if errors is None: + errors = "strict" + data = data.encode(fp.encoding, errors) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) +if sys.version_info[:2] < (3, 3): + _print = print_ + + def print_(*args, **kwargs): + fp = kwargs.get("file", sys.stdout) + flush = kwargs.pop("flush", False) + _print(*args, **kwargs) + if flush and fp is not None: + fp.flush() + +_add_doc(reraise, """Reraise an exception.""") + +if sys.version_info[0:2] < (3, 4): + # This does exactly the same what the :func:`py3:functools.update_wrapper` + # function does on Python versions after 3.2. It sets the ``__wrapped__`` + # attribute on ``wrapper`` object and it doesn't raise an error if any of + # the attributes mentioned in ``assigned`` and ``updated`` are missing on + # ``wrapped`` object. + def _update_wrapper(wrapper, wrapped, + assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + for attr in assigned: + try: + value = getattr(wrapped, attr) + except AttributeError: + continue + else: + setattr(wrapper, attr, value) + for attr in updated: + getattr(wrapper, attr).update(getattr(wrapped, attr, {})) + wrapper.__wrapped__ = wrapped + return wrapper + _update_wrapper.__doc__ = functools.update_wrapper.__doc__ + + def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + return functools.partial(_update_wrapper, wrapped=wrapped, + assigned=assigned, updated=updated) + wraps.__doc__ = functools.wraps.__doc__ + +else: + wraps = functools.wraps + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(type): + + def __new__(cls, name, this_bases, d): + if sys.version_info[:2] >= (3, 7): + # This version introduced PEP 560 that requires a bit + # of extra care (we mimic what is done by __build_class__). + resolved_bases = types.resolve_bases(bases) + if resolved_bases is not bases: + d['__orig_bases__'] = bases + else: + resolved_bases = bases + return meta(name, resolved_bases, d) + + @classmethod + def __prepare__(cls, name, this_bases): + return meta.__prepare__(name, bases) + return type.__new__(metaclass, 'temporary_class', (), {}) + + +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + if hasattr(cls, '__qualname__'): + orig_vars['__qualname__'] = cls.__qualname__ + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper + + +def ensure_binary(s, encoding='utf-8', errors='strict'): + """Coerce **s** to six.binary_type. + + For Python 2: + - `unicode` -> encoded to `str` + - `str` -> `str` + + For Python 3: + - `str` -> encoded to `bytes` + - `bytes` -> `bytes` + """ + if isinstance(s, binary_type): + return s + if isinstance(s, text_type): + return s.encode(encoding, errors) + raise TypeError("not expecting type '%s'" % type(s)) + + +def ensure_str(s, encoding='utf-8', errors='strict'): + """Coerce *s* to `str`. + + For Python 2: + - `unicode` -> encoded to `str` + - `str` -> `str` + + For Python 3: + - `str` -> `str` + - `bytes` -> decoded to `str` + """ + # Optimization: Fast return for the common case. + if type(s) is str: + return s + if PY2 and isinstance(s, text_type): + return s.encode(encoding, errors) + elif PY3 and isinstance(s, binary_type): + return s.decode(encoding, errors) + elif not isinstance(s, (text_type, binary_type)): + raise TypeError("not expecting type '%s'" % type(s)) + return s + + +def ensure_text(s, encoding='utf-8', errors='strict'): + """Coerce *s* to six.text_type. + + For Python 2: + - `unicode` -> `unicode` + - `str` -> `unicode` + + For Python 3: + - `str` -> `str` + - `bytes` -> decoded to `str` + """ + if isinstance(s, binary_type): + return s.decode(encoding, errors) + elif isinstance(s, text_type): + return s + else: + raise TypeError("not expecting type '%s'" % type(s)) + + +def python_2_unicode_compatible(klass): + """ + A class decorator that defines __unicode__ and __str__ methods under Python 2. + Under Python 3 it does nothing. + + To support Python 2 and 3 with a single code base, define a __str__ method + returning text and apply this decorator to the class. + """ + if PY2: + if '__str__' not in klass.__dict__: + raise ValueError("@python_2_unicode_compatible cannot be applied " + "to %s because it doesn't define __str__()." % + klass.__name__) + klass.__unicode__ = klass.__str__ + klass.__str__ = lambda self: self.__unicode__().encode('utf-8') + return klass + + +# Complete the moves implementation. +# This code is at the end of this module to speed up module loading. +# Turn this module into a package. +__path__ = [] # required for PEP 302 and PEP 451 +__package__ = __name__ # see PEP 366 @ReservedAssignment +if globals().get("__spec__") is not None: + __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable +# Remove other six meta path importers, since they cause problems. This can +# happen if six is removed from sys.modules and then reloaded. (Setuptools does +# this for some reason.) +if sys.meta_path: + for i, importer in enumerate(sys.meta_path): + # Here's some real nastiness: Another "instance" of the six module might + # be floating around. Therefore, we can't use isinstance() to check for + # the six meta path importer, since the other six instance will have + # inserted an importer with different class. + if (type(importer).__name__ == "_SixMetaPathImporter" and + importer.name == __name__): + del sys.meta_path[i] + break + del i, importer +# Finally, add the importer to the meta path import hook. +sys.meta_path.append(_importer) diff --git a/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/INSTALLER b/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/LICENSE.md b/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/LICENSE.md new file mode 100644 index 00000000..f121286c --- /dev/null +++ b/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Paul Lamere + +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/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/METADATA b/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/METADATA new file mode 100644 index 00000000..beeb19c0 --- /dev/null +++ b/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/METADATA @@ -0,0 +1,100 @@ +Metadata-Version: 2.1 +Name: spotipy +Version: 2.23.0 +Summary: A light weight Python library for the Spotify Web API +Home-page: https://spotipy.readthedocs.org/ +Author: @plamere +Author-email: paul@echonest.com +License: MIT +Project-URL: Source, https://github.com/plamere/spotipy +Description-Content-Type: text/markdown +License-File: LICENSE.md +Requires-Dist: redis (>=3.5.3) +Requires-Dist: requests (>=2.25.0) +Requires-Dist: six (>=1.15.0) +Requires-Dist: urllib3 (>=1.26.0) +Requires-Dist: redis (<4.0.0) ; python_version < "3.4" +Provides-Extra: doc +Requires-Dist: Sphinx (>=1.5.2) ; extra == 'doc' +Provides-Extra: test +Requires-Dist: mock (==2.0.0) ; extra == 'test' + +# Spotipy + +##### A light weight Python library for the Spotify Web API + +![Tests](https://github.com/plamere/spotipy/workflows/Tests/badge.svg?branch=master) [![Documentation Status](https://readthedocs.org/projects/spotipy/badge/?version=latest)](https://spotipy.readthedocs.io/en/latest/?badge=latest) + +## Documentation + +Spotipy's full documentation is online at [Spotipy Documentation](http://spotipy.readthedocs.org/). + +## Installation + +```bash +pip install spotipy +``` + +alternatively, for Windows users + +```bash +py -m pip install spotipy +``` + +or upgrade + +```bash +pip install spotipy --upgrade +``` + +## Quick Start + +A full set of examples can be found in the [online documentation](http://spotipy.readthedocs.org/) and in the [Spotipy examples directory](https://github.com/plamere/spotipy/tree/master/examples). + +To get started, install spotipy and create an app on https://developers.spotify.com/. +Add your new ID and SECRET to your environment: + +### Without user authentication + +```python +import spotipy +from spotipy.oauth2 import SpotifyClientCredentials + +sp = spotipy.Spotify(auth_manager=SpotifyClientCredentials(client_id="YOUR_APP_CLIENT_ID", + client_secret="YOUR_APP_CLIENT_SECRET")) + +results = sp.search(q='weezer', limit=20) +for idx, track in enumerate(results['tracks']['items']): + print(idx, track['name']) +``` + +### With user authentication + +A redirect URI must be added to your application at [My Dashboard](https://developer.spotify.com/dashboard/applications) to access user authenticated features. + +```python +import spotipy +from spotipy.oauth2 import SpotifyOAuth + +sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id="YOUR_APP_CLIENT_ID", + client_secret="YOUR_APP_CLIENT_SECRET", + redirect_uri="YOUR_APP_REDIRECT_URI", + scope="user-library-read")) + +results = sp.current_user_saved_tracks() +for idx, item in enumerate(results['items']): + track = item['track'] + print(idx, track['artists'][0]['name'], " – ", track['name']) +``` + +## Reporting Issues + +For common questions please check our [FAQ](FAQ.md). + +You can ask questions about Spotipy on +[Stack Overflow](http://stackoverflow.com/questions/ask). +Don’t forget to add the *Spotipy* tag, and any other relevant tags as well, before posting. + +If you have suggestions, bugs or other issues specific to this library, +file them [here](https://github.com/plamere/spotipy/issues). +Or just send a pull request. diff --git a/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/RECORD b/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/RECORD new file mode 100644 index 00000000..2802103a --- /dev/null +++ b/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/RECORD @@ -0,0 +1,19 @@ +spotipy-2.23.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +spotipy-2.23.0.dist-info/LICENSE.md,sha256=tsEBFbMqRzu097t-Ecqy-G6uyDeOFEqFcrWtQuS3I_8,1068 +spotipy-2.23.0.dist-info/METADATA,sha256=I0-D4pcOm-EPF5NayigGceAVQ-Jrz4z47H4YatDSq8s,3253 +spotipy-2.23.0.dist-info/RECORD,, +spotipy-2.23.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +spotipy-2.23.0.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92 +spotipy-2.23.0.dist-info/top_level.txt,sha256=dSwjjk5rAZzv_g4EkBg7OkAUjW6k02wB8jjA29BrSa0,8 +spotipy/__init__.py,sha256=6DLF5dHdanFTLYpi1yrQKlC44FgLiTTa-hycEQ53ZFw,159 +spotipy/__pycache__/__init__.cpython-311.pyc,, +spotipy/__pycache__/cache_handler.cpython-311.pyc,, +spotipy/__pycache__/client.cpython-311.pyc,, +spotipy/__pycache__/exceptions.cpython-311.pyc,, +spotipy/__pycache__/oauth2.cpython-311.pyc,, +spotipy/__pycache__/util.cpython-311.pyc,, +spotipy/cache_handler.py,sha256=1PA6rG_MApoNr-KlDQU_WSB1CYEX5W-tKViQF6K30vs,6181 +spotipy/client.py,sha256=Eqsyi1o49YbxI_QU5kpZte52JA8HTX_m2AziIj4jPaI,75075 +spotipy/exceptions.py,sha256=s4lt7yTc8PeAiJGnShH7nu7HKXKGVnRouRaHT51Xo4w,568 +spotipy/oauth2.py,sha256=rXWNs77R5u8oLSpZbigFsMctuQlfayEiA5I-8_7D0kU,53619 +spotipy/util.py,sha256=Cg8U74tNWsq3Lz_VOttp_qYvnGiVLXr6f8IPeoKA9-w,3996 diff --git a/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/REQUESTED b/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/REQUESTED new file mode 100644 index 00000000..e69de29b diff --git a/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/WHEEL b/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/WHEEL new file mode 100644 index 00000000..1f37c02f --- /dev/null +++ b/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.40.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/top_level.txt b/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/top_level.txt new file mode 100644 index 00000000..9dc31a22 --- /dev/null +++ b/.venv/Lib/site-packages/spotipy-2.23.0.dist-info/top_level.txt @@ -0,0 +1 @@ +spotipy diff --git a/.venv/Lib/site-packages/spotipy/__init__.py b/.venv/Lib/site-packages/spotipy/__init__.py new file mode 100644 index 00000000..7f3d8599 --- /dev/null +++ b/.venv/Lib/site-packages/spotipy/__init__.py @@ -0,0 +1,5 @@ +from .cache_handler import * # noqa +from .client import * # noqa +from .exceptions import * # noqa +from .oauth2 import * # noqa +from .util import * # noqa diff --git a/.venv/Lib/site-packages/spotipy/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/spotipy/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6c8fe9b6940ca687e86fa5d5c3c5f5b159257346 GIT binary patch literal 340 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/spotipy/__pycache__/exceptions.cpython-311.pyc b/.venv/Lib/site-packages/spotipy/__pycache__/exceptions.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c545f93e6fc6a0d2288517581c6feb07bdd5056a GIT binary patch literal 1134 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 JRt4PI|9|s>7LWh{ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/spotipy/__pycache__/util.cpython-311.pyc b/.venv/Lib/site-packages/spotipy/__pycache__/util.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e6dbeccfc561cb87ad543da205fb6b9bcb96f9d2 GIT binary patch literal 3847 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 ssY*Cr0hl^eNv0v1*(8y!CFeMtrack|artist|album|playlist|show|episode):(?P[0-9A-Za-z]+)|user:(?P[0-9A-Za-z]+):playlist:(?P[0-9A-Za-z]+))$' # noqa: E501 + + # Spotify URLs are defined at [1]. The assumption is made that they are all + # pointing to open.spotify.com, so a regex is used to parse them as well, + # instead of a more complex URL parsing function. + # + # [1] https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids + _regex_spotify_url = r'^(http[s]?:\/\/)?open.spotify.com\/(?Ptrack|artist|album|playlist|show|episode|user)\/(?P[0-9A-Za-z]+)(\?.*)?$' # noqa: E501 + + _regex_base62 = r'^[0-9A-Za-z]+$' + + def __init__( + self, + auth=None, + requests_session=True, + client_credentials_manager=None, + oauth_manager=None, + auth_manager=None, + proxies=None, + requests_timeout=5, + status_forcelist=None, + retries=max_retries, + status_retries=max_retries, + backoff_factor=0.3, + language=None, + ): + """ + Creates a Spotify API client. + + :param auth: An access token (optional) + :param requests_session: + A Requests session object or a truthy value to create one. + A falsy value disables sessions. + It should generally be a good idea to keep sessions enabled + for performance reasons (connection pooling). + :param client_credentials_manager: + SpotifyClientCredentials object + :param oauth_manager: + SpotifyOAuth object + :param auth_manager: + SpotifyOauth, SpotifyClientCredentials, + or SpotifyImplicitGrant object + :param proxies: + Definition of proxies (optional). + See Requests doc https://2.python-requests.org/en/master/user/advanced/#proxies + :param requests_timeout: + Tell Requests to stop waiting for a response after a given + number of seconds + :param status_forcelist: + Tell requests what type of status codes retries should occur on + :param retries: + Total number of retries to allow + :param status_retries: + Number of times to retry on bad status codes + :param backoff_factor: + A backoff factor to apply between attempts after the second try + See urllib3 https://urllib3.readthedocs.io/en/latest/reference/urllib3.util.html + :param language: + The language parameter advertises what language the user prefers to see. + See ISO-639-1 language code: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes + """ + self.prefix = "https://api.spotify.com/v1/" + self._auth = auth + self.client_credentials_manager = client_credentials_manager + self.oauth_manager = oauth_manager + self.auth_manager = auth_manager + self.proxies = proxies + self.requests_timeout = requests_timeout + self.status_forcelist = status_forcelist or self.default_retry_codes + self.backoff_factor = backoff_factor + self.retries = retries + self.status_retries = status_retries + self.language = language + + if isinstance(requests_session, requests.Session): + self._session = requests_session + else: + if requests_session: # Build a new session. + self._build_session() + else: # Use the Requests API module as a "session". + self._session = requests.api + + def set_auth(self, auth): + self._auth = auth + + @property + def auth_manager(self): + return self._auth_manager + + @auth_manager.setter + def auth_manager(self, auth_manager): + if auth_manager is not None: + self._auth_manager = auth_manager + else: + self._auth_manager = ( + self.client_credentials_manager or self.oauth_manager + ) + + def __del__(self): + """Make sure the connection (pool) gets closed""" + if isinstance(self._session, requests.Session): + self._session.close() + + def _build_session(self): + self._session = requests.Session() + retry = urllib3.Retry( + total=self.retries, + connect=None, + read=False, + allowed_methods=frozenset(['GET', 'POST', 'PUT', 'DELETE']), + status=self.status_retries, + backoff_factor=self.backoff_factor, + status_forcelist=self.status_forcelist) + + adapter = requests.adapters.HTTPAdapter(max_retries=retry) + self._session.mount('http://', adapter) + self._session.mount('https://', adapter) + + def _auth_headers(self): + if self._auth: + return {"Authorization": "Bearer {0}".format(self._auth)} + if not self.auth_manager: + return {} + try: + token = self.auth_manager.get_access_token(as_dict=False) + except TypeError: + token = self.auth_manager.get_access_token() + return {"Authorization": "Bearer {0}".format(token)} + + def _internal_call(self, method, url, payload, params): + args = dict(params=params) + if not url.startswith("http"): + url = self.prefix + url + headers = self._auth_headers() + + if "content_type" in args["params"]: + headers["Content-Type"] = args["params"]["content_type"] + del args["params"]["content_type"] + if payload: + args["data"] = payload + else: + headers["Content-Type"] = "application/json" + if payload: + args["data"] = json.dumps(payload) + + if self.language is not None: + headers["Accept-Language"] = self.language + + logger.debug('Sending %s to %s with Params: %s Headers: %s and Body: %r ', + method, url, args.get("params"), headers, args.get('data')) + + try: + response = self._session.request( + method, url, headers=headers, proxies=self.proxies, + timeout=self.requests_timeout, **args + ) + + response.raise_for_status() + results = response.json() + except requests.exceptions.HTTPError as http_error: + response = http_error.response + try: + json_response = response.json() + error = json_response.get("error", {}) + msg = error.get("message") + reason = error.get("reason") + except ValueError: + # if the response cannot be decoded into JSON (which raises a ValueError), + # then try to decode it into text + + # if we receive an empty string (which is falsy), then replace it with `None` + msg = response.text or None + reason = None + + logger.error( + 'HTTP Error for %s to %s with Params: %s returned %s due to %s', + method, url, args.get("params"), response.status_code, msg + ) + + raise SpotifyException( + response.status_code, + -1, + "%s:\n %s" % (response.url, msg), + reason=reason, + headers=response.headers, + ) + except requests.exceptions.RetryError as retry_error: + request = retry_error.request + logger.error('Max Retries reached') + try: + reason = retry_error.args[0].reason + except (IndexError, AttributeError): + reason = None + raise SpotifyException( + 429, + -1, + "%s:\n %s" % (request.path_url, "Max Retries"), + reason=reason + ) + except ValueError: + results = None + + logger.debug('RESULTS: %s', results) + return results + + def _get(self, url, args=None, payload=None, **kwargs): + if args: + kwargs.update(args) + + return self._internal_call("GET", url, payload, kwargs) + + def _post(self, url, args=None, payload=None, **kwargs): + if args: + kwargs.update(args) + return self._internal_call("POST", url, payload, kwargs) + + def _delete(self, url, args=None, payload=None, **kwargs): + if args: + kwargs.update(args) + return self._internal_call("DELETE", url, payload, kwargs) + + def _put(self, url, args=None, payload=None, **kwargs): + if args: + kwargs.update(args) + return self._internal_call("PUT", url, payload, kwargs) + + def next(self, result): + """ returns the next result given a paged result + + Parameters: + - result - a previously returned paged result + """ + if result["next"]: + return self._get(result["next"]) + else: + return None + + def previous(self, result): + """ returns the previous result given a paged result + + Parameters: + - result - a previously returned paged result + """ + if result["previous"]: + return self._get(result["previous"]) + else: + return None + + def track(self, track_id, market=None): + """ returns a single track given the track's ID, URI or URL + + Parameters: + - track_id - a spotify URI, URL or ID + - market - an ISO 3166-1 alpha-2 country code. + """ + + trid = self._get_id("track", track_id) + return self._get("tracks/" + trid, market=market) + + def tracks(self, tracks, market=None): + """ returns a list of tracks given a list of track IDs, URIs, or URLs + + Parameters: + - tracks - a list of spotify URIs, URLs or IDs. Maximum: 50 IDs. + - market - an ISO 3166-1 alpha-2 country code. + """ + + tlist = [self._get_id("track", t) for t in tracks] + return self._get("tracks/?ids=" + ",".join(tlist), market=market) + + def artist(self, artist_id): + """ returns a single artist given the artist's ID, URI or URL + + Parameters: + - artist_id - an artist ID, URI or URL + """ + + trid = self._get_id("artist", artist_id) + return self._get("artists/" + trid) + + def artists(self, artists): + """ returns a list of artists given the artist IDs, URIs, or URLs + + Parameters: + - artists - a list of artist IDs, URIs or URLs + """ + + tlist = [self._get_id("artist", a) for a in artists] + return self._get("artists/?ids=" + ",".join(tlist)) + + def artist_albums( + self, artist_id, album_type=None, country=None, limit=20, offset=0 + ): + """ Get Spotify catalog information about an artist's albums + + Parameters: + - artist_id - the artist ID, URI or URL + - album_type - 'album', 'single', 'appears_on', 'compilation' + - country - limit the response to one particular country. + - limit - the number of albums to return + - offset - the index of the first album to return + """ + + trid = self._get_id("artist", artist_id) + return self._get( + "artists/" + trid + "/albums", + album_type=album_type, + country=country, + limit=limit, + offset=offset, + ) + + def artist_top_tracks(self, artist_id, country="US"): + """ Get Spotify catalog information about an artist's top 10 tracks + by country. + + Parameters: + - artist_id - the artist ID, URI or URL + - country - limit the response to one particular country. + """ + + trid = self._get_id("artist", artist_id) + return self._get("artists/" + trid + "/top-tracks", country=country) + + def artist_related_artists(self, artist_id): + """ Get Spotify catalog information about artists similar to an + identified artist. Similarity is based on analysis of the + Spotify community's listening history. + + Parameters: + - artist_id - the artist ID, URI or URL + """ + trid = self._get_id("artist", artist_id) + return self._get("artists/" + trid + "/related-artists") + + def album(self, album_id, market=None): + """ returns a single album given the album's ID, URIs or URL + + Parameters: + - album_id - the album ID, URI or URL + - market - an ISO 3166-1 alpha-2 country code + """ + + trid = self._get_id("album", album_id) + if market is not None: + return self._get("albums/" + trid + '?market=' + market) + else: + return self._get("albums/" + trid) + + def album_tracks(self, album_id, limit=50, offset=0, market=None): + """ Get Spotify catalog information about an album's tracks + + Parameters: + - album_id - the album ID, URI or URL + - limit - the number of items to return + - offset - the index of the first item to return + - market - an ISO 3166-1 alpha-2 country code. + + """ + + trid = self._get_id("album", album_id) + return self._get( + "albums/" + trid + "/tracks/", limit=limit, offset=offset, market=market + ) + + def albums(self, albums, market=None): + """ returns a list of albums given the album IDs, URIs, or URLs + + Parameters: + - albums - a list of album IDs, URIs or URLs + - market - an ISO 3166-1 alpha-2 country code + """ + + tlist = [self._get_id("album", a) for a in albums] + if market is not None: + return self._get("albums/?ids=" + ",".join(tlist) + '&market=' + market) + else: + return self._get("albums/?ids=" + ",".join(tlist)) + + def show(self, show_id, market=None): + """ returns a single show given the show's ID, URIs or URL + + Parameters: + - show_id - the show ID, URI or URL + - market - an ISO 3166-1 alpha-2 country code. + The show must be available in the given market. + If user-based authorization is in use, the user's country + takes precedence. If neither market nor user country are + provided, the content is considered unavailable for the client. + """ + + trid = self._get_id("show", show_id) + return self._get("shows/" + trid, market=market) + + def shows(self, shows, market=None): + """ returns a list of shows given the show IDs, URIs, or URLs + + Parameters: + - shows - a list of show IDs, URIs or URLs + - market - an ISO 3166-1 alpha-2 country code. + Only shows available in the given market will be returned. + If user-based authorization is in use, the user's country + takes precedence. If neither market nor user country are + provided, the content is considered unavailable for the client. + """ + + tlist = [self._get_id("show", s) for s in shows] + return self._get("shows/?ids=" + ",".join(tlist), market=market) + + def show_episodes(self, show_id, limit=50, offset=0, market=None): + """ Get Spotify catalog information about a show's episodes + + Parameters: + - show_id - the show ID, URI or URL + - limit - the number of items to return + - offset - the index of the first item to return + - market - an ISO 3166-1 alpha-2 country code. + Only episodes available in the given market will be returned. + If user-based authorization is in use, the user's country + takes precedence. If neither market nor user country are + provided, the content is considered unavailable for the client. + """ + + trid = self._get_id("show", show_id) + return self._get( + "shows/" + trid + "/episodes/", limit=limit, offset=offset, market=market + ) + + def episode(self, episode_id, market=None): + """ returns a single episode given the episode's ID, URIs or URL + + Parameters: + - episode_id - the episode ID, URI or URL + - market - an ISO 3166-1 alpha-2 country code. + The episode must be available in the given market. + If user-based authorization is in use, the user's country + takes precedence. If neither market nor user country are + provided, the content is considered unavailable for the client. + """ + + trid = self._get_id("episode", episode_id) + return self._get("episodes/" + trid, market=market) + + def episodes(self, episodes, market=None): + """ returns a list of episodes given the episode IDs, URIs, or URLs + + Parameters: + - episodes - a list of episode IDs, URIs or URLs + - market - an ISO 3166-1 alpha-2 country code. + Only episodes available in the given market will be returned. + If user-based authorization is in use, the user's country + takes precedence. If neither market nor user country are + provided, the content is considered unavailable for the client. + """ + + tlist = [self._get_id("episode", e) for e in episodes] + return self._get("episodes/?ids=" + ",".join(tlist), market=market) + + def search(self, q, limit=10, offset=0, type="track", market=None): + """ searches for an item + + Parameters: + - q - the search query (see how to write a query in the + official documentation https://developer.spotify.com/documentation/web-api/reference/search/) # noqa + - limit - the number of items to return (min = 1, default = 10, max = 50). The limit is applied + within each type, not on the total response. + - offset - the index of the first item to return + - type - the types of items to return. One or more of 'artist', 'album', + 'track', 'playlist', 'show', and 'episode'. If multiple types are desired, + pass in a comma separated string; e.g., 'track,album,episode'. + - market - An ISO 3166-1 alpha-2 country code or the string + from_token. + """ + return self._get( + "search", q=q, limit=limit, offset=offset, type=type, market=market + ) + + def search_markets(self, q, limit=10, offset=0, type="track", markets=None, total=None): + """ (experimental) Searches multiple markets for an item + + Parameters: + - q - the search query (see how to write a query in the + official documentation https://developer.spotify.com/documentation/web-api/reference/search/) # noqa + - limit - the number of items to return (min = 1, default = 10, max = 50). If a search is to be done on multiple + markets, then this limit is applied to each market. (e.g. search US, CA, MX each with a limit of 10). + If multiple types are specified, this applies to each type. + - offset - the index of the first item to return + - type - the types of items to return. One or more of 'artist', 'album', + 'track', 'playlist', 'show', or 'episode'. If multiple types are desired, pass in a comma separated string. + - markets - A list of ISO 3166-1 alpha-2 country codes. Search all country markets by default. + - total - the total number of results to return across multiple markets and types. + """ + warnings.warn( + "Searching multiple markets is an experimental feature. " + "Please be aware that this method's inputs and outputs can change in the future.", + UserWarning, + ) + if not markets: + markets = self.country_codes + + if not (isinstance(markets, list) or isinstance(markets, tuple)): + markets = [] + + warnings.warn( + "Searching multiple markets is poorly performing.", + UserWarning, + ) + return self._search_multiple_markets(q, limit, offset, type, markets, total) + + def user(self, user): + """ Gets basic profile information about a Spotify User + + Parameters: + - user - the id of the usr + """ + return self._get("users/" + user) + + def current_user_playlists(self, limit=50, offset=0): + """ Get current user playlists without required getting his profile + Parameters: + - limit - the number of items to return + - offset - the index of the first item to return + """ + return self._get("me/playlists", limit=limit, offset=offset) + + def playlist(self, playlist_id, fields=None, market=None, additional_types=("track",)): + """ Gets playlist by id. + + Parameters: + - playlist - the id of the playlist + - fields - which fields to return + - market - An ISO 3166-1 alpha-2 country code or the + string from_token. + - additional_types - list of item types to return. + valid types are: track and episode + """ + plid = self._get_id("playlist", playlist_id) + return self._get( + "playlists/%s" % (plid), + fields=fields, + market=market, + additional_types=",".join(additional_types), + ) + + def playlist_tracks( + self, + playlist_id, + fields=None, + limit=100, + offset=0, + market=None, + additional_types=("track",) + ): + """ Get full details of the tracks of a playlist. + + Parameters: + - playlist_id - the playlist ID, URI or URL + - fields - which fields to return + - limit - the maximum number of tracks to return + - offset - the index of the first track to return + - market - an ISO 3166-1 alpha-2 country code. + - additional_types - list of item types to return. + valid types are: track and episode + """ + warnings.warn( + "You should use `playlist_items(playlist_id, ...," + "additional_types=('track',))` instead", + DeprecationWarning, + ) + return self.playlist_items(playlist_id, fields, limit, offset, + market, additional_types) + + def playlist_items( + self, + playlist_id, + fields=None, + limit=100, + offset=0, + market=None, + additional_types=("track", "episode") + ): + """ Get full details of the tracks and episodes of a playlist. + + Parameters: + - playlist_id - the playlist ID, URI or URL + - fields - which fields to return + - limit - the maximum number of tracks to return + - offset - the index of the first track to return + - market - an ISO 3166-1 alpha-2 country code. + - additional_types - list of item types to return. + valid types are: track and episode + """ + plid = self._get_id("playlist", playlist_id) + return self._get( + "playlists/%s/tracks" % (plid), + limit=limit, + offset=offset, + fields=fields, + market=market, + additional_types=",".join(additional_types) + ) + + def playlist_cover_image(self, playlist_id): + """ Get cover image of a playlist. + + Parameters: + - playlist_id - the playlist ID, URI or URL + """ + plid = self._get_id("playlist", playlist_id) + return self._get("playlists/%s/images" % (plid)) + + def playlist_upload_cover_image(self, playlist_id, image_b64): + """ Replace the image used to represent a specific playlist + + Parameters: + - playlist_id - the id of the playlist + - image_b64 - image data as a Base64 encoded JPEG image string + (maximum payload size is 256 KB) + """ + plid = self._get_id("playlist", playlist_id) + return self._put( + "playlists/{}/images".format(plid), + payload=image_b64, + content_type="image/jpeg", + ) + + def user_playlist(self, user, playlist_id=None, fields=None, market=None): + warnings.warn( + "You should use `playlist(playlist_id)` instead", + DeprecationWarning, + ) + + """ Gets a single playlist of a user + + Parameters: + - user - the id of the user + - playlist_id - the id of the playlist + - fields - which fields to return + """ + if playlist_id is None: + return self._get("users/%s/starred" % user) + return self.playlist(playlist_id, fields=fields, market=market) + + def user_playlist_tracks( + self, + user=None, + playlist_id=None, + fields=None, + limit=100, + offset=0, + market=None, + ): + warnings.warn( + "You should use `playlist_tracks(playlist_id)` instead", + DeprecationWarning, + ) + + """ Get full details of the tracks of a playlist owned by a user. + + Parameters: + - user - the id of the user + - playlist_id - the id of the playlist + - fields - which fields to return + - limit - the maximum number of tracks to return + - offset - the index of the first track to return + - market - an ISO 3166-1 alpha-2 country code. + """ + return self.playlist_tracks( + playlist_id, + limit=limit, + offset=offset, + fields=fields, + market=market, + ) + + def user_playlists(self, user, limit=50, offset=0): + """ Gets playlists of a user + + Parameters: + - user - the id of the usr + - limit - the number of items to return + - offset - the index of the first item to return + """ + return self._get( + "users/%s/playlists" % user, limit=limit, offset=offset + ) + + def user_playlist_create(self, user, name, public=True, collaborative=False, description=""): + """ Creates a playlist for a user + + Parameters: + - user - the id of the user + - name - the name of the playlist + - public - is the created playlist public + - collaborative - is the created playlist collaborative + - description - the description of the playlist + """ + data = { + "name": name, + "public": public, + "collaborative": collaborative, + "description": description + } + + return self._post("users/%s/playlists" % (user,), payload=data) + + def user_playlist_change_details( + self, + user, + playlist_id, + name=None, + public=None, + collaborative=None, + description=None, + ): + warnings.warn( + "You should use `playlist_change_details(playlist_id, ...)` instead", + DeprecationWarning, + ) + """ Changes a playlist's name and/or public/private state + + Parameters: + - user - the id of the user + - playlist_id - the id of the playlist + - name - optional name of the playlist + - public - optional is the playlist public + - collaborative - optional is the playlist collaborative + - description - optional description of the playlist + """ + + return self.playlist_change_details(playlist_id, name, public, + collaborative, description) + + def user_playlist_unfollow(self, user, playlist_id): + """ Unfollows (deletes) a playlist for a user + + Parameters: + - user - the id of the user + - name - the name of the playlist + """ + warnings.warn( + "You should use `current_user_unfollow_playlist(playlist_id)` instead", + DeprecationWarning, + ) + return self.current_user_unfollow_playlist(playlist_id) + + def user_playlist_add_tracks( + self, user, playlist_id, tracks, position=None + ): + warnings.warn( + "You should use `playlist_add_items(playlist_id, tracks)` instead", + DeprecationWarning, + ) + """ Adds tracks to a playlist + + Parameters: + - user - the id of the user + - playlist_id - the id of the playlist + - tracks - a list of track URIs, URLs or IDs + - position - the position to add the tracks + """ + tracks = [self._get_uri("track", tid) for tid in tracks] + return self.playlist_add_items(playlist_id, tracks, position) + + def user_playlist_add_episodes( + self, user, playlist_id, episodes, position=None + ): + warnings.warn( + "You should use `playlist_add_items(playlist_id, episodes)` instead", + DeprecationWarning, + ) + """ Adds episodes to a playlist + + Parameters: + - user - the id of the user + - playlist_id - the id of the playlist + - episodes - a list of track URIs, URLs or IDs + - position - the position to add the episodes + """ + episodes = [self._get_uri("episode", tid) for tid in episodes] + return self.playlist_add_items(playlist_id, episodes, position) + + def user_playlist_replace_tracks(self, user, playlist_id, tracks): + """ Replace all tracks in a playlist for a user + + Parameters: + - user - the id of the user + - playlist_id - the id of the playlist + - tracks - the list of track ids to add to the playlist + """ + warnings.warn( + "You should use `playlist_replace_items(playlist_id, tracks)` instead", + DeprecationWarning, + ) + return self.playlist_replace_items(playlist_id, tracks) + + def user_playlist_reorder_tracks( + self, + user, + playlist_id, + range_start, + insert_before, + range_length=1, + snapshot_id=None, + ): + """ Reorder tracks in a playlist from a user + + Parameters: + - user - the id of the user + - playlist_id - the id of the playlist + - range_start - the position of the first track to be reordered + - range_length - optional the number of tracks to be reordered + (default: 1) + - insert_before - the position where the tracks should be + inserted + - snapshot_id - optional playlist's snapshot ID + """ + warnings.warn( + "You should use `playlist_reorder_items(playlist_id, ...)` instead", + DeprecationWarning, + ) + return self.playlist_reorder_items(playlist_id, range_start, + insert_before, range_length, + snapshot_id) + + def user_playlist_remove_all_occurrences_of_tracks( + self, user, playlist_id, tracks, snapshot_id=None + ): + """ Removes all occurrences of the given tracks from the given playlist + + Parameters: + - user - the id of the user + - playlist_id - the id of the playlist + - tracks - the list of track ids to remove from the playlist + - snapshot_id - optional id of the playlist snapshot + + """ + warnings.warn( + "You should use `playlist_remove_all_occurrences_of_items" + "(playlist_id, tracks)` instead", + DeprecationWarning, + ) + return self.playlist_remove_all_occurrences_of_items(playlist_id, + tracks, + snapshot_id) + + def user_playlist_remove_specific_occurrences_of_tracks( + self, user, playlist_id, tracks, snapshot_id=None + ): + """ Removes all occurrences of the given tracks from the given playlist + + Parameters: + - user - the id of the user + - playlist_id - the id of the playlist + - tracks - an array of objects containing Spotify URIs of the + tracks to remove with their current positions in the + playlist. For example: + [ { "uri":"4iV5W9uYEdYUVa79Axb7Rh", "positions":[2] }, + { "uri":"1301WleyT98MSxVHPZCA6M", "positions":[7] } ] + - snapshot_id - optional id of the playlist snapshot + """ + warnings.warn( + "You should use `playlist_remove_specific_occurrences_of_items" + "(playlist_id, tracks)` instead", + DeprecationWarning, + ) + plid = self._get_id("playlist", playlist_id) + ftracks = [] + for tr in tracks: + ftracks.append( + { + "uri": self._get_uri("track", tr["uri"]), + "positions": tr["positions"], + } + ) + payload = {"tracks": ftracks} + if snapshot_id: + payload["snapshot_id"] = snapshot_id + return self._delete( + "users/%s/playlists/%s/tracks" % (user, plid), payload=payload + ) + + def user_playlist_follow_playlist(self, playlist_owner_id, playlist_id): + """ + Add the current authenticated user as a follower of a playlist. + + Parameters: + - playlist_owner_id - the user id of the playlist owner + - playlist_id - the id of the playlist + + """ + warnings.warn( + "You should use `current_user_follow_playlist(playlist_id)` instead", + DeprecationWarning, + ) + return self.current_user_follow_playlist(playlist_id) + + def user_playlist_is_following( + self, playlist_owner_id, playlist_id, user_ids + ): + """ + Check to see if the given users are following the given playlist + + Parameters: + - playlist_owner_id - the user id of the playlist owner + - playlist_id - the id of the playlist + - user_ids - the ids of the users that you want to check to see + if they follow the playlist. Maximum: 5 ids. + + """ + warnings.warn( + "You should use `playlist_is_following(playlist_id, user_ids)` instead", + DeprecationWarning, + ) + return self.playlist_is_following(playlist_id, user_ids) + + def playlist_change_details( + self, + playlist_id, + name=None, + public=None, + collaborative=None, + description=None, + ): + """ Changes a playlist's name and/or public/private state, + collaborative state, and/or description + + Parameters: + - playlist_id - the id of the playlist + - name - optional name of the playlist + - public - optional is the playlist public + - collaborative - optional is the playlist collaborative + - description - optional description of the playlist + """ + + data = {} + if isinstance(name, six.string_types): + data["name"] = name + if isinstance(public, bool): + data["public"] = public + if isinstance(collaborative, bool): + data["collaborative"] = collaborative + if isinstance(description, six.string_types): + data["description"] = description + return self._put( + "playlists/%s" % (self._get_id("playlist", playlist_id)), payload=data + ) + + def current_user_unfollow_playlist(self, playlist_id): + """ Unfollows (deletes) a playlist for the current authenticated + user + + Parameters: + - name - the name of the playlist + """ + return self._delete( + "playlists/%s/followers" % (playlist_id) + ) + + def playlist_add_items( + self, playlist_id, items, position=None + ): + """ Adds tracks/episodes to a playlist + + Parameters: + - playlist_id - the id of the playlist + - items - a list of track/episode URIs or URLs + - position - the position to add the tracks + """ + plid = self._get_id("playlist", playlist_id) + ftracks = [self._get_uri("track", tid) for tid in items] + return self._post( + "playlists/%s/tracks" % (plid), + payload=ftracks, + position=position, + ) + + def playlist_replace_items(self, playlist_id, items): + """ Replace all tracks/episodes in a playlist + + Parameters: + - playlist_id - the id of the playlist + - items - list of track/episode ids to comprise playlist + """ + plid = self._get_id("playlist", playlist_id) + ftracks = [self._get_uri("track", tid) for tid in items] + payload = {"uris": ftracks} + return self._put( + "playlists/%s/tracks" % (plid), payload=payload + ) + + def playlist_reorder_items( + self, + playlist_id, + range_start, + insert_before, + range_length=1, + snapshot_id=None, + ): + """ Reorder tracks in a playlist + + Parameters: + - playlist_id - the id of the playlist + - range_start - the position of the first track to be reordered + - range_length - optional the number of tracks to be reordered + (default: 1) + - insert_before - the position where the tracks should be + inserted + - snapshot_id - optional playlist's snapshot ID + """ + plid = self._get_id("playlist", playlist_id) + payload = { + "range_start": range_start, + "range_length": range_length, + "insert_before": insert_before, + } + if snapshot_id: + payload["snapshot_id"] = snapshot_id + return self._put( + "playlists/%s/tracks" % (plid), payload=payload + ) + + def playlist_remove_all_occurrences_of_items( + self, playlist_id, items, snapshot_id=None + ): + """ Removes all occurrences of the given tracks/episodes from the given playlist + + Parameters: + - playlist_id - the id of the playlist + - items - list of track/episode ids to remove from the playlist + - snapshot_id - optional id of the playlist snapshot + + """ + + plid = self._get_id("playlist", playlist_id) + ftracks = [self._get_uri("track", tid) for tid in items] + payload = {"tracks": [{"uri": track} for track in ftracks]} + if snapshot_id: + payload["snapshot_id"] = snapshot_id + return self._delete( + "playlists/%s/tracks" % (plid), payload=payload + ) + + def playlist_remove_specific_occurrences_of_items( + self, playlist_id, items, snapshot_id=None + ): + """ Removes all occurrences of the given tracks from the given playlist + + Parameters: + - playlist_id - the id of the playlist + - items - an array of objects containing Spotify URIs of the + tracks/episodes to remove with their current positions in + the playlist. For example: + [ { "uri":"4iV5W9uYEdYUVa79Axb7Rh", "positions":[2] }, + { "uri":"1301WleyT98MSxVHPZCA6M", "positions":[7] } ] + - snapshot_id - optional id of the playlist snapshot + """ + + plid = self._get_id("playlist", playlist_id) + ftracks = [] + for tr in items: + ftracks.append( + { + "uri": self._get_uri("track", tr["uri"]), + "positions": tr["positions"], + } + ) + payload = {"tracks": ftracks} + if snapshot_id: + payload["snapshot_id"] = snapshot_id + return self._delete( + "playlists/%s/tracks" % (plid), payload=payload + ) + + def current_user_follow_playlist(self, playlist_id): + """ + Add the current authenticated user as a follower of a playlist. + + Parameters: + - playlist_id - the id of the playlist + + """ + return self._put( + "playlists/{}/followers".format(playlist_id) + ) + + def playlist_is_following( + self, playlist_id, user_ids + ): + """ + Check to see if the given users are following the given playlist + + Parameters: + - playlist_id - the id of the playlist + - user_ids - the ids of the users that you want to check to see + if they follow the playlist. Maximum: 5 ids. + + """ + endpoint = "playlists/{}/followers/contains?ids={}" + return self._get( + endpoint.format(playlist_id, ",".join(user_ids)) + ) + + def me(self): + """ Get detailed profile information about the current user. + An alias for the 'current_user' method. + """ + return self._get("me/") + + def current_user(self): + """ Get detailed profile information about the current user. + An alias for the 'me' method. + """ + return self.me() + + def current_user_playing_track(self): + """ Get information about the current users currently playing track. + """ + return self._get("me/player/currently-playing") + + def current_user_saved_albums(self, limit=20, offset=0, market=None): + """ Gets a list of the albums saved in the current authorized user's + "Your Music" library + + Parameters: + - limit - the number of albums to return (MAX_LIMIT=50) + - offset - the index of the first album to return + - market - an ISO 3166-1 alpha-2 country code. + + """ + return self._get("me/albums", limit=limit, offset=offset, market=market) + + def current_user_saved_albums_add(self, albums=[]): + """ Add one or more albums to the current user's + "Your Music" library. + Parameters: + - albums - a list of album URIs, URLs or IDs + """ + + alist = [self._get_id("album", a) for a in albums] + return self._put("me/albums?ids=" + ",".join(alist)) + + def current_user_saved_albums_delete(self, albums=[]): + """ Remove one or more albums from the current user's + "Your Music" library. + + Parameters: + - albums - a list of album URIs, URLs or IDs + """ + alist = [self._get_id("album", a) for a in albums] + return self._delete("me/albums/?ids=" + ",".join(alist)) + + def current_user_saved_albums_contains(self, albums=[]): + """ Check if one or more albums is already saved in + the current Spotify user’s “Your Music” library. + + Parameters: + - albums - a list of album URIs, URLs or IDs + """ + alist = [self._get_id("album", a) for a in albums] + return self._get("me/albums/contains?ids=" + ",".join(alist)) + + def current_user_saved_tracks(self, limit=20, offset=0, market=None): + """ Gets a list of the tracks saved in the current authorized user's + "Your Music" library + + Parameters: + - limit - the number of tracks to return + - offset - the index of the first track to return + - market - an ISO 3166-1 alpha-2 country code + + """ + return self._get("me/tracks", limit=limit, offset=offset, market=market) + + def current_user_saved_tracks_add(self, tracks=None): + """ Add one or more tracks to the current user's + "Your Music" library. + + Parameters: + - tracks - a list of track URIs, URLs or IDs + """ + tlist = [] + if tracks is not None: + tlist = [self._get_id("track", t) for t in tracks] + return self._put("me/tracks/?ids=" + ",".join(tlist)) + + def current_user_saved_tracks_delete(self, tracks=None): + """ Remove one or more tracks from the current user's + "Your Music" library. + + Parameters: + - tracks - a list of track URIs, URLs or IDs + """ + tlist = [] + if tracks is not None: + tlist = [self._get_id("track", t) for t in tracks] + return self._delete("me/tracks/?ids=" + ",".join(tlist)) + + def current_user_saved_tracks_contains(self, tracks=None): + """ Check if one or more tracks is already saved in + the current Spotify user’s “Your Music” library. + + Parameters: + - tracks - a list of track URIs, URLs or IDs + """ + tlist = [] + if tracks is not None: + tlist = [self._get_id("track", t) for t in tracks] + return self._get("me/tracks/contains?ids=" + ",".join(tlist)) + + def current_user_saved_episodes(self, limit=20, offset=0, market=None): + """ Gets a list of the episodes saved in the current authorized user's + "Your Music" library + + Parameters: + - limit - the number of episodes to return + - offset - the index of the first episode to return + - market - an ISO 3166-1 alpha-2 country code + + """ + return self._get("me/episodes", limit=limit, offset=offset, market=market) + + def current_user_saved_episodes_add(self, episodes=None): + """ Add one or more episodes to the current user's + "Your Music" library. + + Parameters: + - episodes - a list of episode URIs, URLs or IDs + """ + elist = [] + if episodes is not None: + elist = [self._get_id("episode", e) for e in episodes] + return self._put("me/episodes/?ids=" + ",".join(elist)) + + def current_user_saved_episodes_delete(self, episodes=None): + """ Remove one or more episodes from the current user's + "Your Music" library. + + Parameters: + - episodes - a list of episode URIs, URLs or IDs + """ + elist = [] + if episodes is not None: + elist = [self._get_id("episode", e) for e in episodes] + return self._delete("me/episodes/?ids=" + ",".join(elist)) + + def current_user_saved_episodes_contains(self, episodes=None): + """ Check if one or more episodes is already saved in + the current Spotify user’s “Your Music” library. + + Parameters: + - episodes - a list of episode URIs, URLs or IDs + """ + elist = [] + if episodes is not None: + elist = [self._get_id("episode", e) for e in episodes] + return self._get("me/episodes/contains?ids=" + ",".join(elist)) + + def current_user_saved_shows(self, limit=20, offset=0, market=None): + """ Gets a list of the shows saved in the current authorized user's + "Your Music" library + + Parameters: + - limit - the number of shows to return + - offset - the index of the first show to return + - market - an ISO 3166-1 alpha-2 country code + + """ + return self._get("me/shows", limit=limit, offset=offset, market=market) + + def current_user_saved_shows_add(self, shows=[]): + """ Add one or more albums to the current user's + "Your Music" library. + Parameters: + - shows - a list of show URIs, URLs or IDs + """ + slist = [self._get_id("show", s) for s in shows] + return self._put("me/shows?ids=" + ",".join(slist)) + + def current_user_saved_shows_delete(self, shows=[]): + """ Remove one or more shows from the current user's + "Your Music" library. + + Parameters: + - shows - a list of show URIs, URLs or IDs + """ + slist = [self._get_id("show", s) for s in shows] + return self._delete("me/shows/?ids=" + ",".join(slist)) + + def current_user_saved_shows_contains(self, shows=[]): + """ Check if one or more shows is already saved in + the current Spotify user’s “Your Music” library. + + Parameters: + - shows - a list of show URIs, URLs or IDs + """ + slist = [self._get_id("show", s) for s in shows] + return self._get("me/shows/contains?ids=" + ",".join(slist)) + + def current_user_followed_artists(self, limit=20, after=None): + """ Gets a list of the artists followed by the current authorized user + + Parameters: + - limit - the number of artists to return + - after - the last artist ID retrieved from the previous + request + + """ + return self._get( + "me/following", type="artist", limit=limit, after=after + ) + + def current_user_following_artists(self, ids=None): + """ Check if the current user is following certain artists + + Returns list of booleans respective to ids + + Parameters: + - ids - a list of artist URIs, URLs or IDs + """ + idlist = [] + if ids is not None: + idlist = [self._get_id("artist", i) for i in ids] + return self._get( + "me/following/contains", ids=",".join(idlist), type="artist" + ) + + def current_user_following_users(self, ids=None): + """ Check if the current user is following certain users + + Returns list of booleans respective to ids + + Parameters: + - ids - a list of user URIs, URLs or IDs + """ + idlist = [] + if ids is not None: + idlist = [self._get_id("user", i) for i in ids] + return self._get( + "me/following/contains", ids=",".join(idlist), type="user" + ) + + def current_user_top_artists( + self, limit=20, offset=0, time_range="medium_term" + ): + """ Get the current user's top artists + + Parameters: + - limit - the number of entities to return + - offset - the index of the first entity to return + - time_range - Over what time frame are the affinities computed + Valid-values: short_term, medium_term, long_term + """ + return self._get( + "me/top/artists", time_range=time_range, limit=limit, offset=offset + ) + + def current_user_top_tracks( + self, limit=20, offset=0, time_range="medium_term" + ): + """ Get the current user's top tracks + + Parameters: + - limit - the number of entities to return + - offset - the index of the first entity to return + - time_range - Over what time frame are the affinities computed + Valid-values: short_term, medium_term, long_term + """ + return self._get( + "me/top/tracks", time_range=time_range, limit=limit, offset=offset + ) + + def current_user_recently_played(self, limit=50, after=None, before=None): + """ Get the current user's recently played tracks + + Parameters: + - limit - the number of entities to return + - after - unix timestamp in milliseconds. Returns all items + after (but not including) this cursor position. + Cannot be used if before is specified. + - before - unix timestamp in milliseconds. Returns all items + before (but not including) this cursor position. + Cannot be used if after is specified + """ + return self._get( + "me/player/recently-played", + limit=limit, + after=after, + before=before, + ) + + def user_follow_artists(self, ids=[]): + """ Follow one or more artists + Parameters: + - ids - a list of artist IDs + """ + return self._put("me/following?type=artist&ids=" + ",".join(ids)) + + def user_follow_users(self, ids=[]): + """ Follow one or more users + Parameters: + - ids - a list of user IDs + """ + return self._put("me/following?type=user&ids=" + ",".join(ids)) + + def user_unfollow_artists(self, ids=[]): + """ Unfollow one or more artists + Parameters: + - ids - a list of artist IDs + """ + return self._delete("me/following?type=artist&ids=" + ",".join(ids)) + + def user_unfollow_users(self, ids=[]): + """ Unfollow one or more users + Parameters: + - ids - a list of user IDs + """ + return self._delete("me/following?type=user&ids=" + ",".join(ids)) + + def featured_playlists( + self, locale=None, country=None, timestamp=None, limit=20, offset=0 + ): + """ Get a list of Spotify featured playlists + + Parameters: + - locale - The desired language, consisting of a lowercase ISO + 639-1 alpha-2 language code and an uppercase ISO 3166-1 alpha-2 + country code, joined by an underscore. + + - country - An ISO 3166-1 alpha-2 country code. + + - timestamp - A timestamp in ISO 8601 format: + yyyy-MM-ddTHH:mm:ss. Use this parameter to specify the user's + local time to get results tailored for that specific date and + time in the day + + - limit - The maximum number of items to return. Default: 20. + Minimum: 1. Maximum: 50 + + - offset - The index of the first item to return. Default: 0 + (the first object). Use with limit to get the next set of + items. + """ + return self._get( + "browse/featured-playlists", + locale=locale, + country=country, + timestamp=timestamp, + limit=limit, + offset=offset, + ) + + def new_releases(self, country=None, limit=20, offset=0): + """ Get a list of new album releases featured in Spotify + + Parameters: + - country - An ISO 3166-1 alpha-2 country code. + + - limit - The maximum number of items to return. Default: 20. + Minimum: 1. Maximum: 50 + + - offset - The index of the first item to return. Default: 0 + (the first object). Use with limit to get the next set of + items. + """ + return self._get( + "browse/new-releases", country=country, limit=limit, offset=offset + ) + + def category(self, category_id, country=None, locale=None): + """ Get info about a category + + Parameters: + - category_id - The Spotify category ID for the category. + + - country - An ISO 3166-1 alpha-2 country code. + - locale - The desired language, consisting of an ISO 639-1 alpha-2 + language code and an ISO 3166-1 alpha-2 country code, joined + by an underscore. + """ + return self._get( + "browse/categories/" + category_id, + country=country, + locale=locale, + ) + + def categories(self, country=None, locale=None, limit=20, offset=0): + """ Get a list of categories + + Parameters: + - country - An ISO 3166-1 alpha-2 country code. + - locale - The desired language, consisting of an ISO 639-1 alpha-2 + language code and an ISO 3166-1 alpha-2 country code, joined + by an underscore. + + - limit - The maximum number of items to return. Default: 20. + Minimum: 1. Maximum: 50 + + - offset - The index of the first item to return. Default: 0 + (the first object). Use with limit to get the next set of + items. + """ + return self._get( + "browse/categories", + country=country, + locale=locale, + limit=limit, + offset=offset, + ) + + def category_playlists( + self, category_id=None, country=None, limit=20, offset=0 + ): + """ Get a list of playlists for a specific Spotify category + + Parameters: + - category_id - The Spotify category ID for the category. + + - country - An ISO 3166-1 alpha-2 country code. + + - limit - The maximum number of items to return. Default: 20. + Minimum: 1. Maximum: 50 + + - offset - The index of the first item to return. Default: 0 + (the first object). Use with limit to get the next set of + items. + """ + return self._get( + "browse/categories/" + category_id + "/playlists", + country=country, + limit=limit, + offset=offset, + ) + + def recommendations( + self, + seed_artists=None, + seed_genres=None, + seed_tracks=None, + limit=20, + country=None, + **kwargs + ): + """ Get a list of recommended tracks for one to five seeds. + (at least one of `seed_artists`, `seed_tracks` and `seed_genres` + are needed) + + Parameters: + - seed_artists - a list of artist IDs, URIs or URLs + - seed_tracks - a list of track IDs, URIs or URLs + - seed_genres - a list of genre names. Available genres for + recommendations can be found by calling + recommendation_genre_seeds + + - country - An ISO 3166-1 alpha-2 country code. If provided, + all results will be playable in this country. + + - limit - The maximum number of items to return. Default: 20. + Minimum: 1. Maximum: 100 + + - min/max/target_ - For the tuneable track + attributes listed in the documentation, these values + provide filters and targeting on results. + """ + params = dict(limit=limit) + if seed_artists: + params["seed_artists"] = ",".join( + [self._get_id("artist", a) for a in seed_artists] + ) + if seed_genres: + params["seed_genres"] = ",".join(seed_genres) + if seed_tracks: + params["seed_tracks"] = ",".join( + [self._get_id("track", t) for t in seed_tracks] + ) + if country: + params["market"] = country + + for attribute in [ + "acousticness", + "danceability", + "duration_ms", + "energy", + "instrumentalness", + "key", + "liveness", + "loudness", + "mode", + "popularity", + "speechiness", + "tempo", + "time_signature", + "valence", + ]: + for prefix in ["min_", "max_", "target_"]: + param = prefix + attribute + if param in kwargs: + params[param] = kwargs[param] + return self._get("recommendations", **params) + + def recommendation_genre_seeds(self): + """ Get a list of genres available for the recommendations function. + """ + return self._get("recommendations/available-genre-seeds") + + def audio_analysis(self, track_id): + """ Get audio analysis for a track based upon its Spotify ID + Parameters: + - track_id - a track URI, URL or ID + """ + trid = self._get_id("track", track_id) + return self._get("audio-analysis/" + trid) + + def audio_features(self, tracks=[]): + """ Get audio features for one or multiple tracks based upon their Spotify IDs + Parameters: + - tracks - a list of track URIs, URLs or IDs, maximum: 100 ids + """ + if isinstance(tracks, str): + trackid = self._get_id("track", tracks) + results = self._get("audio-features/?ids=" + trackid) + else: + tlist = [self._get_id("track", t) for t in tracks] + results = self._get("audio-features/?ids=" + ",".join(tlist)) + # the response has changed, look for the new style first, and if + # its not there, fallback on the old style + if "audio_features" in results: + return results["audio_features"] + else: + return results + + def devices(self): + """ Get a list of user's available devices. + """ + return self._get("me/player/devices") + + def current_playback(self, market=None, additional_types=None): + """ Get information about user's current playback. + + Parameters: + - market - an ISO 3166-1 alpha-2 country code. + - additional_types - `episode` to get podcast track information + """ + return self._get("me/player", market=market, additional_types=additional_types) + + def currently_playing(self, market=None, additional_types=None): + """ Get user's currently playing track. + + Parameters: + - market - an ISO 3166-1 alpha-2 country code. + - additional_types - `episode` to get podcast track information + """ + return self._get("me/player/currently-playing", market=market, + additional_types=additional_types) + + def transfer_playback(self, device_id, force_play=True): + """ Transfer playback to another device. + Note that the API accepts a list of device ids, but only + actually supports one. + + Parameters: + - device_id - transfer playback to this device + - force_play - true: after transfer, play. false: + keep current state. + """ + data = {"device_ids": [device_id], "play": force_play} + return self._put("me/player", payload=data) + + def start_playback( + self, device_id=None, context_uri=None, uris=None, offset=None, position_ms=None + ): + """ Start or resume user's playback. + + Provide a `context_uri` to start playback of an album, + artist, or playlist. + + Provide a `uris` list to start playback of one or more + tracks. + + Provide `offset` as {"position": } or {"uri": ""} + to start playback at a particular offset. + + Parameters: + - device_id - device target for playback + - context_uri - spotify context uri to play + - uris - spotify track uris + - offset - offset into context by index or track + - position_ms - (optional) indicates from what position to start playback. + Must be a positive number. Passing in a position that is + greater than the length of the track will cause the player to + start playing the next song. + """ + if context_uri is not None and uris is not None: + logger.warning("Specify either context uri or uris, not both") + return + if uris is not None and not isinstance(uris, list): + logger.warning("URIs must be a list") + return + data = {} + if context_uri is not None: + data["context_uri"] = context_uri + if uris is not None: + data["uris"] = uris + if offset is not None: + data["offset"] = offset + if position_ms is not None: + data["position_ms"] = position_ms + return self._put( + self._append_device_id("me/player/play", device_id), payload=data + ) + + def pause_playback(self, device_id=None): + """ Pause user's playback. + + Parameters: + - device_id - device target for playback + """ + return self._put(self._append_device_id("me/player/pause", device_id)) + + def next_track(self, device_id=None): + """ Skip user's playback to next track. + + Parameters: + - device_id - device target for playback + """ + return self._post(self._append_device_id("me/player/next", device_id)) + + def previous_track(self, device_id=None): + """ Skip user's playback to previous track. + + Parameters: + - device_id - device target for playback + """ + return self._post( + self._append_device_id("me/player/previous", device_id) + ) + + def seek_track(self, position_ms, device_id=None): + """ Seek to position in current track. + + Parameters: + - position_ms - position in milliseconds to seek to + - device_id - device target for playback + """ + if not isinstance(position_ms, int): + logger.warning("Position_ms must be an integer") + return + return self._put( + self._append_device_id( + "me/player/seek?position_ms=%s" % position_ms, device_id + ) + ) + + def repeat(self, state, device_id=None): + """ Set repeat mode for playback. + + Parameters: + - state - `track`, `context`, or `off` + - device_id - device target for playback + """ + if state not in ["track", "context", "off"]: + logger.warning("Invalid state") + return + self._put( + self._append_device_id( + "me/player/repeat?state=%s" % state, device_id + ) + ) + + def volume(self, volume_percent, device_id=None): + """ Set playback volume. + + Parameters: + - volume_percent - volume between 0 and 100 + - device_id - device target for playback + """ + if not isinstance(volume_percent, int): + logger.warning("Volume must be an integer") + return + if volume_percent < 0 or volume_percent > 100: + logger.warning("Volume must be between 0 and 100, inclusive") + return + self._put( + self._append_device_id( + "me/player/volume?volume_percent=%s" % volume_percent, + device_id, + ) + ) + + def shuffle(self, state, device_id=None): + """ Toggle playback shuffling. + + Parameters: + - state - true or false + - device_id - device target for playback + """ + if not isinstance(state, bool): + logger.warning("state must be a boolean") + return + state = str(state).lower() + self._put( + self._append_device_id( + "me/player/shuffle?state=%s" % state, device_id + ) + ) + + def queue(self): + """ Gets the current user's queue """ + return self._get("me/player/queue") + + def add_to_queue(self, uri, device_id=None): + """ Adds a song to the end of a user's queue + + If device A is currently playing music and you try to add to the queue + and pass in the id for device B, you will get a + 'Player command failed: Restriction violated' error + I therefore recommend leaving device_id as None so that the active device is targeted + + :param uri: song uri, id, or url + :param device_id: + the id of a Spotify device. + If None, then the active device is used. + + """ + + uri = self._get_uri("track", uri) + + endpoint = "me/player/queue?uri=%s" % uri + + if device_id is not None: + endpoint += "&device_id=%s" % device_id + + return self._post(endpoint) + + def available_markets(self): + """ Get the list of markets where Spotify is available. + Returns a list of the countries in which Spotify is available, identified by their + ISO 3166-1 alpha-2 country code with additional country codes for special territories. + """ + return self._get("markets") + + def _append_device_id(self, path, device_id): + """ Append device ID to API path. + + Parameters: + - device_id - device id to append + """ + if device_id: + if "?" in path: + path += "&device_id=%s" % device_id + else: + path += "?device_id=%s" % device_id + return path + + def _get_id(self, type, id): + uri_match = re.search(Spotify._regex_spotify_uri, id) + if uri_match is not None: + uri_match_groups = uri_match.groupdict() + if uri_match_groups['type'] != type: + # TODO change to a ValueError in v3 + raise SpotifyException(400, -1, "Unexpected Spotify URI type.") + return uri_match_groups['id'] + + url_match = re.search(Spotify._regex_spotify_url, id) + if url_match is not None: + url_match_groups = url_match.groupdict() + if url_match_groups['type'] != type: + raise SpotifyException(400, -1, "Unexpected Spotify URL type.") + # TODO change to a ValueError in v3 + return url_match_groups['id'] + + # Raw identifiers might be passed, ensure they are also base-62 + if re.search(Spotify._regex_base62, id) is not None: + return id + + # TODO change to a ValueError in v3 + raise SpotifyException(400, -1, "Unsupported URL / URI.") + + def _get_uri(self, type, id): + if self._is_uri(id): + return id + else: + return "spotify:" + type + ":" + self._get_id(type, id) + + def _is_uri(self, uri): + return re.search(Spotify._regex_spotify_uri, uri) is not None + + def _search_multiple_markets(self, q, limit, offset, type, markets, total): + if total and limit > total: + limit = total + warnings.warn( + "limit was auto-adjusted to equal {} as it must not be higher than total".format( + total), + UserWarning, + ) + + results = defaultdict(dict) + item_types = [item_type + "s" for item_type in type.split(",")] + count = 0 + + for country in markets: + result = self._get( + "search", q=q, limit=limit, offset=offset, type=type, market=country + ) + for item_type in item_types: + results[country][item_type] = result[item_type] + + # Truncate the items list to the current limit + if len(results[country][item_type]['items']) > limit: + results[country][item_type]['items'] = \ + results[country][item_type]['items'][:limit] + + count += len(results[country][item_type]['items']) + if total and limit > total - count: + # when approaching `total` results, adjust `limit` to not request more + # items than needed + limit = total - count + + if total and count >= total: + return results + + return results diff --git a/.venv/Lib/site-packages/spotipy/exceptions.py b/.venv/Lib/site-packages/spotipy/exceptions.py new file mode 100644 index 00000000..df503f10 --- /dev/null +++ b/.venv/Lib/site-packages/spotipy/exceptions.py @@ -0,0 +1,16 @@ +class SpotifyException(Exception): + + def __init__(self, http_status, code, msg, reason=None, headers=None): + self.http_status = http_status + self.code = code + self.msg = msg + self.reason = reason + # `headers` is used to support `Retry-After` in the event of a + # 429 status code. + if headers is None: + headers = {} + self.headers = headers + + def __str__(self): + return 'http status: {0}, code:{1} - {2}, reason: {3}'.format( + self.http_status, self.code, self.msg, self.reason) diff --git a/.venv/Lib/site-packages/spotipy/oauth2.py b/.venv/Lib/site-packages/spotipy/oauth2.py new file mode 100644 index 00000000..125c87c9 --- /dev/null +++ b/.venv/Lib/site-packages/spotipy/oauth2.py @@ -0,0 +1,1308 @@ +# -*- coding: utf-8 -*- + +__all__ = [ + "SpotifyClientCredentials", + "SpotifyOAuth", + "SpotifyOauthError", + "SpotifyStateError", + "SpotifyImplicitGrant", + "SpotifyPKCE" +] + +import base64 +import logging +import os +import time +import warnings +import webbrowser + +import requests +# Workaround to support both python 2 & 3 +import six +import six.moves.urllib.parse as urllibparse +from six.moves.BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer +from six.moves.urllib_parse import parse_qsl, urlparse + +from spotipy.cache_handler import CacheFileHandler, CacheHandler +from spotipy.util import CLIENT_CREDS_ENV_VARS, get_host_port, normalize_scope + +logger = logging.getLogger(__name__) + + +class SpotifyOauthError(Exception): + """ Error during Auth Code or Implicit Grant flow """ + + def __init__(self, message, error=None, error_description=None, *args, **kwargs): + self.error = error + self.error_description = error_description + self.__dict__.update(kwargs) + super(SpotifyOauthError, self).__init__(message, *args, **kwargs) + + +class SpotifyStateError(SpotifyOauthError): + """ The state sent and state received were different """ + + def __init__(self, local_state=None, remote_state=None, message=None, + error=None, error_description=None, *args, **kwargs): + if not message: + message = ("Expected " + local_state + " but recieved " + + remote_state) + super(SpotifyOauthError, self).__init__(message, error, + error_description, *args, + **kwargs) + + +def _make_authorization_headers(client_id, client_secret): + auth_header = base64.b64encode( + six.text_type(client_id + ":" + client_secret).encode("ascii") + ) + return {"Authorization": "Basic %s" % auth_header.decode("ascii")} + + +def _ensure_value(value, env_key): + env_val = CLIENT_CREDS_ENV_VARS[env_key] + _val = value or os.getenv(env_val) + if _val is None: + msg = "No %s. Pass it or set a %s environment variable." % ( + env_key, + env_val, + ) + raise SpotifyOauthError(msg) + return _val + + +class SpotifyAuthBase(object): + def __init__(self, requests_session): + if isinstance(requests_session, requests.Session): + self._session = requests_session + else: + if requests_session: # Build a new session. + self._session = requests.Session() + else: # Use the Requests API module as a "session". + from requests import api + self._session = api + + def _normalize_scope(self, scope): + return normalize_scope(scope) + + @property + def client_id(self): + return self._client_id + + @client_id.setter + def client_id(self, val): + self._client_id = _ensure_value(val, "client_id") + + @property + def client_secret(self): + return self._client_secret + + @client_secret.setter + def client_secret(self, val): + self._client_secret = _ensure_value(val, "client_secret") + + @property + def redirect_uri(self): + return self._redirect_uri + + @redirect_uri.setter + def redirect_uri(self, val): + self._redirect_uri = _ensure_value(val, "redirect_uri") + + @staticmethod + def _get_user_input(prompt): + try: + return raw_input(prompt) + except NameError: + return input(prompt) + + @staticmethod + def is_token_expired(token_info): + now = int(time.time()) + return token_info["expires_at"] - now < 60 + + @staticmethod + def _is_scope_subset(needle_scope, haystack_scope): + needle_scope = set(needle_scope.split()) if needle_scope else set() + haystack_scope = ( + set(haystack_scope.split()) if haystack_scope else set() + ) + return needle_scope <= haystack_scope + + def _handle_oauth_error(self, http_error): + response = http_error.response + try: + error_payload = response.json() + error = error_payload.get('error') + error_description = error_payload.get('error_description') + except ValueError: + # if the response cannot be decoded into JSON (which raises a ValueError), + # then try to decode it into text + + # if we receive an empty string (which is falsy), then replace it with `None` + error = response.text or None + error_description = None + + raise SpotifyOauthError( + 'error: {0}, error_description: {1}'.format( + error, error_description + ), + error=error, + error_description=error_description + ) + + def __del__(self): + """Make sure the connection (pool) gets closed""" + if isinstance(self._session, requests.Session): + self._session.close() + + +class SpotifyClientCredentials(SpotifyAuthBase): + OAUTH_TOKEN_URL = "https://accounts.spotify.com/api/token" + + def __init__( + self, + client_id=None, + client_secret=None, + proxies=None, + requests_session=True, + requests_timeout=None, + cache_handler=None + ): + """ + Creates a Client Credentials Flow Manager. + + The Client Credentials flow is used in server-to-server authentication. + Only endpoints that do not access user information can be accessed. + This means that endpoints that require authorization scopes cannot be accessed. + The advantage, however, of this authorization flow is that it does not require any + user interaction + + You can either provide a client_id and client_secret to the + constructor or set SPOTIPY_CLIENT_ID and SPOTIPY_CLIENT_SECRET + environment variables + + Parameters: + * client_id: Must be supplied or set as environment variable + * client_secret: Must be supplied or set as environment variable + * proxies: Optional, proxy for the requests library to route through + * requests_session: A Requests session + * requests_timeout: Optional, tell Requests to stop waiting for a response after + a given number of seconds + * cache_handler: An instance of the `CacheHandler` class to handle + getting and saving cached authorization tokens. + Optional, will otherwise use `CacheFileHandler`. + (takes precedence over `cache_path` and `username`) + + """ + + super(SpotifyClientCredentials, self).__init__(requests_session) + + self.client_id = client_id + self.client_secret = client_secret + self.proxies = proxies + self.requests_timeout = requests_timeout + if cache_handler: + assert issubclass(cache_handler.__class__, CacheHandler), \ + "cache_handler must be a subclass of CacheHandler: " + str(type(cache_handler)) \ + + " != " + str(CacheHandler) + self.cache_handler = cache_handler + else: + self.cache_handler = CacheFileHandler() + + def get_access_token(self, as_dict=True, check_cache=True): + """ + If a valid access token is in memory, returns it + Else fetches a new token and returns it + + Parameters: + - as_dict - a boolean indicating if returning the access token + as a token_info dictionary, otherwise it will be returned + as a string. + """ + if as_dict: + warnings.warn( + "You're using 'as_dict = True'." + "get_access_token will return the token string directly in future " + "versions. Please adjust your code accordingly, or use " + "get_cached_token instead.", + DeprecationWarning, + stacklevel=2, + ) + + if check_cache: + token_info = self.cache_handler.get_cached_token() + if token_info and not self.is_token_expired(token_info): + return token_info if as_dict else token_info["access_token"] + + token_info = self._request_access_token() + token_info = self._add_custom_values_to_token_info(token_info) + self.cache_handler.save_token_to_cache(token_info) + return token_info if as_dict else token_info["access_token"] + + def _request_access_token(self): + """Gets client credentials access token """ + payload = {"grant_type": "client_credentials"} + + headers = _make_authorization_headers( + self.client_id, self.client_secret + ) + + logger.debug( + "sending POST request to %s with Headers: %s and Body: %r", + self.OAUTH_TOKEN_URL, headers, payload + ) + + try: + response = self._session.post( + self.OAUTH_TOKEN_URL, + data=payload, + headers=headers, + verify=True, + proxies=self.proxies, + timeout=self.requests_timeout, + ) + response.raise_for_status() + token_info = response.json() + return token_info + except requests.exceptions.HTTPError as http_error: + self._handle_oauth_error(http_error) + + def _add_custom_values_to_token_info(self, token_info): + """ + Store some values that aren't directly provided by a Web API + response. + """ + token_info["expires_at"] = int(time.time()) + token_info["expires_in"] + return token_info + + +class SpotifyOAuth(SpotifyAuthBase): + """ + Implements Authorization Code Flow for Spotify's OAuth implementation. + """ + OAUTH_AUTHORIZE_URL = "https://accounts.spotify.com/authorize" + OAUTH_TOKEN_URL = "https://accounts.spotify.com/api/token" + + def __init__( + self, + client_id=None, + client_secret=None, + redirect_uri=None, + state=None, + scope=None, + cache_path=None, + username=None, + proxies=None, + show_dialog=False, + requests_session=True, + requests_timeout=None, + open_browser=True, + cache_handler=None + ): + """ + Creates a SpotifyOAuth object + + Parameters: + * client_id: Must be supplied or set as environment variable + * client_secret: Must be supplied or set as environment variable + * redirect_uri: Must be supplied or set as environment variable + * state: Optional, no verification is performed + * scope: Optional, either a list of scopes or comma separated string of scopes. + e.g, "playlist-read-private,playlist-read-collaborative" + * cache_path: (deprecated) Optional, will otherwise be generated + (takes precedence over `username`) + * username: (deprecated) Optional or set as environment variable + (will set `cache_path` to `.cache-{username}`) + * proxies: Optional, proxy for the requests library to route through + * show_dialog: Optional, interpreted as boolean + * requests_session: A Requests session + * requests_timeout: Optional, tell Requests to stop waiting for a response after + a given number of seconds + * open_browser: Optional, whether or not the web browser should be opened to + authorize a user + * cache_handler: An instance of the `CacheHandler` class to handle + getting and saving cached authorization tokens. + Optional, will otherwise use `CacheFileHandler`. + (takes precedence over `cache_path` and `username`) + """ + + super(SpotifyOAuth, self).__init__(requests_session) + + self.client_id = client_id + self.client_secret = client_secret + self.redirect_uri = redirect_uri + self.state = state + self.scope = self._normalize_scope(scope) + if username or cache_path: + warnings.warn("Specifying cache_path or username as arguments to SpotifyOAuth " + + "will be deprecated. Instead, please create a CacheFileHandler " + + "instance with the desired cache_path and username and pass it " + + "to SpotifyOAuth as the cache_handler. For example:\n\n" + + "\tfrom spotipy.oauth2 import CacheFileHandler\n" + + "\thandler = CacheFileHandler(cache_path=cache_path, " + + "username=username)\n" + + "\tsp = spotipy.SpotifyOAuth(client_id, client_secret, " + + "redirect_uri," + + " cache_handler=handler)", + DeprecationWarning + ) + if cache_handler: + warnings.warn("A cache_handler has been specified along with a cache_path or " + + "username. The cache_path and username arguments will be ignored.") + if cache_handler: + assert issubclass(cache_handler.__class__, CacheHandler), \ + "cache_handler must be a subclass of CacheHandler: " + str(type(cache_handler)) \ + + " != " + str(CacheHandler) + self.cache_handler = cache_handler + else: + username = (username or os.getenv(CLIENT_CREDS_ENV_VARS["client_username"])) + self.cache_handler = CacheFileHandler( + username=username, + cache_path=cache_path + ) + self.proxies = proxies + self.requests_timeout = requests_timeout + self.show_dialog = show_dialog + self.open_browser = open_browser + + def validate_token(self, token_info): + if token_info is None: + return None + + # if scopes don't match, then bail + if "scope" not in token_info or not self._is_scope_subset( + self.scope, token_info["scope"] + ): + return None + + if self.is_token_expired(token_info): + token_info = self.refresh_access_token( + token_info["refresh_token"] + ) + + return token_info + + def get_authorize_url(self, state=None): + """ Gets the URL to use to authorize this app + """ + payload = { + "client_id": self.client_id, + "response_type": "code", + "redirect_uri": self.redirect_uri, + } + if self.scope: + payload["scope"] = self.scope + if state is None: + state = self.state + if state is not None: + payload["state"] = state + if self.show_dialog: + payload["show_dialog"] = True + + urlparams = urllibparse.urlencode(payload) + + return "%s?%s" % (self.OAUTH_AUTHORIZE_URL, urlparams) + + def parse_response_code(self, url): + """ Parse the response code in the given response url + + Parameters: + - url - the response url + """ + _, code = self.parse_auth_response_url(url) + if code is None: + return url + else: + return code + + @staticmethod + def parse_auth_response_url(url): + query_s = urlparse(url).query + form = dict(parse_qsl(query_s)) + if "error" in form: + raise SpotifyOauthError("Received error from auth server: " + "{}".format(form["error"]), + error=form["error"]) + return tuple(form.get(param) for param in ["state", "code"]) + + def _make_authorization_headers(self): + return _make_authorization_headers(self.client_id, self.client_secret) + + def _open_auth_url(self): + auth_url = self.get_authorize_url() + try: + webbrowser.open(auth_url) + logger.info("Opened %s in your browser", auth_url) + except webbrowser.Error: + logger.error("Please navigate here: %s", auth_url) + + def _get_auth_response_interactive(self, open_browser=False): + if open_browser: + self._open_auth_url() + prompt = "Enter the URL you were redirected to: " + else: + url = self.get_authorize_url() + prompt = ( + "Go to the following URL: {}\n" + "Enter the URL you were redirected to: ".format(url) + ) + response = self._get_user_input(prompt) + state, code = SpotifyOAuth.parse_auth_response_url(response) + if self.state is not None and self.state != state: + raise SpotifyStateError(self.state, state) + return code + + def _get_auth_response_local_server(self, redirect_port): + server = start_local_http_server(redirect_port) + self._open_auth_url() + server.handle_request() + + if server.error is not None: + raise server.error + elif self.state is not None and server.state != self.state: + raise SpotifyStateError(self.state, server.state) + elif server.auth_code is not None: + return server.auth_code + else: + raise SpotifyOauthError("Server listening on localhost has not been accessed") + + def get_auth_response(self, open_browser=None): + logger.info('User authentication requires interaction with your ' + 'web browser. Once you enter your credentials and ' + 'give authorization, you will be redirected to ' + 'a url. Paste that url you were directed to to ' + 'complete the authorization.') + + redirect_info = urlparse(self.redirect_uri) + redirect_host, redirect_port = get_host_port(redirect_info.netloc) + + if open_browser is None: + open_browser = self.open_browser + + if ( + open_browser + and redirect_host in ("127.0.0.1", "localhost") + and redirect_info.scheme == "http" + ): + # Only start a local http server if a port is specified + if redirect_port: + return self._get_auth_response_local_server(redirect_port) + else: + logger.warning('Using `%s` as redirect URI without a port. ' + 'Specify a port (e.g. `%s:8080`) to allow ' + 'automatic retrieval of authentication code ' + 'instead of having to copy and paste ' + 'the URL your browser is redirected to.', + redirect_host, redirect_host) + + return self._get_auth_response_interactive(open_browser=open_browser) + + def get_authorization_code(self, response=None): + if response: + return self.parse_response_code(response) + return self.get_auth_response() + + def get_access_token(self, code=None, as_dict=True, check_cache=True): + """ Gets the access token for the app given the code + + Parameters: + - code - the response code + - as_dict - a boolean indicating if returning the access token + as a token_info dictionary, otherwise it will be returned + as a string. + """ + if as_dict: + warnings.warn( + "You're using 'as_dict = True'." + "get_access_token will return the token string directly in future " + "versions. Please adjust your code accordingly, or use " + "get_cached_token instead.", + DeprecationWarning, + stacklevel=2, + ) + if check_cache: + token_info = self.validate_token(self.cache_handler.get_cached_token()) + if token_info is not None: + if self.is_token_expired(token_info): + token_info = self.refresh_access_token( + token_info["refresh_token"] + ) + return token_info if as_dict else token_info["access_token"] + + payload = { + "redirect_uri": self.redirect_uri, + "code": code or self.get_auth_response(), + "grant_type": "authorization_code", + } + if self.scope: + payload["scope"] = self.scope + if self.state: + payload["state"] = self.state + + headers = self._make_authorization_headers() + + logger.debug( + "sending POST request to %s with Headers: %s and Body: %r", + self.OAUTH_TOKEN_URL, headers, payload + ) + + try: + response = self._session.post( + self.OAUTH_TOKEN_URL, + data=payload, + headers=headers, + verify=True, + proxies=self.proxies, + timeout=self.requests_timeout, + ) + response.raise_for_status() + token_info = response.json() + token_info = self._add_custom_values_to_token_info(token_info) + self.cache_handler.save_token_to_cache(token_info) + return token_info if as_dict else token_info["access_token"] + except requests.exceptions.HTTPError as http_error: + self._handle_oauth_error(http_error) + + def refresh_access_token(self, refresh_token): + payload = { + "refresh_token": refresh_token, + "grant_type": "refresh_token", + } + + headers = self._make_authorization_headers() + + logger.debug( + "sending POST request to %s with Headers: %s and Body: %r", + self.OAUTH_TOKEN_URL, headers, payload + ) + + try: + response = self._session.post( + self.OAUTH_TOKEN_URL, + data=payload, + headers=headers, + proxies=self.proxies, + timeout=self.requests_timeout, + ) + response.raise_for_status() + token_info = response.json() + token_info = self._add_custom_values_to_token_info(token_info) + if "refresh_token" not in token_info: + token_info["refresh_token"] = refresh_token + self.cache_handler.save_token_to_cache(token_info) + return token_info + except requests.exceptions.HTTPError as http_error: + self._handle_oauth_error(http_error) + + def _add_custom_values_to_token_info(self, token_info): + """ + Store some values that aren't directly provided by a Web API + response. + """ + token_info["expires_at"] = int(time.time()) + token_info["expires_in"] + token_info["scope"] = self.scope + return token_info + + def get_cached_token(self): + warnings.warn("Calling get_cached_token directly on the SpotifyOAuth object will be " + + "deprecated. Instead, please specify a CacheFileHandler instance as " + + "the cache_handler in SpotifyOAuth and use the CacheFileHandler's " + + "get_cached_token method. You can replace:\n\tsp.get_cached_token()" + + "\n\nWith:\n\tsp.validate_token(sp.cache_handler.get_cached_token())", + DeprecationWarning + ) + return self.validate_token(self.cache_handler.get_cached_token()) + + def _save_token_info(self, token_info): + warnings.warn("Calling _save_token_info directly on the SpotifyOAuth object will be " + + "deprecated. Instead, please specify a CacheFileHandler instance as " + + "the cache_handler in SpotifyOAuth and use the CacheFileHandler's " + + "save_token_to_cache method.", + DeprecationWarning + ) + self.cache_handler.save_token_to_cache(token_info) + return None + + +class SpotifyPKCE(SpotifyAuthBase): + """ Implements PKCE Authorization Flow for client apps + + This auth manager enables *user and non-user* endpoints with only + a client ID, redirect URI, and username. When the app requests + an access token for the first time, the user is prompted to + authorize the new client app. After authorizing the app, the client + app is then given both access and refresh tokens. This is the + preferred way of authorizing a mobile/desktop client. + + """ + + OAUTH_AUTHORIZE_URL = "https://accounts.spotify.com/authorize" + OAUTH_TOKEN_URL = "https://accounts.spotify.com/api/token" + + def __init__(self, + client_id=None, + redirect_uri=None, + state=None, + scope=None, + cache_path=None, + username=None, + proxies=None, + requests_timeout=None, + requests_session=True, + open_browser=True, + cache_handler=None): + """ + Creates Auth Manager with the PKCE Auth flow. + + Parameters: + * client_id: Must be supplied or set as environment variable + * redirect_uri: Must be supplied or set as environment variable + * state: Optional, no verification is performed + * scope: Optional, either a list of scopes or comma separated string of scopes. + e.g, "playlist-read-private,playlist-read-collaborative" + * cache_path: (deprecated) Optional, will otherwise be generated + (takes precedence over `username`) + * username: (deprecated) Optional or set as environment variable + (will set `cache_path` to `.cache-{username}`) + * proxies: Optional, proxy for the requests library to route through + * requests_timeout: Optional, tell Requests to stop waiting for a response after + a given number of seconds + * requests_session: A Requests session + * open_browser: Optional, whether or not the web browser should be opened to + authorize a user + * cache_handler: An instance of the `CacheHandler` class to handle + getting and saving cached authorization tokens. + Optional, will otherwise use `CacheFileHandler`. + (takes precedence over `cache_path` and `username`) + """ + + super(SpotifyPKCE, self).__init__(requests_session) + self.client_id = client_id + self.redirect_uri = redirect_uri + self.state = state + self.scope = self._normalize_scope(scope) + if username or cache_path: + warnings.warn("Specifying cache_path or username as arguments to SpotifyPKCE " + + "will be deprecated. Instead, please create a CacheFileHandler " + + "instance with the desired cache_path and username and pass it " + + "to SpotifyPKCE as the cache_handler. For example:\n\n" + + "\tfrom spotipy.oauth2 import CacheFileHandler\n" + + "\thandler = CacheFileHandler(cache_path=cache_path, " + + "username=username)\n" + + "\tsp = spotipy.SpotifyImplicitGrant(client_id, client_secret, " + + "redirect_uri, cache_handler=handler)", + DeprecationWarning + ) + if cache_handler: + warnings.warn("A cache_handler has been specified along with a cache_path or " + + "username. The cache_path and username arguments will be ignored.") + if cache_handler: + assert issubclass(type(cache_handler), CacheHandler), \ + "type(cache_handler): " + str(type(cache_handler)) + " != " + str(CacheHandler) + self.cache_handler = cache_handler + else: + username = (username or os.getenv(CLIENT_CREDS_ENV_VARS["client_username"])) + self.cache_handler = CacheFileHandler( + username=username, + cache_path=cache_path + ) + self.proxies = proxies + self.requests_timeout = requests_timeout + + self._code_challenge_method = "S256" # Spotify requires SHA256 + self.code_verifier = None + self.code_challenge = None + self.authorization_code = None + self.open_browser = open_browser + + def _get_code_verifier(self): + """ Spotify PCKE code verifier - See step 1 of the reference guide below + Reference: + https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow-with-proof-key-for-code-exchange-pkce + """ + # Range (33,96) is used to select between 44-128 base64 characters for the + # next operation. The range looks weird because base64 is 6 bytes + import random + length = random.randint(33, 96) + + # The seeded length generates between a 44 and 128 base64 characters encoded string + try: + import secrets + verifier = secrets.token_urlsafe(length) + except ImportError: # For python 3.5 support + import base64 + import os + rand_bytes = os.urandom(length) + verifier = base64.urlsafe_b64encode(rand_bytes).decode('utf-8').replace('=', '') + return verifier + + def _get_code_challenge(self): + """ Spotify PCKE code challenge - See step 1 of the reference guide below + Reference: + https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow-with-proof-key-for-code-exchange-pkce + """ + import base64 + import hashlib + code_challenge_digest = hashlib.sha256(self.code_verifier.encode('utf-8')).digest() + code_challenge = base64.urlsafe_b64encode(code_challenge_digest).decode('utf-8') + return code_challenge.replace('=', '') + + def get_authorize_url(self, state=None): + """ Gets the URL to use to authorize this app """ + if not self.code_challenge: + self.get_pkce_handshake_parameters() + payload = { + "client_id": self.client_id, + "response_type": "code", + "redirect_uri": self.redirect_uri, + "code_challenge_method": self._code_challenge_method, + "code_challenge": self.code_challenge + } + if self.scope: + payload["scope"] = self.scope + if state is None: + state = self.state + if state is not None: + payload["state"] = state + urlparams = urllibparse.urlencode(payload) + return "%s?%s" % (self.OAUTH_AUTHORIZE_URL, urlparams) + + def _open_auth_url(self, state=None): + auth_url = self.get_authorize_url(state) + try: + webbrowser.open(auth_url) + logger.info("Opened %s in your browser", auth_url) + except webbrowser.Error: + logger.error("Please navigate here: %s", auth_url) + + def _get_auth_response(self, open_browser=None): + logger.info('User authentication requires interaction with your ' + 'web browser. Once you enter your credentials and ' + 'give authorization, you will be redirected to ' + 'a url. Paste that url you were directed to to ' + 'complete the authorization.') + + redirect_info = urlparse(self.redirect_uri) + redirect_host, redirect_port = get_host_port(redirect_info.netloc) + + if open_browser is None: + open_browser = self.open_browser + + if ( + open_browser + and redirect_host in ("127.0.0.1", "localhost") + and redirect_info.scheme == "http" + ): + # Only start a local http server if a port is specified + if redirect_port: + return self._get_auth_response_local_server(redirect_port) + else: + logger.warning('Using `%s` as redirect URI without a port. ' + 'Specify a port (e.g. `%s:8080`) to allow ' + 'automatic retrieval of authentication code ' + 'instead of having to copy and paste ' + 'the URL your browser is redirected to.', + redirect_host, redirect_host) + return self._get_auth_response_interactive(open_browser=open_browser) + + def _get_auth_response_local_server(self, redirect_port): + server = start_local_http_server(redirect_port) + self._open_auth_url() + server.handle_request() + + if self.state is not None and server.state != self.state: + raise SpotifyStateError(self.state, server.state) + + if server.auth_code is not None: + return server.auth_code + elif server.error is not None: + raise SpotifyOauthError("Received error from OAuth server: {}".format(server.error)) + else: + raise SpotifyOauthError("Server listening on localhost has not been accessed") + + def _get_auth_response_interactive(self, open_browser=False): + if open_browser or self.open_browser: + self._open_auth_url() + prompt = "Enter the URL you were redirected to: " + else: + url = self.get_authorize_url() + prompt = ( + "Go to the following URL: {}\n" + "Enter the URL you were redirected to: ".format(url) + ) + response = self._get_user_input(prompt) + state, code = self.parse_auth_response_url(response) + if self.state is not None and self.state != state: + raise SpotifyStateError(self.state, state) + return code + + def get_authorization_code(self, response=None): + if response: + return self.parse_response_code(response) + return self._get_auth_response() + + def validate_token(self, token_info): + if token_info is None: + return None + + # if scopes don't match, then bail + if "scope" not in token_info or not self._is_scope_subset( + self.scope, token_info["scope"] + ): + return None + + if self.is_token_expired(token_info): + token_info = self.refresh_access_token( + token_info["refresh_token"] + ) + + return token_info + + def _add_custom_values_to_token_info(self, token_info): + """ + Store some values that aren't directly provided by a Web API + response. + """ + token_info["expires_at"] = int(time.time()) + token_info["expires_in"] + return token_info + + def get_pkce_handshake_parameters(self): + self.code_verifier = self._get_code_verifier() + self.code_challenge = self._get_code_challenge() + + def get_access_token(self, code=None, check_cache=True): + """ Gets the access token for the app + + If the code is not given and no cached token is used, an + authentication window will be shown to the user to get a new + code. + + Parameters: + - code - the response code from authentication + - check_cache - if true, checks for a locally stored token + before requesting a new token + """ + + if check_cache: + token_info = self.validate_token(self.cache_handler.get_cached_token()) + if token_info is not None: + if self.is_token_expired(token_info): + token_info = self.refresh_access_token( + token_info["refresh_token"] + ) + return token_info["access_token"] + + if self.code_verifier is None or self.code_challenge is None: + self.get_pkce_handshake_parameters() + + payload = { + "client_id": self.client_id, + "grant_type": "authorization_code", + "code": code or self.get_authorization_code(), + "redirect_uri": self.redirect_uri, + "code_verifier": self.code_verifier + } + + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + logger.debug( + "sending POST request to %s with Headers: %s and Body: %r", + self.OAUTH_TOKEN_URL, headers, payload + ) + + try: + response = self._session.post( + self.OAUTH_TOKEN_URL, + data=payload, + headers=headers, + verify=True, + proxies=self.proxies, + timeout=self.requests_timeout, + ) + response.raise_for_status() + token_info = response.json() + token_info = self._add_custom_values_to_token_info(token_info) + self.cache_handler.save_token_to_cache(token_info) + return token_info["access_token"] + except requests.exceptions.HTTPError as http_error: + self._handle_oauth_error(http_error) + + def refresh_access_token(self, refresh_token): + payload = { + "refresh_token": refresh_token, + "grant_type": "refresh_token", + "client_id": self.client_id, + } + + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + logger.debug( + "sending POST request to %s with Headers: %s and Body: %r", + self.OAUTH_TOKEN_URL, headers, payload + ) + + try: + response = self._session.post( + self.OAUTH_TOKEN_URL, + data=payload, + headers=headers, + proxies=self.proxies, + timeout=self.requests_timeout, + ) + response.raise_for_status() + token_info = response.json() + token_info = self._add_custom_values_to_token_info(token_info) + if "refresh_token" not in token_info: + token_info["refresh_token"] = refresh_token + self.cache_handler.save_token_to_cache(token_info) + return token_info + except requests.exceptions.HTTPError as http_error: + self._handle_oauth_error(http_error) + + def parse_response_code(self, url): + """ Parse the response code in the given response url + + Parameters: + - url - the response url + """ + _, code = self.parse_auth_response_url(url) + if code is None: + return url + else: + return code + + @staticmethod + def parse_auth_response_url(url): + return SpotifyOAuth.parse_auth_response_url(url) + + def get_cached_token(self): + warnings.warn("Calling get_cached_token directly on the SpotifyPKCE object will be " + + "deprecated. Instead, please specify a CacheFileHandler instance as " + + "the cache_handler in SpotifyOAuth and use the CacheFileHandler's " + + "get_cached_token method. You can replace:\n\tsp.get_cached_token()" + + "\n\nWith:\n\tsp.validate_token(sp.cache_handler.get_cached_token())", + DeprecationWarning + ) + return self.validate_token(self.cache_handler.get_cached_token()) + + def _save_token_info(self, token_info): + warnings.warn("Calling _save_token_info directly on the SpotifyOAuth object will be " + + "deprecated. Instead, please specify a CacheFileHandler instance as " + + "the cache_handler in SpotifyOAuth and use the CacheFileHandler's " + + "save_token_to_cache method.", + DeprecationWarning + ) + self.cache_handler.save_token_to_cache(token_info) + return None + + +class SpotifyImplicitGrant(SpotifyAuthBase): + """ Implements Implicit Grant Flow for client apps + + This auth manager enables *user and non-user* endpoints with only + a client secret, redirect uri, and username. The user will need to + copy and paste a URI from the browser every hour. + + Security Warning + ----------------- + The OAuth standard no longer recommends the Implicit Grant Flow for + client-side code. Spotify has implemented the OAuth-suggested PKCE + extension that removes the need for a client secret in the + Authentication Code flow. Use the SpotifyPKCE auth manager instead + of SpotifyImplicitGrant. + + SpotifyPKCE contains all of the functionality of + SpotifyImplicitGrant, plus automatic response retrieval and + refreshable tokens. Only a few replacements need to be made: + + * get_auth_response()['access_token'] -> + get_access_token(get_authorization_code()) + * get_auth_response() -> + get_access_token(get_authorization_code()); get_cached_token() + * parse_response_token(url)['access_token'] -> + get_access_token(parse_response_code(url)) + * parse_response_token(url) -> + get_access_token(parse_response_code(url)); get_cached_token() + + The security concern in the Implicit Grant flow is that the token is + returned in the URL and can be intercepted through the browser. A + request with an authorization code and proof of origin could not be + easily intercepted without a compromised network. + """ + OAUTH_AUTHORIZE_URL = "https://accounts.spotify.com/authorize" + + def __init__(self, + client_id=None, + redirect_uri=None, + state=None, + scope=None, + cache_path=None, + username=None, + show_dialog=False, + cache_handler=None): + """ Creates Auth Manager using the Implicit Grant flow + + **See help(SpotifyImplicitGrant) for full Security Warning** + + Parameters + ---------- + * client_id: Must be supplied or set as environment variable + * redirect_uri: Must be supplied or set as environment variable + * state: May be supplied, no verification is performed + * scope: Optional, either a list of scopes or comma separated string of scopes. + e.g, "playlist-read-private,playlist-read-collaborative" + * cache_handler: An instance of the `CacheHandler` class to handle + getting and saving cached authorization tokens. + May be supplied, will otherwise use `CacheFileHandler`. + (takes precedence over `cache_path` and `username`) + * cache_path: (deprecated) May be supplied, will otherwise be generated + (takes precedence over `username`) + * username: (deprecated) May be supplied or set as environment variable + (will set `cache_path` to `.cache-{username}`) + * show_dialog: Interpreted as boolean + """ + logger.warning("The OAuth standard no longer recommends the Implicit " + "Grant Flow for client-side code. Use the SpotifyPKCE " + "auth manager instead of SpotifyImplicitGrant. For " + "more details and a guide to switching, see " + "help(SpotifyImplicitGrant).") + + self.client_id = client_id + self.redirect_uri = redirect_uri + self.state = state + if username or cache_path: + warnings.warn("Specifying cache_path or username as arguments to " + + "SpotifyImplicitGrant will be deprecated. Instead, please create " + + "a CacheFileHandler instance with the desired cache_path and " + + "username and pass it to SpotifyImplicitGrant as the " + + "cache_handler. For example:\n\n" + + "\tfrom spotipy.oauth2 import CacheFileHandler\n" + + "\thandler = CacheFileHandler(cache_path=cache_path, " + + "username=username)\n" + + "\tsp = spotipy.SpotifyImplicitGrant(client_id, client_secret, " + + "redirect_uri, cache_handler=handler)", + DeprecationWarning + ) + if cache_handler: + warnings.warn("A cache_handler has been specified along with a cache_path or " + + "username. The cache_path and username arguments will be ignored.") + if cache_handler: + assert issubclass(type(cache_handler), CacheHandler), \ + "type(cache_handler): " + str(type(cache_handler)) + " != " + str(CacheHandler) + self.cache_handler = cache_handler + else: + username = (username or os.getenv(CLIENT_CREDS_ENV_VARS["client_username"])) + self.cache_handler = CacheFileHandler( + username=username, + cache_path=cache_path + ) + self.scope = self._normalize_scope(scope) + self.show_dialog = show_dialog + self._session = None # As to not break inherited __del__ + + def validate_token(self, token_info): + if token_info is None: + return None + + # if scopes don't match, then bail + if "scope" not in token_info or not self._is_scope_subset( + self.scope, token_info["scope"] + ): + return None + + if self.is_token_expired(token_info): + return None + + return token_info + + def get_access_token(self, + state=None, + response=None, + check_cache=True): + """ Gets Auth Token from cache (preferred) or user interaction + + Parameters + ---------- + * state: May be given, overrides (without changing) self.state + * response: URI with token, can break expiration checks + * check_cache: Interpreted as boolean + """ + if check_cache: + token_info = self.validate_token(self.cache_handler.get_cached_token()) + if not (token_info is None or self.is_token_expired(token_info)): + return token_info["access_token"] + + if response: + token_info = self.parse_response_token(response) + else: + token_info = self.get_auth_response(state) + token_info = self._add_custom_values_to_token_info(token_info) + self.cache_handler.save_token_to_cache(token_info) + + return token_info["access_token"] + + def get_authorize_url(self, state=None): + """ Gets the URL to use to authorize this app """ + payload = { + "client_id": self.client_id, + "response_type": "token", + "redirect_uri": self.redirect_uri, + } + if self.scope: + payload["scope"] = self.scope + if state is None: + state = self.state + if state is not None: + payload["state"] = state + if self.show_dialog: + payload["show_dialog"] = True + + urlparams = urllibparse.urlencode(payload) + + return "%s?%s" % (self.OAUTH_AUTHORIZE_URL, urlparams) + + def parse_response_token(self, url, state=None): + """ Parse the response code in the given response url """ + remote_state, token, t_type, exp_in = self.parse_auth_response_url(url) + if state is None: + state = self.state + if state is not None and remote_state != state: + raise SpotifyStateError(state, remote_state) + return {"access_token": token, "token_type": t_type, + "expires_in": exp_in, "state": state} + + @staticmethod + def parse_auth_response_url(url): + url_components = urlparse(url) + fragment_s = url_components.fragment + query_s = url_components.query + form = dict(i.split('=') for i + in (fragment_s or query_s or url).split('&')) + if "error" in form: + raise SpotifyOauthError("Received error from auth server: " + "{}".format(form["error"]), + state=form["state"]) + if "expires_in" in form: + form["expires_in"] = int(form["expires_in"]) + return tuple(form.get(param) for param in ["state", "access_token", + "token_type", "expires_in"]) + + def _open_auth_url(self, state=None): + auth_url = self.get_authorize_url(state) + try: + webbrowser.open(auth_url) + logger.info("Opened %s in your browser", auth_url) + except webbrowser.Error: + logger.error("Please navigate here: %s", auth_url) + + def get_auth_response(self, state=None): + """ Gets a new auth **token** with user interaction """ + logger.info('User authentication requires interaction with your ' + 'web browser. Once you enter your credentials and ' + 'give authorization, you will be redirected to ' + 'a url. Paste that url you were directed to to ' + 'complete the authorization.') + + redirect_info = urlparse(self.redirect_uri) + redirect_host, redirect_port = get_host_port(redirect_info.netloc) + # Implicit Grant tokens are returned in a hash fragment + # which is only available to the browser. Therefore, interactive + # URL retrieval is required. + if (redirect_host in ("127.0.0.1", "localhost") + and redirect_info.scheme == "http" and redirect_port): + logger.warning('Using a local redirect URI with a ' + 'port, likely expecting automatic ' + 'retrieval. Due to technical limitations, ' + 'the authentication token cannot be ' + 'automatically retrieved and must be ' + 'copied and pasted.') + + self._open_auth_url(state) + logger.info('Paste that url you were directed to in order to ' + 'complete the authorization') + response = SpotifyImplicitGrant._get_user_input("Enter the URL you " + "were redirected to: ") + return self.parse_response_token(response, state) + + def _add_custom_values_to_token_info(self, token_info): + """ + Store some values that aren't directly provided by a Web API + response. + """ + token_info["expires_at"] = int(time.time()) + token_info["expires_in"] + token_info["scope"] = self.scope + return token_info + + def get_cached_token(self): + warnings.warn("Calling get_cached_token directly on the SpotifyImplicitGrant " + + "object will be deprecated. Instead, please specify a " + + "CacheFileHandler instance as the cache_handler in SpotifyOAuth " + + "and use the CacheFileHandler's get_cached_token method. " + + "You can replace:\n\tsp.get_cached_token()" + + "\n\nWith:\n\tsp.validate_token(sp.cache_handler.get_cached_token())", + DeprecationWarning + ) + return self.validate_token(self.cache_handler.get_cached_token()) + + def _save_token_info(self, token_info): + warnings.warn("Calling _save_token_info directly on the SpotifyImplicitGrant " + + "object will be deprecated. Instead, please specify a " + + "CacheFileHandler instance as the cache_handler in SpotifyOAuth " + + "and use the CacheFileHandler's save_token_to_cache method.", + DeprecationWarning + ) + self.cache_handler.save_token_to_cache(token_info) + return None + + +class RequestHandler(BaseHTTPRequestHandler): + def do_GET(self): + self.server.auth_code = self.server.error = None + try: + state, auth_code = SpotifyOAuth.parse_auth_response_url(self.path) + self.server.state = state + self.server.auth_code = auth_code + except SpotifyOauthError as error: + self.server.error = error + + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.end_headers() + + if self.server.auth_code: + status = "successful" + elif self.server.error: + status = "failed ({})".format(self.server.error) + else: + self._write("

Invalid request

") + return + + self._write(""" + + +

Authentication status: {}

+This window can be closed. + + + +""".format(status)) + + def _write(self, text): + return self.wfile.write(text.encode("utf-8")) + + def log_message(self, format, *args): + return + + +def start_local_http_server(port, handler=RequestHandler): + server = HTTPServer(("127.0.0.1", port), handler) + server.allow_reuse_address = True + server.auth_code = None + server.auth_token_form = None + server.error = None + return server diff --git a/.venv/Lib/site-packages/spotipy/util.py b/.venv/Lib/site-packages/spotipy/util.py new file mode 100644 index 00000000..b949a618 --- /dev/null +++ b/.venv/Lib/site-packages/spotipy/util.py @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- + +""" Shows a user's playlists (need to be authenticated via oauth) """ + +__all__ = ["CLIENT_CREDS_ENV_VARS", "prompt_for_user_token"] + +import logging +import os +import warnings + +import spotipy + +LOGGER = logging.getLogger(__name__) + +CLIENT_CREDS_ENV_VARS = { + "client_id": "SPOTIPY_CLIENT_ID", + "client_secret": "SPOTIPY_CLIENT_SECRET", + "client_username": "SPOTIPY_CLIENT_USERNAME", + "redirect_uri": "SPOTIPY_REDIRECT_URI", +} + + +def prompt_for_user_token( + username=None, + scope=None, + client_id=None, + client_secret=None, + redirect_uri=None, + cache_path=None, + oauth_manager=None, + show_dialog=False +): + warnings.warn( + "'prompt_for_user_token' is deprecated." + "Use the following instead: " + " auth_manager=SpotifyOAuth(scope=scope)" + " spotipy.Spotify(auth_manager=auth_manager)", + DeprecationWarning + ) + """ prompts the user to login if necessary and returns + the user token suitable for use with the spotipy.Spotify + constructor + + Parameters: + + - username - the Spotify username (optional) + - scope - the desired scope of the request (optional) + - client_id - the client id of your app (required) + - client_secret - the client secret of your app (required) + - redirect_uri - the redirect URI of your app (required) + - cache_path - path to location to save tokens (optional) + - oauth_manager - Oauth manager object (optional) + - show_dialog - If true, a login prompt always shows (optional, defaults to False) + + """ + if not oauth_manager: + if not client_id: + client_id = os.getenv("SPOTIPY_CLIENT_ID") + + if not client_secret: + client_secret = os.getenv("SPOTIPY_CLIENT_SECRET") + + if not redirect_uri: + redirect_uri = os.getenv("SPOTIPY_REDIRECT_URI") + + if not client_id: + LOGGER.warning( + """ + You need to set your Spotify API credentials. + You can do this by setting environment variables like so: + + export SPOTIPY_CLIENT_ID='your-spotify-client-id' + export SPOTIPY_CLIENT_SECRET='your-spotify-client-secret' + export SPOTIPY_REDIRECT_URI='your-app-redirect-url' + + Get your credentials at + https://developer.spotify.com/my-applications + """ + ) + raise spotipy.SpotifyException(550, -1, "no credentials set") + + sp_oauth = oauth_manager or spotipy.SpotifyOAuth( + client_id, + client_secret, + redirect_uri, + scope=scope, + cache_path=cache_path, + username=username, + show_dialog=show_dialog + ) + + # try to get a valid token for this user, from the cache, + # if not in the cache, then create a new (this will send + # the user to a web page where they can authorize this app) + + token_info = sp_oauth.validate_token(sp_oauth.cache_handler.get_cached_token()) + + if not token_info: + code = sp_oauth.get_auth_response() + token = sp_oauth.get_access_token(code, as_dict=False) + else: + return token_info["access_token"] + + # Auth'ed API request + if token: + return token + else: + return None + + +def get_host_port(netloc): + if ":" in netloc: + host, port = netloc.split(":", 1) + port = int(port) + else: + host = netloc + port = None + + return host, port + + +def normalize_scope(scope): + if scope: + if isinstance(scope, str): + scopes = scope.split(',') + elif isinstance(scope, list) or isinstance(scope, tuple): + scopes = scope + else: + raise Exception( + "Unsupported scope value, please either provide a list of scopes, " + "or a string of scopes separated by commas" + ) + return " ".join(sorted(scopes)) + else: + return None diff --git a/__pycache__/webapp.cpython-311.pyc b/__pycache__/webapp.cpython-311.pyc index 47799fb6190dca455f5b9617b799fc267da39356..649e02f7cc0afc065042289c5838cdb79dfd0821 100644 GIT binary patch delta 1320 zcmZV;O>bL8aQA)Mar}|Et(|YHNC|F2NbL9{6r!Rc1WgV|K_D3k*U!6gY#iI#_k2ik zun$E7gesLi5D_YR3P{O;OMd`2Bqa2Le6XH`goJue)Sh}`)*lFmc{{VS^R=_Hv+tSz zBm5M=zrOl}{;fUqh4F)j3$HW@B2rn;=rGG=*Pc7$#z;aG(~)D0&0(C$wWGpjHeQ*WFj74Urny9I+1jquI5NGwjPVEufauz5m6h;5h7Xx1JxT6G=+Ac zTCRZyLXTBZ#g7niHB_*1Kax)`-QI!L(1>T^Uzd_dtP2Oam%Ta5rSmD1bpT?&_V~Qh1`oPA8ZJCkdaAg;SUOWeZ6#zYp>qw5=kei|J!Zi8 z`Lo_^Z{O`Ptvi2CPXDm@-D1bzv_H6O1MQA;8BNV!AZbc_E{F&eKod(pz1a>gx5IH; zxyqNc@T7QAjw=h@QLJRM??dmXgc|iiG{isFUY^lS(aE)a$Jb|;tGT+h8)M?u`RCeP zfz62sTCdev1QyIIBzpf1IFea&R93B9l!=b(7QvBOy~0HAF_A#GUN2m)?^Q{?OgGqT zAQOKTa|`IXj4|$Ttj}=2uJKuYe5!+dt?t)BaeH|16@4QKC7Vs!GYR{a(RphJ0?h8> z3nb|CF169*U+R_ChxfDg${kzXJX1H@>LxGi8=)|M;~W9Gkdbtwjicw1kgV}v^kqe) F`VS0$L`whw delta 800 zcmZWn&1(}u6rb7M*`3{d))o4JNF~tPruLu+Rog-lL`ty-F-R`U1y?D`!LjQmidMGRY50#$upuR~OA^6z$-t2q7H}7L!!#znQKO_4&d3X(Mx#^am=kcMyLVYp*&@J-Ug4u3~ukBcUrF>Bk++@tc&M%uRkB> zw3d)xb$1Lg((7a9b5w`GMmHGclU?);#4JV&xM|llKmd1$Ise6^xW!@*+XyiL@oANf zAQo>XWDO7Er2K?0OR8O!pS71H0r$k^qCSXYvZzlu6#jMKlbqbuU&udtT3$1Tl+GGV z4~-qfj8F$jLJZOjH5dZjAc5H_NXeR^Qa*!{L!w61q`i%9n4!t+!G8fI(mififhy>f zm=jt>+#7orjm7RncF_yC;C|pov|L$T4vH0To!$~f?lJ%Rx;ZgCSHN7(5hnLZCT$6o zAu>vS#f$U;m%quAD`&yvt9FM^NyHT>UEm%U%K?9|T7e{9ATEG8t-$-TX-?&wgH+}) zmD#*~l`-czYm?;&A!bZ zrB+(Gr54E4ik!1t?8tl82s}h+4d6cc+PWyeS?3ocvL>M4$h=vG{sPgj$|Ryvg%PM} zwF``NQT2pcW1*I>-ODdJ{iwpKWj-q=!KRkj|B2*%IwSY!tQ@hY`&~S9j6nR*kv4va Q$Bs2+8JCakNkiT97h?pt)Bpeg diff --git a/requirements.txt b/requirements.txt index d139b8d7587d2537a5637097f2f12b2a03b57e35..068cdab62a1018ab065d7bcd2387835f4498f6c8 100644 GIT binary patch delta 143 zcmdnTc7%O{9dmseLk>eCLoq`(gB^n{gAs!sg8>j5Gw?ESF%&RVGL$f6Fyu4jG3YX+ z0O=BjR3N(ytQMrskiim28i7?OGL(W<=P+b4B!N{Jf=vUNR0Pyl2$W9++EfC>FuRP{ J8O*`P001BD7To{< delta 7 OcmX@YzK?B#9Www6>H>iP diff --git a/server.py b/server.py new file mode 100644 index 00000000..cc0d1e6c --- /dev/null +++ b/server.py @@ -0,0 +1,60 @@ +import json +from os import environ as env +from urllib.parse import quote_plus, urlencode + +from authlib.integrations.flask_client import OAuth +from dotenv import find_dotenv, load_dotenv +from flask import Flask, redirect, render_template, session, url_for + +ENV_FILE = find_dotenv() +if ENV_FILE: + load_dotenv(ENV_FILE) + +app = Flask(__name__) +app.secret_key = env.get("APP_SECRET_KEY") + +oauth = OAuth(app) + +oauth.register( + "auth0", + client_id=env.get("AUTH0_CLIENT_ID"), + client_secret=env.get("AUTH0_CLIENT_SECRET"), + client_kwargs={ + "scope": "openid profile email", + }, + server_metadata_url=f'https://{env.get("AUTH0_DOMAIN")}/.well-known/openid-configuration' +) + +@app.route("/login") +def login(): + return oauth.auth0.authorize_redirect( + redirect_uri=url_for("callback", _external=True) + ) + +@app.route("/callback", methods=["GET", "POST"]) +def callback(): + token = oauth.auth0.authorize_access_token() + session["user"] = token + return redirect("/") + +@app.route("/logout") +def logout(): + session.clear() + return redirect( + "https://" + env.get("AUTH0_DOMAIN") + + "/v2/logout?" + + urlencode( + { + "returnTo": url_for("home", _external=True), + "client_id": env.get("AUTH0_CLIENT_ID"), + }, + quote_via=quote_plus, + ) + ) + +@app.route("/") +def home(): + return render_template("home.html", session=session.get('user'), pretty=json.dumps(session.get('user'), indent=4)) + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=env.get("PORT", 3000)) \ No newline at end of file diff --git a/templates/home.html b/templates/home.html index 7e524cef..30a5dde9 100644 --- a/templates/home.html +++ b/templates/home.html @@ -7,6 +7,15 @@ + {% if session %} +

Welcome {{session.userinfo.name}}!

+

Logout

+
{{pretty}}
+ {% else %} +

Welcome Guest

+

Login

+ {% endif %} +

Flask Cohere App

@@ -43,8 +52,8 @@

Flask Cohere App

function generateContent() { var interests = document.getElementById("interests").value; var location = document.getElementById("location").value; - var location = document.getElementById("friends").value; - var location = document.getElementById("age").value; + var friends = document.getElementById("friends").value; + var age = document.getElementById("age").value; fetch('/generate', { method: 'POST', @@ -62,5 +71,7 @@

Flask Cohere App

} + + \ No newline at end of file diff --git a/webapp.py b/webapp.py index a25f2ace..ba4eab22 100644 --- a/webapp.py +++ b/webapp.py @@ -1,6 +1,8 @@ from flask import Flask, render_template, request, jsonify import cohere import os +import spotipy +from spotipy.oauth2 import SpotifyClientCredentials app = Flask(__name__) @@ -9,6 +11,11 @@ print(f"API Key: {cohere_api_key}") co = cohere.Client(cohere_api_key) +# Initialize Spotipy client +client_credentials_manager = SpotifyClientCredentials(client_id='55be60be52eb4b658763757653391641', + client_secret='8ce1ad629229430ab7d2d7278ebdb9bd') +sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) + @app.route("/") def home(): return render_template("home.html") @@ -20,17 +27,19 @@ def generate_content(): # Get user inputs from the JSON data user_interests = data.get("interests") user_location = data.get("location") - user_age = data.get("location") - user_friends = data.get("location") + user_age = data.get("age") + user_friends = data.get("friends") + + print(user_friends) # Use Cohere to generate content based on user inputs parameters = f'Friends:{user_friends}, Interests: {user_interests}, Location: {user_location}' generation_response = co.generate( - prompt=f'Please write a short story for nostalgia based on these parameters: {parameters}' + prompt=f'Please write a short story for nostalgia based on these parameters: {parameters} addressing the user as "you"' ) # User's age & location used for childhood Spotify - + # Access the 'text' attribute to get the generated content generated_content = generation_response[0].text From 1cd4c49c25ffd5f9b02959de6e5090966ab8e8c6 Mon Sep 17 00:00:00 2001 From: Yihoi Jung Date: Sat, 27 Jan 2024 13:46:58 -0500 Subject: [PATCH 04/16] OAuth Authentication implemented --- .../Authlib-1.3.0.dist-info/INSTALLER | 1 + .../Authlib-1.3.0.dist-info/LICENSE | 29 + .../Authlib-1.3.0.dist-info/METADATA | 104 + .../Authlib-1.3.0.dist-info/RECORD | 387 ++ .../Authlib-1.3.0.dist-info/REQUESTED | 0 .../Authlib-1.3.0.dist-info/WHEEL | 6 + .../Authlib-1.3.0.dist-info/top_level.txt | 1 + .../_cffi_backend.cp311-win_amd64.pyd | Bin 0 -> 181248 bytes .venv/Lib/site-packages/authlib/__init__.py | 17 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 745 bytes .../__pycache__/consts.cpython-311.pyc | Bin 0 -> 534 bytes .../__pycache__/deprecate.cpython-311.pyc | Bin 0 -> 1088 bytes .../site-packages/authlib/common/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 195 bytes .../__pycache__/encoding.cpython-311.pyc | Bin 0 -> 4022 bytes .../common/__pycache__/errors.cpython-311.pyc | Bin 0 -> 3449 bytes .../__pycache__/security.cpython-311.pyc | Bin 0 -> 1424 bytes .../common/__pycache__/urls.cpython-311.pyc | Bin 0 -> 5899 bytes .../site-packages/authlib/common/encoding.py | 66 + .../site-packages/authlib/common/errors.py | 63 + .../site-packages/authlib/common/security.py | 19 + .../Lib/site-packages/authlib/common/urls.py | 146 + .venv/Lib/site-packages/authlib/consts.py | 11 + .venv/Lib/site-packages/authlib/deprecate.py | 16 + .../authlib/integrations/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 201 bytes .../integrations/base_client/__init__.py | 18 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 941 bytes .../__pycache__/async_app.cpython-311.pyc | Bin 0 -> 10260 bytes .../__pycache__/async_openid.cpython-311.pyc | Bin 0 -> 4462 bytes .../__pycache__/errors.cpython-311.pyc | Bin 0 -> 1998 bytes .../framework_integration.cpython-311.pyc | Bin 0 -> 3987 bytes .../__pycache__/registry.cpython-311.pyc | Bin 0 -> 5667 bytes .../__pycache__/sync_app.cpython-311.pyc | Bin 0 -> 16623 bytes .../__pycache__/sync_openid.cpython-311.pyc | Bin 0 -> 4444 bytes .../integrations/base_client/async_app.py | 144 + .../integrations/base_client/async_openid.py | 79 + .../integrations/base_client/errors.py | 30 + .../base_client/framework_integration.py | 64 + .../integrations/base_client/registry.py | 131 + .../integrations/base_client/sync_app.py | 343 ++ .../integrations/base_client/sync_openid.py | 77 + .../integrations/django_client/__init__.py | 19 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 895 bytes .../__pycache__/apps.cpython-311.pyc | Bin 0 -> 5255 bytes .../__pycache__/integration.cpython-311.pyc | Bin 0 -> 1491 bytes .../integrations/django_client/apps.py | 87 + .../integrations/django_client/integration.py | 22 + .../integrations/django_oauth1/__init__.py | 9 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 465 bytes .../authorization_server.cpython-311.pyc | Bin 0 -> 7652 bytes .../__pycache__/nonce.cpython-311.pyc | Bin 0 -> 875 bytes .../resource_protector.cpython-311.pyc | Bin 0 -> 4465 bytes .../django_oauth1/authorization_server.py | 125 + .../integrations/django_oauth1/nonce.py | 15 + .../django_oauth1/resource_protector.py | 64 + .../integrations/django_oauth2/__init__.py | 10 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 634 bytes .../authorization_server.cpython-311.pyc | Bin 0 -> 7049 bytes .../__pycache__/endpoints.cpython-311.pyc | Bin 0 -> 2739 bytes .../__pycache__/requests.cpython-311.pyc | Bin 0 -> 2962 bytes .../resource_protector.cpython-311.pyc | Bin 0 -> 4751 bytes .../__pycache__/signals.cpython-311.pyc | Bin 0 -> 433 bytes .../django_oauth2/authorization_server.py | 118 + .../integrations/django_oauth2/endpoints.py | 56 + .../integrations/django_oauth2/requests.py | 35 + .../django_oauth2/resource_protector.py | 75 + .../integrations/django_oauth2/signals.py | 11 + .../integrations/flask_client/__init__.py | 51 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 3001 bytes .../__pycache__/apps.cpython-311.pyc | Bin 0 -> 6189 bytes .../__pycache__/integration.cpython-311.pyc | Bin 0 -> 1642 bytes .../authlib/integrations/flask_client/apps.py | 107 + .../integrations/flask_client/integration.py | 28 + .../integrations/flask_oauth1/__init__.py | 9 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 588 bytes .../authorization_server.cpython-311.pyc | Bin 0 -> 9815 bytes .../__pycache__/cache.cpython-311.pyc | Bin 0 -> 4502 bytes .../resource_protector.cpython-311.pyc | Bin 0 -> 6040 bytes .../flask_oauth1/authorization_server.py | 182 + .../integrations/flask_oauth1/cache.py | 80 + .../flask_oauth1/resource_protector.py | 113 + .../integrations/flask_oauth2/__init__.py | 12 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 574 bytes .../authorization_server.cpython-311.pyc | Bin 0 -> 8964 bytes .../__pycache__/errors.cpython-311.pyc | Bin 0 -> 2441 bytes .../__pycache__/requests.cpython-311.pyc | Bin 0 -> 2430 bytes .../resource_protector.cpython-311.pyc | Bin 0 -> 6019 bytes .../__pycache__/signals.cpython-311.pyc | Bin 0 -> 582 bytes .../flask_oauth2/authorization_server.py | 159 + .../integrations/flask_oauth2/errors.py | 39 + .../integrations/flask_oauth2/requests.py | 30 + .../flask_oauth2/resource_protector.py | 114 + .../integrations/flask_oauth2/signals.py | 12 + .../integrations/httpx_client/__init__.py | 25 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 1107 bytes .../assertion_client.cpython-311.pyc | Bin 0 -> 4427 bytes .../__pycache__/oauth1_client.cpython-311.pyc | Bin 0 -> 5692 bytes .../__pycache__/oauth2_client.cpython-311.pyc | Bin 0 -> 12125 bytes .../__pycache__/utils.cpython-311.pyc | Bin 0 -> 1295 bytes .../httpx_client/assertion_client.py | 81 + .../httpx_client/oauth1_client.py | 102 + .../httpx_client/oauth2_client.py | 220 ++ .../integrations/httpx_client/utils.py | 30 + .../integrations/requests_client/__init__.py | 22 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 933 bytes .../assertion_session.cpython-311.pyc | Bin 0 -> 3040 bytes .../oauth1_session.cpython-311.pyc | Bin 0 -> 3348 bytes .../oauth2_session.cpython-311.pyc | Bin 0 -> 6306 bytes .../__pycache__/utils.cpython-311.pyc | Bin 0 -> 655 bytes .../requests_client/assertion_session.py | 46 + .../requests_client/oauth1_session.py | 59 + .../requests_client/oauth2_session.py | 110 + .../integrations/requests_client/utils.py | 10 + .../integrations/sqla_oauth2/__init__.py | 17 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 740 bytes .../__pycache__/client_mixin.cpython-311.pyc | Bin 0 -> 8496 bytes .../__pycache__/functions.cpython-311.pyc | Bin 0 -> 5975 bytes .../__pycache__/tokens_mixins.cpython-311.pyc | Bin 0 -> 4743 bytes .../integrations/sqla_oauth2/client_mixin.py | 138 + .../integrations/sqla_oauth2/functions.py | 101 + .../integrations/sqla_oauth2/tokens_mixins.py | 70 + .../integrations/starlette_client/__init__.py | 22 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 1298 bytes .../__pycache__/apps.cpython-311.pyc | Bin 0 -> 5743 bytes .../__pycache__/integration.cpython-311.pyc | Bin 0 -> 4090 bytes .../integrations/starlette_client/apps.py | 86 + .../starlette_client/integration.py | 66 + .../site-packages/authlib/jose/__init__.py | 60 + .../jose/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 1914 bytes .../jose/__pycache__/errors.cpython-311.pyc | Bin 0 -> 7590 bytes .../jose/__pycache__/jwk.cpython-311.pyc | Bin 0 -> 1107 bytes .../jose/__pycache__/util.cpython-311.pyc | Bin 0 -> 2113 bytes .../authlib/jose/drafts/__init__.py | 17 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 1063 bytes .../_jwe_algorithms.cpython-311.pyc | Bin 0 -> 10093 bytes .../_jwe_enc_cryptodome.cpython-311.pyc | Bin 0 -> 2783 bytes .../_jwe_enc_cryptography.cpython-311.pyc | Bin 0 -> 2597 bytes .../authlib/jose/drafts/_jwe_algorithms.py | 188 + .../jose/drafts/_jwe_enc_cryptodome.py | 52 + .../jose/drafts/_jwe_enc_cryptography.py | 50 + .../Lib/site-packages/authlib/jose/errors.py | 113 + .venv/Lib/site-packages/authlib/jose/jwk.py | 19 + .../authlib/jose/rfc7515/__init__.py | 18 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 629 bytes .../rfc7515/__pycache__/jws.cpython-311.pyc | Bin 0 -> 14489 bytes .../__pycache__/models.cpython-311.pyc | Bin 0 -> 4381 bytes .../site-packages/authlib/jose/rfc7515/jws.py | 304 ++ .../authlib/jose/rfc7515/models.py | 81 + .../authlib/jose/rfc7516/__init__.py | 18 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 701 bytes .../rfc7516/__pycache__/jwe.cpython-311.pyc | Bin 0 -> 31457 bytes .../__pycache__/models.cpython-311.pyc | Bin 0 -> 8497 bytes .../site-packages/authlib/jose/rfc7516/jwe.py | 722 ++++ .../authlib/jose/rfc7516/models.py | 148 + .../authlib/jose/rfc7517/__init__.py | 17 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 752 bytes .../_cryptography_key.cpython-311.pyc | Bin 0 -> 2014 bytes .../asymmetric_key.cpython-311.pyc | Bin 0 -> 9847 bytes .../__pycache__/base_key.cpython-311.pyc | Bin 0 -> 5893 bytes .../rfc7517/__pycache__/jwk.cpython-311.pyc | Bin 0 -> 3686 bytes .../__pycache__/key_set.cpython-311.pyc | Bin 0 -> 2009 bytes .../authlib/jose/rfc7517/_cryptography_key.py | 34 + .../authlib/jose/rfc7517/asymmetric_key.py | 191 + .../authlib/jose/rfc7517/base_key.py | 118 + .../site-packages/authlib/jose/rfc7517/jwk.py | 64 + .../authlib/jose/rfc7517/key_set.py | 29 + .../authlib/jose/rfc7518/__init__.py | 35 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 1546 bytes .../__pycache__/ec_key.cpython-311.pyc | Bin 0 -> 5595 bytes .../__pycache__/jwe_algs.cpython-311.pyc | Bin 0 -> 18332 bytes .../__pycache__/jwe_encs.cpython-311.pyc | Bin 0 -> 8305 bytes .../__pycache__/jwe_zips.cpython-311.pyc | Bin 0 -> 1449 bytes .../__pycache__/jws_algs.cpython-311.pyc | Bin 0 -> 11397 bytes .../__pycache__/oct_key.cpython-311.pyc | Bin 0 -> 4550 bytes .../__pycache__/rsa_key.cpython-311.pyc | Bin 0 -> 6690 bytes .../rfc7518/__pycache__/util.cpython-311.pyc | Bin 0 -> 841 bytes .../authlib/jose/rfc7518/ec_key.py | 101 + .../authlib/jose/rfc7518/jwe_algs.py | 349 ++ .../authlib/jose/rfc7518/jwe_encs.py | 144 + .../authlib/jose/rfc7518/jwe_zips.py | 21 + .../authlib/jose/rfc7518/jws_algs.py | 215 + .../authlib/jose/rfc7518/oct_key.py | 80 + .../authlib/jose/rfc7518/rsa_key.py | 123 + .../authlib/jose/rfc7518/util.py | 12 + .../authlib/jose/rfc7519/__init__.py | 15 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 583 bytes .../__pycache__/claims.cpython-311.pyc | Bin 0 -> 12107 bytes .../rfc7519/__pycache__/jwt.cpython-311.pyc | Bin 0 -> 8599 bytes .../authlib/jose/rfc7519/claims.py | 227 ++ .../site-packages/authlib/jose/rfc7519/jwt.py | 183 + .../authlib/jose/rfc8037/__init__.py | 5 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 360 bytes .../__pycache__/jws_eddsa.cpython-311.pyc | Bin 0 -> 1879 bytes .../__pycache__/okp_key.cpython-311.pyc | Bin 0 -> 5917 bytes .../authlib/jose/rfc8037/jws_eddsa.py | 27 + .../authlib/jose/rfc8037/okp_key.py | 103 + .venv/Lib/site-packages/authlib/jose/util.py | 37 + .../site-packages/authlib/oauth1/__init__.py | 34 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 807 bytes .../oauth1/__pycache__/client.cpython-311.pyc | Bin 0 -> 8605 bytes .../oauth1/__pycache__/errors.cpython-311.pyc | Bin 0 -> 234 bytes .../site-packages/authlib/oauth1/client.py | 172 + .../site-packages/authlib/oauth1/errors.py | 3 + .../authlib/oauth1/rfc5849/__init__.py | 45 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 1267 bytes .../authorization_server.cpython-311.pyc | Bin 0 -> 16553 bytes .../__pycache__/base_server.cpython-311.pyc | Bin 0 -> 4908 bytes .../__pycache__/client_auth.cpython-311.pyc | Bin 0 -> 8468 bytes .../__pycache__/errors.cpython-311.pyc | Bin 0 -> 5399 bytes .../__pycache__/models.cpython-311.pyc | Bin 0 -> 6023 bytes .../__pycache__/parameters.cpython-311.pyc | Bin 0 -> 4172 bytes .../resource_protector.cpython-311.pyc | Bin 0 -> 2152 bytes .../rfc5849/__pycache__/rsa.cpython-311.pyc | Bin 0 -> 1821 bytes .../__pycache__/signature.cpython-311.pyc | Bin 0 -> 13646 bytes .../rfc5849/__pycache__/util.cpython-311.pyc | Bin 0 -> 619 bytes .../__pycache__/wrapper.cpython-311.pyc | Bin 0 -> 7815 bytes .../oauth1/rfc5849/authorization_server.py | 357 ++ .../authlib/oauth1/rfc5849/base_server.py | 119 + .../authlib/oauth1/rfc5849/client_auth.py | 187 + .../authlib/oauth1/rfc5849/errors.py | 89 + .../authlib/oauth1/rfc5849/models.py | 108 + .../authlib/oauth1/rfc5849/parameters.py | 101 + .../oauth1/rfc5849/resource_protector.py | 41 + .../authlib/oauth1/rfc5849/rsa.py | 29 + .../authlib/oauth1/rfc5849/signature.py | 386 ++ .../authlib/oauth1/rfc5849/util.py | 9 + .../authlib/oauth1/rfc5849/wrapper.py | 129 + .../site-packages/authlib/oauth2/__init__.py | 16 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 692 bytes .../oauth2/__pycache__/auth.cpython-311.pyc | Bin 0 -> 5317 bytes .../oauth2/__pycache__/base.cpython-311.pyc | Bin 0 -> 2018 bytes .../oauth2/__pycache__/client.cpython-311.pyc | Bin 0 -> 19946 bytes .../Lib/site-packages/authlib/oauth2/auth.py | 106 + .../Lib/site-packages/authlib/oauth2/base.py | 26 + .../site-packages/authlib/oauth2/client.py | 438 +++ .../authlib/oauth2/rfc6749/__init__.py | 83 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 2425 bytes .../authenticate_client.cpython-311.pyc | Bin 0 -> 5469 bytes .../authorization_server.cpython-311.pyc | Bin 0 -> 16195 bytes .../__pycache__/errors.cpython-311.pyc | Bin 0 -> 11706 bytes .../__pycache__/models.cpython-311.pyc | Bin 0 -> 9777 bytes .../__pycache__/parameters.cpython-311.pyc | Bin 0 -> 9604 bytes .../__pycache__/requests.cpython-311.pyc | Bin 0 -> 4795 bytes .../resource_protector.cpython-311.pyc | Bin 0 -> 7213 bytes .../token_endpoint.cpython-311.pyc | Bin 0 -> 2063 bytes .../rfc6749/__pycache__/util.cpython-311.pyc | Bin 0 -> 2507 bytes .../__pycache__/wrappers.cpython-311.pyc | Bin 0 -> 1814 bytes .../oauth2/rfc6749/authenticate_client.py | 103 + .../oauth2/rfc6749/authorization_server.py | 301 ++ .../authlib/oauth2/rfc6749/errors.py | 233 ++ .../authlib/oauth2/rfc6749/grants/__init__.py | 37 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 1562 bytes .../authorization_code.cpython-311.pyc | Bin 0 -> 17623 bytes .../grants/__pycache__/base.cpython-311.pyc | Bin 0 -> 7835 bytes .../client_credentials.cpython-311.pyc | Bin 0 -> 5037 bytes .../__pycache__/implicit.cpython-311.pyc | Bin 0 -> 10383 bytes .../__pycache__/refresh_token.cpython-311.pyc | Bin 0 -> 8489 bytes ...owner_password_credentials.cpython-311.pyc | Bin 0 -> 7163 bytes .../rfc6749/grants/authorization_code.py | 378 ++ .../authlib/oauth2/rfc6749/grants/base.py | 148 + .../rfc6749/grants/client_credentials.py | 102 + .../authlib/oauth2/rfc6749/grants/implicit.py | 229 ++ .../oauth2/rfc6749/grants/refresh_token.py | 179 + .../resource_owner_password_credentials.py | 154 + .../authlib/oauth2/rfc6749/models.py | 228 ++ .../authlib/oauth2/rfc6749/parameters.py | 214 + .../authlib/oauth2/rfc6749/requests.py | 84 + .../oauth2/rfc6749/resource_protector.py | 140 + .../authlib/oauth2/rfc6749/token_endpoint.py | 32 + .../authlib/oauth2/rfc6749/util.py | 40 + .../authlib/oauth2/rfc6749/wrappers.py | 23 + .../authlib/oauth2/rfc6750/__init__.py | 26 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 836 bytes .../__pycache__/errors.cpython-311.pyc | Bin 0 -> 4341 bytes .../__pycache__/parameters.cpython-311.pyc | Bin 0 -> 1807 bytes .../rfc6750/__pycache__/token.cpython-311.pyc | Bin 0 -> 3907 bytes .../__pycache__/validator.cpython-311.pyc | Bin 0 -> 2285 bytes .../authlib/oauth2/rfc6750/errors.py | 80 + .../authlib/oauth2/rfc6750/parameters.py | 41 + .../authlib/oauth2/rfc6750/token.py | 88 + .../authlib/oauth2/rfc6750/validator.py | 39 + .../authlib/oauth2/rfc7009/__init__.py | 14 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 595 bytes .../__pycache__/parameters.cpython-311.pyc | Bin 0 -> 1147 bytes .../__pycache__/revocation.cpython-311.pyc | Bin 0 -> 5186 bytes .../authlib/oauth2/rfc7009/parameters.py | 25 + .../authlib/oauth2/rfc7009/revocation.py | 108 + .../authlib/oauth2/rfc7521/__init__.py | 3 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 289 bytes .../__pycache__/client.cpython-311.pyc | Bin 0 -> 3928 bytes .../authlib/oauth2/rfc7521/client.py | 91 + .../authlib/oauth2/rfc7523/__init__.py | 37 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 1111 bytes .../__pycache__/assertion.cpython-311.pyc | Bin 0 -> 2323 bytes .../rfc7523/__pycache__/auth.cpython-311.pyc | Bin 0 -> 4253 bytes .../__pycache__/client.cpython-311.pyc | Bin 0 -> 6078 bytes .../__pycache__/jwt_bearer.cpython-311.pyc | Bin 0 -> 8711 bytes .../rfc7523/__pycache__/token.cpython-311.pyc | Bin 0 -> 4519 bytes .../__pycache__/validator.cpython-311.pyc | Bin 0 -> 3390 bytes .../authlib/oauth2/rfc7523/assertion.py | 66 + .../authlib/oauth2/rfc7523/auth.py | 94 + .../authlib/oauth2/rfc7523/client.py | 113 + .../authlib/oauth2/rfc7523/jwt_bearer.py | 182 + .../authlib/oauth2/rfc7523/token.py | 93 + .../authlib/oauth2/rfc7523/validator.py | 54 + .../authlib/oauth2/rfc7591/__init__.py | 25 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 869 bytes .../__pycache__/claims.cpython-311.pyc | Bin 0 -> 12805 bytes .../__pycache__/endpoint.cpython-311.pyc | Bin 0 -> 11082 bytes .../__pycache__/errors.cpython-311.pyc | Bin 0 -> 2030 bytes .../authlib/oauth2/rfc7591/claims.py | 218 + .../authlib/oauth2/rfc7591/endpoint.py | 211 + .../authlib/oauth2/rfc7591/errors.py | 33 + .../authlib/oauth2/rfc7592/__init__.py | 13 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 544 bytes .../__pycache__/endpoint.cpython-311.pyc | Bin 0 -> 12596 bytes .../authlib/oauth2/rfc7592/endpoint.py | 256 ++ .../authlib/oauth2/rfc7636/__init__.py | 13 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 579 bytes .../__pycache__/challenge.cpython-311.pyc | Bin 0 -> 6235 bytes .../authlib/oauth2/rfc7636/challenge.py | 138 + .../authlib/oauth2/rfc7662/__init__.py | 15 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 677 bytes .../__pycache__/introspection.cpython-311.pyc | Bin 0 -> 6361 bytes .../__pycache__/models.cpython-311.pyc | Bin 0 -> 1926 bytes .../token_validator.cpython-311.pyc | Bin 0 -> 2336 bytes .../authlib/oauth2/rfc7662/introspection.py | 131 + .../authlib/oauth2/rfc7662/models.py | 30 + .../authlib/oauth2/rfc7662/token_validator.py | 34 + .../authlib/oauth2/rfc8414/__init__.py | 15 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 605 bytes .../__pycache__/models.cpython-311.pyc | Bin 0 -> 22506 bytes .../__pycache__/well_known.cpython-311.pyc | Bin 0 -> 1086 bytes .../authlib/oauth2/rfc8414/models.py | 368 ++ .../authlib/oauth2/rfc8414/well_known.py | 22 + .../authlib/oauth2/rfc8628/__init__.py | 22 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 912 bytes .../__pycache__/device_code.cpython-311.pyc | Bin 0 -> 9634 bytes .../__pycache__/endpoint.cpython-311.pyc | Bin 0 -> 8770 bytes .../__pycache__/errors.cpython-311.pyc | Bin 0 -> 1634 bytes .../__pycache__/models.cpython-311.pyc | Bin 0 -> 2648 bytes .../authlib/oauth2/rfc8628/device_code.py | 183 + .../authlib/oauth2/rfc8628/endpoint.py | 170 + .../authlib/oauth2/rfc8628/errors.py | 27 + .../authlib/oauth2/rfc8628/models.py | 38 + .../authlib/oauth2/rfc8693/__init__.py | 9 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 400 bytes .../authlib/oauth2/rfc9068/__init__.py | 11 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 553 bytes .../__pycache__/claims.cpython-311.pyc | Bin 0 -> 4083 bytes .../__pycache__/introspection.cpython-311.pyc | Bin 0 -> 5687 bytes .../__pycache__/revocation.cpython-311.pyc | Bin 0 -> 3574 bytes .../rfc9068/__pycache__/token.cpython-311.pyc | Bin 0 -> 7977 bytes .../token_validator.cpython-311.pyc | Bin 0 -> 6031 bytes .../authlib/oauth2/rfc9068/claims.py | 62 + .../authlib/oauth2/rfc9068/introspection.py | 126 + .../authlib/oauth2/rfc9068/revocation.py | 70 + .../authlib/oauth2/rfc9068/token.py | 218 + .../authlib/oauth2/rfc9068/token_validator.py | 163 + .../site-packages/authlib/oidc/__init__.py | 0 .../oidc/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 193 bytes .../authlib/oidc/core/__init__.py | 23 + .../core/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 935 bytes .../core/__pycache__/claims.cpython-311.pyc | Bin 0 -> 14374 bytes .../core/__pycache__/errors.cpython-311.pyc | Bin 0 -> 4612 bytes .../core/__pycache__/models.cpython-311.pyc | Bin 0 -> 1022 bytes .../core/__pycache__/util.cpython-311.pyc | Bin 0 -> 952 bytes .../site-packages/authlib/oidc/core/claims.py | 242 ++ .../site-packages/authlib/oidc/core/errors.py | 78 + .../authlib/oidc/core/grants/__init__.py | 10 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 472 bytes .../grants/__pycache__/code.cpython-311.pyc | Bin 0 -> 6799 bytes .../grants/__pycache__/hybrid.cpython-311.pyc | Bin 0 -> 5095 bytes .../__pycache__/implicit.cpython-311.pyc | Bin 0 -> 7636 bytes .../grants/__pycache__/util.cpython-311.pyc | Bin 0 -> 5271 bytes .../authlib/oidc/core/grants/code.py | 142 + .../authlib/oidc/core/grants/hybrid.py | 90 + .../authlib/oidc/core/grants/implicit.py | 150 + .../authlib/oidc/core/grants/util.py | 131 + .../site-packages/authlib/oidc/core/models.py | 13 + .../site-packages/authlib/oidc/core/util.py | 12 + .../authlib/oidc/discovery/__init__.py | 13 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 569 bytes .../__pycache__/models.cpython-311.pyc | Bin 0 -> 15745 bytes .../__pycache__/well_known.cpython-311.pyc | Bin 0 -> 893 bytes .../authlib/oidc/discovery/models.py | 283 ++ .../authlib/oidc/discovery/well_known.py | 17 + .../cffi-1.16.0.dist-info/INSTALLER | 1 + .../cffi-1.16.0.dist-info/LICENSE | 26 + .../cffi-1.16.0.dist-info/METADATA | 39 + .../cffi-1.16.0.dist-info/RECORD | 48 + .../site-packages/cffi-1.16.0.dist-info/WHEEL | 5 + .../cffi-1.16.0.dist-info/entry_points.txt | 2 + .../cffi-1.16.0.dist-info/top_level.txt | 2 + .venv/Lib/site-packages/cffi/__init__.py | 14 + .../cffi/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 620 bytes .../_imp_emulation.cpython-311.pyc | Bin 0 -> 4705 bytes .../_shimmed_dist_utils.cpython-311.pyc | Bin 0 -> 2189 bytes .../cffi/__pycache__/api.cpython-311.pyc | Bin 0 -> 55609 bytes .../backend_ctypes.cpython-311.pyc | Bin 0 -> 71900 bytes .../__pycache__/cffi_opcode.cpython-311.pyc | Bin 0 -> 7119 bytes .../__pycache__/commontypes.cpython-311.pyc | Bin 0 -> 3173 bytes .../cffi/__pycache__/cparser.cpython-311.pyc | Bin 0 -> 49595 bytes .../cffi/__pycache__/error.cpython-311.pyc | Bin 0 -> 2118 bytes .../__pycache__/ffiplatform.cpython-311.pyc | Bin 0 -> 6613 bytes .../cffi/__pycache__/lock.cpython-311.pyc | Bin 0 -> 630 bytes .../cffi/__pycache__/model.cpython-311.pyc | Bin 0 -> 33861 bytes .../__pycache__/pkgconfig.cpython-311.pyc | Bin 0 -> 8125 bytes .../__pycache__/recompiler.cpython-311.pyc | Bin 0 -> 89734 bytes .../setuptools_ext.cpython-311.pyc | Bin 0 -> 12593 bytes .../__pycache__/vengine_cpy.cpython-311.pyc | Bin 0 -> 56807 bytes .../__pycache__/vengine_gen.cpython-311.pyc | Bin 0 -> 38093 bytes .../cffi/__pycache__/verifier.cpython-311.pyc | Bin 0 -> 18082 bytes .venv/Lib/site-packages/cffi/_cffi_errors.h | 149 + .venv/Lib/site-packages/cffi/_cffi_include.h | 385 ++ .venv/Lib/site-packages/cffi/_embedding.h | 550 +++ .../Lib/site-packages/cffi/_imp_emulation.py | 83 + .../site-packages/cffi/_shimmed_dist_utils.py | 41 + .venv/Lib/site-packages/cffi/api.py | 965 +++++ .../Lib/site-packages/cffi/backend_ctypes.py | 1121 ++++++ .venv/Lib/site-packages/cffi/cffi_opcode.py | 187 + .venv/Lib/site-packages/cffi/commontypes.py | 80 + .venv/Lib/site-packages/cffi/cparser.py | 1006 +++++ .venv/Lib/site-packages/cffi/error.py | 31 + .venv/Lib/site-packages/cffi/ffiplatform.py | 113 + .venv/Lib/site-packages/cffi/lock.py | 30 + .venv/Lib/site-packages/cffi/model.py | 618 +++ .venv/Lib/site-packages/cffi/parse_c_type.h | 181 + .venv/Lib/site-packages/cffi/pkgconfig.py | 121 + .venv/Lib/site-packages/cffi/recompiler.py | 1581 ++++++++ .../Lib/site-packages/cffi/setuptools_ext.py | 216 + .venv/Lib/site-packages/cffi/vengine_cpy.py | 1077 +++++ .venv/Lib/site-packages/cffi/vengine_gen.py | 675 ++++ .venv/Lib/site-packages/cffi/verifier.py | 306 ++ .../cryptography-42.0.1.dist-info/INSTALLER | 1 + .../cryptography-42.0.1.dist-info/LICENSE | 3 + .../LICENSE.APACHE | 202 + .../cryptography-42.0.1.dist-info/LICENSE.BSD | 27 + .../cryptography-42.0.1.dist-info/METADATA | 135 + .../cryptography-42.0.1.dist-info/RECORD | 171 + .../cryptography-42.0.1.dist-info/WHEEL | 5 + .../top_level.txt | 1 + .../site-packages/cryptography/__about__.py | 17 + .../site-packages/cryptography/__init__.py | 13 + .../__pycache__/__about__.cpython-311.pyc | Bin 0 -> 485 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 435 bytes .../__pycache__/exceptions.cpython-311.pyc | Bin 0 -> 2962 bytes .../__pycache__/fernet.cpython-311.pyc | Bin 0 -> 11893 bytes .../__pycache__/utils.cpython-311.pyc | Bin 0 -> 7502 bytes .../site-packages/cryptography/exceptions.py | 52 + .../Lib/site-packages/cryptography/fernet.py | 215 + .../cryptography/hazmat/__init__.py | 13 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 266 bytes .../hazmat/__pycache__/_oid.cpython-311.pyc | Bin 0 -> 17971 bytes .../site-packages/cryptography/hazmat/_oid.py | 296 ++ .../cryptography/hazmat/backends/__init__.py | 13 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 576 bytes .../hazmat/backends/openssl/__init__.py | 9 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 396 bytes .../openssl/__pycache__/aead.cpython-311.pyc | Bin 0 -> 11226 bytes .../__pycache__/backend.cpython-311.pyc | Bin 0 -> 41980 bytes .../__pycache__/ciphers.cpython-311.pyc | Bin 0 -> 14002 bytes .../__pycache__/decode_asn1.cpython-311.pyc | Bin 0 -> 965 bytes .../hazmat/backends/openssl/aead.py | 272 ++ .../hazmat/backends/openssl/backend.py | 897 +++++ .../hazmat/backends/openssl/ciphers.py | 282 ++ .../hazmat/backends/openssl/decode_asn1.py | 32 + .../cryptography/hazmat/bindings/__init__.py | 3 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 209 bytes .../cryptography/hazmat/bindings/_rust.pyd | Bin 0 -> 7211520 bytes .../hazmat/bindings/_rust/__init__.pyi | 17 + .../hazmat/bindings/_rust/_openssl.pyi | 8 + .../hazmat/bindings/_rust/asn1.pyi | 14 + .../hazmat/bindings/_rust/exceptions.pyi | 17 + .../hazmat/bindings/_rust/ocsp.pyi | 23 + .../bindings/_rust/openssl/__init__.pyi | 57 + .../hazmat/bindings/_rust/openssl/aead.pyi | 69 + .../hazmat/bindings/_rust/openssl/cmac.pyi | 18 + .../hazmat/bindings/_rust/openssl/dh.pyi | 51 + .../hazmat/bindings/_rust/openssl/dsa.pyi | 41 + .../hazmat/bindings/_rust/openssl/ec.pyi | 52 + .../hazmat/bindings/_rust/openssl/ed25519.pyi | 12 + .../hazmat/bindings/_rust/openssl/ed448.pyi | 12 + .../hazmat/bindings/_rust/openssl/hashes.pyi | 17 + .../hazmat/bindings/_rust/openssl/hmac.pyi | 21 + .../hazmat/bindings/_rust/openssl/kdf.pyi | 22 + .../hazmat/bindings/_rust/openssl/keys.pyi | 37 + .../bindings/_rust/openssl/poly1305.pyi | 13 + .../hazmat/bindings/_rust/openssl/rsa.pyi | 55 + .../hazmat/bindings/_rust/openssl/x25519.pyi | 12 + .../hazmat/bindings/_rust/openssl/x448.pyi | 12 + .../hazmat/bindings/_rust/pkcs7.pyi | 21 + .../hazmat/bindings/_rust/x509.pyi | 88 + .../hazmat/bindings/openssl/__init__.py | 3 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 217 bytes .../__pycache__/_conditional.cpython-311.pyc | Bin 0 -> 7150 bytes .../__pycache__/binding.cpython-311.pyc | Bin 0 -> 8210 bytes .../hazmat/bindings/openssl/_conditional.py | 233 ++ .../hazmat/bindings/openssl/binding.py | 175 + .../hazmat/primitives/__init__.py | 3 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 211 bytes .../__pycache__/_asymmetric.cpython-311.pyc | Bin 0 -> 917 bytes .../_cipheralgorithm.cpython-311.pyc | Bin 0 -> 2124 bytes .../_serialization.cpython-311.pyc | Bin 0 -> 7713 bytes .../__pycache__/cmac.cpython-311.pyc | Bin 0 -> 437 bytes .../__pycache__/constant_time.cpython-311.pyc | Bin 0 -> 783 bytes .../__pycache__/hashes.cpython-311.pyc | Bin 0 -> 9491 bytes .../__pycache__/hmac.cpython-311.pyc | Bin 0 -> 614 bytes .../__pycache__/keywrap.cpython-311.pyc | Bin 0 -> 9140 bytes .../__pycache__/padding.cpython-311.pyc | Bin 0 -> 10341 bytes .../__pycache__/poly1305.cpython-311.pyc | Bin 0 -> 449 bytes .../hazmat/primitives/_asymmetric.py | 19 + .../hazmat/primitives/_cipheralgorithm.py | 44 + .../hazmat/primitives/_serialization.py | 169 + .../hazmat/primitives/asymmetric/__init__.py | 3 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 222 bytes .../asymmetric/__pycache__/dh.cpython-311.pyc | Bin 0 -> 5926 bytes .../__pycache__/dsa.cpython-311.pyc | Bin 0 -> 6759 bytes .../asymmetric/__pycache__/ec.cpython-311.pyc | Bin 0 -> 16721 bytes .../__pycache__/ed25519.cpython-311.pyc | Bin 0 -> 5560 bytes .../__pycache__/ed448.cpython-311.pyc | Bin 0 -> 5649 bytes .../__pycache__/padding.cpython-311.pyc | Bin 0 -> 5598 bytes .../__pycache__/rsa.cpython-311.pyc | Bin 0 -> 9363 bytes .../__pycache__/types.cpython-311.pyc | Bin 0 -> 2810 bytes .../__pycache__/utils.cpython-311.pyc | Bin 0 -> 1463 bytes .../__pycache__/x25519.cpython-311.pyc | Bin 0 -> 5346 bytes .../__pycache__/x448.cpython-311.pyc | Bin 0 -> 5430 bytes .../hazmat/primitives/asymmetric/dh.py | 135 + .../hazmat/primitives/asymmetric/dsa.py | 154 + .../hazmat/primitives/asymmetric/ec.py | 383 ++ .../hazmat/primitives/asymmetric/ed25519.py | 116 + .../hazmat/primitives/asymmetric/ed448.py | 118 + .../hazmat/primitives/asymmetric/padding.py | 113 + .../hazmat/primitives/asymmetric/rsa.py | 239 ++ .../hazmat/primitives/asymmetric/types.py | 111 + .../hazmat/primitives/asymmetric/utils.py | 24 + .../hazmat/primitives/asymmetric/x25519.py | 109 + .../hazmat/primitives/asymmetric/x448.py | 112 + .../hazmat/primitives/ciphers/__init__.py | 27 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 764 bytes .../ciphers/__pycache__/aead.cpython-311.pyc | Bin 0 -> 7570 bytes .../__pycache__/algorithms.cpython-311.pyc | Bin 0 -> 10491 bytes .../ciphers/__pycache__/base.cpython-311.pyc | Bin 0 -> 13988 bytes .../ciphers/__pycache__/modes.cpython-311.pyc | Bin 0 -> 13368 bytes .../hazmat/primitives/ciphers/aead.py | 174 + .../hazmat/primitives/ciphers/algorithms.py | 226 ++ .../hazmat/primitives/ciphers/base.py | 272 ++ .../hazmat/primitives/ciphers/modes.py | 273 ++ .../cryptography/hazmat/primitives/cmac.py | 10 + .../hazmat/primitives/constant_time.py | 14 + .../cryptography/hazmat/primitives/hashes.py | 242 ++ .../cryptography/hazmat/primitives/hmac.py | 13 + .../hazmat/primitives/kdf/__init__.py | 23 + .../kdf/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 1373 bytes .../kdf/__pycache__/concatkdf.cpython-311.pyc | Bin 0 -> 6058 bytes .../kdf/__pycache__/hkdf.cpython-311.pyc | Bin 0 -> 5238 bytes .../kdf/__pycache__/kbkdf.cpython-311.pyc | Bin 0 -> 12053 bytes .../kdf/__pycache__/pbkdf2.cpython-311.pyc | Bin 0 -> 3069 bytes .../kdf/__pycache__/scrypt.cpython-311.pyc | Bin 0 -> 3436 bytes .../kdf/__pycache__/x963kdf.cpython-311.pyc | Bin 0 -> 3451 bytes .../hazmat/primitives/kdf/concatkdf.py | 124 + .../hazmat/primitives/kdf/hkdf.py | 101 + .../hazmat/primitives/kdf/kbkdf.py | 299 ++ .../hazmat/primitives/kdf/pbkdf2.py | 64 + .../hazmat/primitives/kdf/scrypt.py | 80 + .../hazmat/primitives/kdf/x963kdf.py | 61 + .../cryptography/hazmat/primitives/keywrap.py | 177 + .../cryptography/hazmat/primitives/padding.py | 225 ++ .../hazmat/primitives/poly1305.py | 11 + .../primitives/serialization/__init__.py | 63 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 1629 bytes .../__pycache__/base.cpython-311.pyc | Bin 0 -> 712 bytes .../__pycache__/pkcs12.cpython-311.pyc | Bin 0 -> 9851 bytes .../__pycache__/pkcs7.cpython-311.pyc | Bin 0 -> 10210 bytes .../__pycache__/ssh.cpython-311.pyc | Bin 0 -> 68621 bytes .../hazmat/primitives/serialization/base.py | 14 + .../hazmat/primitives/serialization/pkcs12.py | 229 ++ .../hazmat/primitives/serialization/pkcs7.py | 233 ++ .../hazmat/primitives/serialization/ssh.py | 1507 +++++++ .../hazmat/primitives/twofactor/__init__.py | 9 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 527 bytes .../__pycache__/hotp.cpython-311.pyc | Bin 0 -> 5251 bytes .../__pycache__/totp.cpython-311.pyc | Bin 0 -> 2544 bytes .../hazmat/primitives/twofactor/hotp.py | 92 + .../hazmat/primitives/twofactor/totp.py | 50 + .venv/Lib/site-packages/cryptography/py.typed | 0 .venv/Lib/site-packages/cryptography/utils.py | 131 + .../cryptography/x509/__init__.py | 257 ++ .../x509/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 8120 bytes .../x509/__pycache__/base.cpython-311.pyc | Bin 0 -> 50830 bytes .../certificate_transparency.cpython-311.pyc | Bin 0 -> 4537 bytes .../__pycache__/extensions.cpython-311.pyc | Bin 0 -> 105559 bytes .../__pycache__/general_name.cpython-311.pyc | Bin 0 -> 14623 bytes .../x509/__pycache__/name.cpython-311.pyc | Bin 0 -> 25296 bytes .../x509/__pycache__/ocsp.cpython-311.pyc | Bin 0 -> 25432 bytes .../x509/__pycache__/oid.cpython-311.pyc | Bin 0 -> 832 bytes .../__pycache__/verification.cpython-311.pyc | Bin 0 -> 754 bytes .../site-packages/cryptography/x509/base.py | 1221 ++++++ .../x509/certificate_transparency.py | 97 + .../cryptography/x509/extensions.py | 2175 ++++++++++ .../cryptography/x509/general_name.py | 281 ++ .../site-packages/cryptography/x509/name.py | 456 +++ .../site-packages/cryptography/x509/ocsp.py | 615 +++ .../site-packages/cryptography/x509/oid.py | 33 + .../cryptography/x509/verification.py | 24 + .venv/Lib/site-packages/dotenv/__init__.py | 49 + .venv/Lib/site-packages/dotenv/__main__.py | 6 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 2030 bytes .../__pycache__/__main__.cpython-311.pyc | Bin 0 -> 394 bytes .../dotenv/__pycache__/cli.cpython-311.pyc | Bin 0 -> 10858 bytes .../__pycache__/ipython.cpython-311.pyc | Bin 0 -> 2310 bytes .../dotenv/__pycache__/main.cpython-311.pyc | Bin 0 -> 18147 bytes .../dotenv/__pycache__/parser.cpython-311.pyc | Bin 0 -> 11367 bytes .../__pycache__/variables.cpython-311.pyc | Bin 0 -> 5528 bytes .../__pycache__/version.cpython-311.pyc | Bin 0 -> 206 bytes .venv/Lib/site-packages/dotenv/cli.py | 199 + .venv/Lib/site-packages/dotenv/ipython.py | 39 + .venv/Lib/site-packages/dotenv/main.py | 392 ++ .venv/Lib/site-packages/dotenv/parser.py | 175 + .venv/Lib/site-packages/dotenv/py.typed | 1 + .venv/Lib/site-packages/dotenv/variables.py | 86 + .venv/Lib/site-packages/dotenv/version.py | 1 + .../pycparser-2.21.dist-info/INSTALLER | 1 + .../pycparser-2.21.dist-info/LICENSE | 27 + .../pycparser-2.21.dist-info/METADATA | 31 + .../pycparser-2.21.dist-info/RECORD | 41 + .../pycparser-2.21.dist-info/WHEEL | 6 + .../pycparser-2.21.dist-info/top_level.txt | 1 + .venv/Lib/site-packages/pycparser/__init__.py | 90 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 3231 bytes .../__pycache__/_ast_gen.cpython-311.pyc | Bin 0 -> 13454 bytes .../__pycache__/_build_tables.cpython-311.pyc | Bin 0 -> 790 bytes .../ast_transforms.cpython-311.pyc | Bin 0 -> 5544 bytes .../__pycache__/c_ast.cpython-311.pyc | Bin 0 -> 53264 bytes .../__pycache__/c_generator.cpython-311.pyc | Bin 0 -> 30966 bytes .../__pycache__/c_lexer.cpython-311.pyc | Bin 0 -> 18615 bytes .../__pycache__/c_parser.cpython-311.pyc | Bin 0 -> 93519 bytes .../__pycache__/lextab.cpython-311.pyc | Bin 0 -> 6973 bytes .../__pycache__/plyparser.cpython-311.pyc | Bin 0 -> 6499 bytes .../__pycache__/yacctab.cpython-311.pyc | Bin 0 -> 193304 bytes .venv/Lib/site-packages/pycparser/_ast_gen.py | 336 ++ .../site-packages/pycparser/_build_tables.py | 37 + .venv/Lib/site-packages/pycparser/_c_ast.cfg | 195 + .../site-packages/pycparser/ast_transforms.py | 164 + .venv/Lib/site-packages/pycparser/c_ast.py | 1125 ++++++ .../site-packages/pycparser/c_generator.py | 502 +++ .venv/Lib/site-packages/pycparser/c_lexer.py | 554 +++ .venv/Lib/site-packages/pycparser/c_parser.py | 1936 +++++++++ .venv/Lib/site-packages/pycparser/lextab.py | 10 + .../site-packages/pycparser/ply/__init__.py | 5 + .../ply/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 251 bytes .../ply/__pycache__/cpp.cpython-311.pyc | Bin 0 -> 34625 bytes .../ply/__pycache__/ctokens.cpython-311.pyc | Bin 0 -> 2458 bytes .../ply/__pycache__/lex.cpython-311.pyc | Bin 0 -> 44018 bytes .../ply/__pycache__/yacc.cpython-311.pyc | Bin 0 -> 110035 bytes .../ply/__pycache__/ygen.cpython-311.pyc | Bin 0 -> 3611 bytes .venv/Lib/site-packages/pycparser/ply/cpp.py | 905 +++++ .../site-packages/pycparser/ply/ctokens.py | 133 + .venv/Lib/site-packages/pycparser/ply/lex.py | 1099 ++++++ .venv/Lib/site-packages/pycparser/ply/yacc.py | 3494 +++++++++++++++++ .venv/Lib/site-packages/pycparser/ply/ygen.py | 74 + .../Lib/site-packages/pycparser/plyparser.py | 133 + .venv/Lib/site-packages/pycparser/yacctab.py | 366 ++ .../python_dotenv-1.0.1.dist-info/INSTALLER | 1 + .../python_dotenv-1.0.1.dist-info/LICENSE | 27 + .../python_dotenv-1.0.1.dist-info/METADATA | 692 ++++ .../python_dotenv-1.0.1.dist-info/RECORD | 26 + .../python_dotenv-1.0.1.dist-info/REQUESTED | 0 .../python_dotenv-1.0.1.dist-info/WHEEL | 5 + .../entry_points.txt | 2 + .../top_level.txt | 1 + .venv/Scripts/dotenv.exe | Bin 0 -> 108410 bytes __pycache__/webapp.cpython-311.pyc | Bin 2475 -> 5491 bytes server.py | 60 - templates/home.html | 15 +- templates/login.html | 12 + webapp.py | 61 +- 678 files changed, 56754 insertions(+), 69 deletions(-) create mode 100644 .venv/Lib/site-packages/Authlib-1.3.0.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/Authlib-1.3.0.dist-info/LICENSE create mode 100644 .venv/Lib/site-packages/Authlib-1.3.0.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/Authlib-1.3.0.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/Authlib-1.3.0.dist-info/REQUESTED create mode 100644 .venv/Lib/site-packages/Authlib-1.3.0.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/Authlib-1.3.0.dist-info/top_level.txt create mode 100644 .venv/Lib/site-packages/_cffi_backend.cp311-win_amd64.pyd create mode 100644 .venv/Lib/site-packages/authlib/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/__pycache__/consts.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/__pycache__/deprecate.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/common/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/common/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/common/__pycache__/encoding.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/common/__pycache__/errors.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/common/__pycache__/security.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/common/__pycache__/urls.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/common/encoding.py create mode 100644 .venv/Lib/site-packages/authlib/common/errors.py create mode 100644 .venv/Lib/site-packages/authlib/common/security.py create mode 100644 .venv/Lib/site-packages/authlib/common/urls.py create mode 100644 .venv/Lib/site-packages/authlib/consts.py create mode 100644 .venv/Lib/site-packages/authlib/deprecate.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/base_client/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/async_app.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/async_openid.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/errors.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/framework_integration.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/registry.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/sync_app.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/sync_openid.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/base_client/async_app.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/base_client/async_openid.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/base_client/errors.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/base_client/framework_integration.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/base_client/registry.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/base_client/sync_app.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/base_client/sync_openid.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_client/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_client/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_client/__pycache__/apps.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_client/__pycache__/integration.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_client/apps.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_client/integration.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth1/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth1/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth1/__pycache__/authorization_server.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth1/__pycache__/nonce.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth1/__pycache__/resource_protector.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth1/authorization_server.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth1/nonce.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth1/resource_protector.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth2/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth2/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth2/__pycache__/authorization_server.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth2/__pycache__/endpoints.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth2/__pycache__/requests.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth2/__pycache__/resource_protector.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth2/__pycache__/signals.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth2/authorization_server.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth2/endpoints.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth2/requests.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth2/resource_protector.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/django_oauth2/signals.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_client/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_client/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_client/__pycache__/apps.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_client/__pycache__/integration.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_client/apps.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_client/integration.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth1/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth1/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth1/__pycache__/authorization_server.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth1/__pycache__/cache.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth1/__pycache__/resource_protector.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth1/authorization_server.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth1/cache.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth1/resource_protector.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth2/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth2/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth2/__pycache__/authorization_server.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth2/__pycache__/errors.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth2/__pycache__/requests.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth2/__pycache__/resource_protector.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth2/__pycache__/signals.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth2/authorization_server.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth2/errors.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth2/requests.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth2/resource_protector.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/flask_oauth2/signals.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/httpx_client/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/httpx_client/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/httpx_client/__pycache__/assertion_client.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/httpx_client/__pycache__/oauth1_client.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/httpx_client/__pycache__/oauth2_client.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/httpx_client/__pycache__/utils.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/httpx_client/assertion_client.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/httpx_client/oauth1_client.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/httpx_client/oauth2_client.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/httpx_client/utils.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/requests_client/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/requests_client/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/requests_client/__pycache__/assertion_session.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/requests_client/__pycache__/oauth1_session.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/requests_client/__pycache__/oauth2_session.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/requests_client/__pycache__/utils.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/requests_client/assertion_session.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/requests_client/oauth1_session.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/requests_client/oauth2_session.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/requests_client/utils.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/sqla_oauth2/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/sqla_oauth2/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/sqla_oauth2/__pycache__/client_mixin.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/sqla_oauth2/__pycache__/functions.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/sqla_oauth2/__pycache__/tokens_mixins.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/sqla_oauth2/client_mixin.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/sqla_oauth2/functions.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/sqla_oauth2/tokens_mixins.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/starlette_client/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/starlette_client/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/starlette_client/__pycache__/apps.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/starlette_client/__pycache__/integration.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/integrations/starlette_client/apps.py create mode 100644 .venv/Lib/site-packages/authlib/integrations/starlette_client/integration.py create mode 100644 .venv/Lib/site-packages/authlib/jose/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/jose/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/__pycache__/errors.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/__pycache__/jwk.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/__pycache__/util.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/drafts/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/jose/drafts/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/drafts/__pycache__/_jwe_algorithms.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/drafts/__pycache__/_jwe_enc_cryptodome.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/drafts/__pycache__/_jwe_enc_cryptography.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/drafts/_jwe_algorithms.py create mode 100644 .venv/Lib/site-packages/authlib/jose/drafts/_jwe_enc_cryptodome.py create mode 100644 .venv/Lib/site-packages/authlib/jose/drafts/_jwe_enc_cryptography.py create mode 100644 .venv/Lib/site-packages/authlib/jose/errors.py create mode 100644 .venv/Lib/site-packages/authlib/jose/jwk.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7515/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7515/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7515/__pycache__/jws.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7515/__pycache__/models.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7515/jws.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7515/models.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7516/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7516/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7516/__pycache__/jwe.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7516/__pycache__/models.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7516/jwe.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7516/models.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7517/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7517/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7517/__pycache__/_cryptography_key.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7517/__pycache__/asymmetric_key.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7517/__pycache__/base_key.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7517/__pycache__/jwk.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7517/__pycache__/key_set.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7517/_cryptography_key.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7517/asymmetric_key.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7517/base_key.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7517/jwk.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7517/key_set.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7518/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7518/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7518/__pycache__/ec_key.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7518/__pycache__/jwe_algs.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7518/__pycache__/jwe_encs.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7518/__pycache__/jwe_zips.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7518/__pycache__/jws_algs.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7518/__pycache__/oct_key.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7518/__pycache__/rsa_key.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7518/__pycache__/util.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7518/ec_key.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7518/jwe_algs.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7518/jwe_encs.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7518/jwe_zips.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7518/jws_algs.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7518/oct_key.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7518/rsa_key.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7518/util.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7519/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7519/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7519/__pycache__/claims.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7519/__pycache__/jwt.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7519/claims.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc7519/jwt.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc8037/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc8037/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc8037/__pycache__/jws_eddsa.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc8037/__pycache__/okp_key.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc8037/jws_eddsa.py create mode 100644 .venv/Lib/site-packages/authlib/jose/rfc8037/okp_key.py create mode 100644 .venv/Lib/site-packages/authlib/jose/util.py create mode 100644 .venv/Lib/site-packages/authlib/oauth1/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oauth1/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth1/__pycache__/client.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth1/__pycache__/errors.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth1/client.py create mode 100644 .venv/Lib/site-packages/authlib/oauth1/errors.py create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/authorization_server.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/base_server.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/client_auth.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/errors.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/models.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/parameters.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/resource_protector.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/rsa.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/signature.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/util.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/wrapper.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/authorization_server.py create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/base_server.py create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/client_auth.py create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/errors.py create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/models.py create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/parameters.py create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/resource_protector.py create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/rsa.py create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/signature.py create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/util.py create mode 100644 .venv/Lib/site-packages/authlib/oauth1/rfc5849/wrapper.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/__pycache__/auth.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/__pycache__/base.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/__pycache__/client.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/auth.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/base.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/client.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/authenticate_client.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/authorization_server.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/errors.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/models.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/parameters.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/requests.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/resource_protector.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/token_endpoint.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/util.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/wrappers.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/authenticate_client.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/authorization_server.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/errors.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__pycache__/authorization_code.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__pycache__/base.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__pycache__/client_credentials.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__pycache__/implicit.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__pycache__/refresh_token.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__pycache__/resource_owner_password_credentials.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/authorization_code.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/base.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/client_credentials.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/implicit.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/refresh_token.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/resource_owner_password_credentials.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/models.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/parameters.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/requests.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/resource_protector.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/token_endpoint.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/util.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6749/wrappers.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6750/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6750/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6750/__pycache__/errors.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6750/__pycache__/parameters.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6750/__pycache__/token.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6750/__pycache__/validator.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6750/errors.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6750/parameters.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6750/token.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc6750/validator.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7009/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7009/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7009/__pycache__/parameters.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7009/__pycache__/revocation.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7009/parameters.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7009/revocation.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7521/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7521/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7521/__pycache__/client.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7521/client.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7523/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7523/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7523/__pycache__/assertion.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7523/__pycache__/auth.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7523/__pycache__/client.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7523/__pycache__/jwt_bearer.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7523/__pycache__/token.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7523/__pycache__/validator.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7523/assertion.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7523/auth.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7523/client.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7523/jwt_bearer.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7523/token.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7523/validator.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7591/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7591/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7591/__pycache__/claims.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7591/__pycache__/endpoint.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7591/__pycache__/errors.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7591/claims.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7591/endpoint.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7591/errors.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7592/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7592/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7592/__pycache__/endpoint.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7592/endpoint.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7636/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7636/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7636/__pycache__/challenge.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7636/challenge.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7662/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7662/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7662/__pycache__/introspection.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7662/__pycache__/models.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7662/__pycache__/token_validator.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7662/introspection.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7662/models.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc7662/token_validator.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc8414/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc8414/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc8414/__pycache__/models.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc8414/__pycache__/well_known.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc8414/models.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc8414/well_known.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc8628/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc8628/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc8628/__pycache__/device_code.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc8628/__pycache__/endpoint.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc8628/__pycache__/errors.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc8628/__pycache__/models.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc8628/device_code.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc8628/endpoint.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc8628/errors.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc8628/models.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc8693/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc8693/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc9068/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc9068/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc9068/__pycache__/claims.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc9068/__pycache__/introspection.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc9068/__pycache__/revocation.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc9068/__pycache__/token.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc9068/__pycache__/token_validator.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc9068/claims.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc9068/introspection.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc9068/revocation.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc9068/token.py create mode 100644 .venv/Lib/site-packages/authlib/oauth2/rfc9068/token_validator.py create mode 100644 .venv/Lib/site-packages/authlib/oidc/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oidc/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/__pycache__/claims.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/__pycache__/errors.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/__pycache__/models.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/__pycache__/util.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/claims.py create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/errors.py create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/grants/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/grants/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/grants/__pycache__/code.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/grants/__pycache__/hybrid.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/grants/__pycache__/implicit.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/grants/__pycache__/util.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/grants/code.py create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/grants/hybrid.py create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/grants/implicit.py create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/grants/util.py create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/models.py create mode 100644 .venv/Lib/site-packages/authlib/oidc/core/util.py create mode 100644 .venv/Lib/site-packages/authlib/oidc/discovery/__init__.py create mode 100644 .venv/Lib/site-packages/authlib/oidc/discovery/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oidc/discovery/__pycache__/models.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oidc/discovery/__pycache__/well_known.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/authlib/oidc/discovery/models.py create mode 100644 .venv/Lib/site-packages/authlib/oidc/discovery/well_known.py create mode 100644 .venv/Lib/site-packages/cffi-1.16.0.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/cffi-1.16.0.dist-info/LICENSE create mode 100644 .venv/Lib/site-packages/cffi-1.16.0.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/cffi-1.16.0.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/cffi-1.16.0.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/cffi-1.16.0.dist-info/entry_points.txt create mode 100644 .venv/Lib/site-packages/cffi-1.16.0.dist-info/top_level.txt create mode 100644 .venv/Lib/site-packages/cffi/__init__.py create mode 100644 .venv/Lib/site-packages/cffi/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cffi/__pycache__/_imp_emulation.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cffi/__pycache__/_shimmed_dist_utils.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cffi/__pycache__/api.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cffi/__pycache__/backend_ctypes.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cffi/__pycache__/cffi_opcode.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cffi/__pycache__/commontypes.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cffi/__pycache__/cparser.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cffi/__pycache__/error.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cffi/__pycache__/ffiplatform.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cffi/__pycache__/lock.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cffi/__pycache__/model.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cffi/__pycache__/pkgconfig.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cffi/__pycache__/recompiler.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cffi/__pycache__/setuptools_ext.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cffi/__pycache__/vengine_cpy.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cffi/__pycache__/vengine_gen.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cffi/__pycache__/verifier.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cffi/_cffi_errors.h create mode 100644 .venv/Lib/site-packages/cffi/_cffi_include.h create mode 100644 .venv/Lib/site-packages/cffi/_embedding.h create mode 100644 .venv/Lib/site-packages/cffi/_imp_emulation.py create mode 100644 .venv/Lib/site-packages/cffi/_shimmed_dist_utils.py create mode 100644 .venv/Lib/site-packages/cffi/api.py create mode 100644 .venv/Lib/site-packages/cffi/backend_ctypes.py create mode 100644 .venv/Lib/site-packages/cffi/cffi_opcode.py create mode 100644 .venv/Lib/site-packages/cffi/commontypes.py create mode 100644 .venv/Lib/site-packages/cffi/cparser.py create mode 100644 .venv/Lib/site-packages/cffi/error.py create mode 100644 .venv/Lib/site-packages/cffi/ffiplatform.py create mode 100644 .venv/Lib/site-packages/cffi/lock.py create mode 100644 .venv/Lib/site-packages/cffi/model.py create mode 100644 .venv/Lib/site-packages/cffi/parse_c_type.h create mode 100644 .venv/Lib/site-packages/cffi/pkgconfig.py create mode 100644 .venv/Lib/site-packages/cffi/recompiler.py create mode 100644 .venv/Lib/site-packages/cffi/setuptools_ext.py create mode 100644 .venv/Lib/site-packages/cffi/vengine_cpy.py create mode 100644 .venv/Lib/site-packages/cffi/vengine_gen.py create mode 100644 .venv/Lib/site-packages/cffi/verifier.py create mode 100644 .venv/Lib/site-packages/cryptography-42.0.1.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/cryptography-42.0.1.dist-info/LICENSE create mode 100644 .venv/Lib/site-packages/cryptography-42.0.1.dist-info/LICENSE.APACHE create mode 100644 .venv/Lib/site-packages/cryptography-42.0.1.dist-info/LICENSE.BSD create mode 100644 .venv/Lib/site-packages/cryptography-42.0.1.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/cryptography-42.0.1.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/cryptography-42.0.1.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/cryptography-42.0.1.dist-info/top_level.txt create mode 100644 .venv/Lib/site-packages/cryptography/__about__.py create mode 100644 .venv/Lib/site-packages/cryptography/__init__.py create mode 100644 .venv/Lib/site-packages/cryptography/__pycache__/__about__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/__pycache__/exceptions.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/__pycache__/fernet.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/__pycache__/utils.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/exceptions.py create mode 100644 .venv/Lib/site-packages/cryptography/fernet.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/__init__.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/__pycache__/_oid.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/_oid.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/backends/__init__.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/backends/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__init__.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__pycache__/aead.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__pycache__/backend.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__pycache__/ciphers.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__pycache__/decode_asn1.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/backends/openssl/aead.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/backends/openssl/backend.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/backends/openssl/ciphers.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/backends/openssl/decode_asn1.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/__init__.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust.pyd create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/__init__.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/_openssl.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/asn1.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/exceptions.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/ocsp.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/aead.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/cmac.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/dh.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/dsa.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ec.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed25519.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed448.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/hashes.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/hmac.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/kdf.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/keys.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/poly1305.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/rsa.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/x25519.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/x448.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/pkcs7.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/x509.pyi create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__init__.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/_conditional.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/binding.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/_conditional.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/binding.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/__init__.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/_asymmetric.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/_cipheralgorithm.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/_serialization.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/cmac.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/constant_time.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/hashes.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/hmac.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/keywrap.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/padding.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/poly1305.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/_asymmetric.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/_cipheralgorithm.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/_serialization.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__init__.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/dh.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/dsa.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ec.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ed25519.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ed448.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/padding.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/rsa.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/types.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/utils.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/x25519.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/x448.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/dh.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ec.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ed25519.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ed448.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/padding.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/rsa.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/types.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/utils.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/x25519.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/x448.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__init__.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/aead.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/algorithms.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/base.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/modes.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/aead.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/algorithms.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/base.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/modes.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/cmac.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/constant_time.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/hashes.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/hmac.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__init__.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/concatkdf.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/hkdf.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/kbkdf.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/pbkdf2.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/scrypt.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/x963kdf.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/concatkdf.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/hkdf.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/kbkdf.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/pbkdf2.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/scrypt.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/x963kdf.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/keywrap.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/padding.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/poly1305.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__init__.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/base.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/pkcs12.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/pkcs7.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/ssh.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/base.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/pkcs12.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/pkcs7.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/ssh.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__init__.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/hotp.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/totp.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/hotp.py create mode 100644 .venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/totp.py create mode 100644 .venv/Lib/site-packages/cryptography/py.typed create mode 100644 .venv/Lib/site-packages/cryptography/utils.py create mode 100644 .venv/Lib/site-packages/cryptography/x509/__init__.py create mode 100644 .venv/Lib/site-packages/cryptography/x509/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/x509/__pycache__/base.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/x509/__pycache__/certificate_transparency.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/x509/__pycache__/extensions.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/x509/__pycache__/general_name.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/x509/__pycache__/name.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/x509/__pycache__/ocsp.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/x509/__pycache__/oid.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/x509/__pycache__/verification.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/cryptography/x509/base.py create mode 100644 .venv/Lib/site-packages/cryptography/x509/certificate_transparency.py create mode 100644 .venv/Lib/site-packages/cryptography/x509/extensions.py create mode 100644 .venv/Lib/site-packages/cryptography/x509/general_name.py create mode 100644 .venv/Lib/site-packages/cryptography/x509/name.py create mode 100644 .venv/Lib/site-packages/cryptography/x509/ocsp.py create mode 100644 .venv/Lib/site-packages/cryptography/x509/oid.py create mode 100644 .venv/Lib/site-packages/cryptography/x509/verification.py create mode 100644 .venv/Lib/site-packages/dotenv/__init__.py create mode 100644 .venv/Lib/site-packages/dotenv/__main__.py create mode 100644 .venv/Lib/site-packages/dotenv/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/dotenv/__pycache__/__main__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/dotenv/__pycache__/cli.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/dotenv/__pycache__/ipython.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/dotenv/__pycache__/main.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/dotenv/__pycache__/parser.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/dotenv/__pycache__/variables.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/dotenv/__pycache__/version.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/dotenv/cli.py create mode 100644 .venv/Lib/site-packages/dotenv/ipython.py create mode 100644 .venv/Lib/site-packages/dotenv/main.py create mode 100644 .venv/Lib/site-packages/dotenv/parser.py create mode 100644 .venv/Lib/site-packages/dotenv/py.typed create mode 100644 .venv/Lib/site-packages/dotenv/variables.py create mode 100644 .venv/Lib/site-packages/dotenv/version.py create mode 100644 .venv/Lib/site-packages/pycparser-2.21.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/pycparser-2.21.dist-info/LICENSE create mode 100644 .venv/Lib/site-packages/pycparser-2.21.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/pycparser-2.21.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/pycparser-2.21.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/pycparser-2.21.dist-info/top_level.txt create mode 100644 .venv/Lib/site-packages/pycparser/__init__.py create mode 100644 .venv/Lib/site-packages/pycparser/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/pycparser/__pycache__/_ast_gen.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/pycparser/__pycache__/_build_tables.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/pycparser/__pycache__/ast_transforms.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/pycparser/__pycache__/c_ast.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/pycparser/__pycache__/c_generator.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/pycparser/__pycache__/c_lexer.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/pycparser/__pycache__/c_parser.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/pycparser/__pycache__/lextab.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/pycparser/__pycache__/plyparser.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/pycparser/__pycache__/yacctab.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/pycparser/_ast_gen.py create mode 100644 .venv/Lib/site-packages/pycparser/_build_tables.py create mode 100644 .venv/Lib/site-packages/pycparser/_c_ast.cfg create mode 100644 .venv/Lib/site-packages/pycparser/ast_transforms.py create mode 100644 .venv/Lib/site-packages/pycparser/c_ast.py create mode 100644 .venv/Lib/site-packages/pycparser/c_generator.py create mode 100644 .venv/Lib/site-packages/pycparser/c_lexer.py create mode 100644 .venv/Lib/site-packages/pycparser/c_parser.py create mode 100644 .venv/Lib/site-packages/pycparser/lextab.py create mode 100644 .venv/Lib/site-packages/pycparser/ply/__init__.py create mode 100644 .venv/Lib/site-packages/pycparser/ply/__pycache__/__init__.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/pycparser/ply/__pycache__/cpp.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/pycparser/ply/__pycache__/ctokens.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/pycparser/ply/__pycache__/lex.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/pycparser/ply/__pycache__/yacc.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/pycparser/ply/__pycache__/ygen.cpython-311.pyc create mode 100644 .venv/Lib/site-packages/pycparser/ply/cpp.py create mode 100644 .venv/Lib/site-packages/pycparser/ply/ctokens.py create mode 100644 .venv/Lib/site-packages/pycparser/ply/lex.py create mode 100644 .venv/Lib/site-packages/pycparser/ply/yacc.py create mode 100644 .venv/Lib/site-packages/pycparser/ply/ygen.py create mode 100644 .venv/Lib/site-packages/pycparser/plyparser.py create mode 100644 .venv/Lib/site-packages/pycparser/yacctab.py create mode 100644 .venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/LICENSE create mode 100644 .venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/REQUESTED create mode 100644 .venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/entry_points.txt create mode 100644 .venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/top_level.txt create mode 100644 .venv/Scripts/dotenv.exe delete mode 100644 server.py create mode 100644 templates/login.html diff --git a/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/INSTALLER b/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/LICENSE b/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/LICENSE new file mode 100644 index 00000000..42441994 --- /dev/null +++ b/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2017, Hsiaoming Yang +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/METADATA b/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/METADATA new file mode 100644 index 00000000..b2beee6f --- /dev/null +++ b/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/METADATA @@ -0,0 +1,104 @@ +Metadata-Version: 2.1 +Name: Authlib +Version: 1.3.0 +Summary: The ultimate Python library in building OAuth and OpenID Connect servers and clients. +Author-email: Hsiaoming Yang +License: BSD-3-Clause +Project-URL: Documentation, https://docs.authlib.org/ +Project-URL: Purchase, https://authlib.org/plans +Project-URL: Issues, https://github.com/lepture/authlib/issues +Project-URL: Source, https://github.com/lepture/authlib +Project-URL: Donate, https://github.com/sponsors/lepture +Project-URL: Blog, https://blog.authlib.org/ +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Console +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Topic :: Security +Classifier: Topic :: Security :: Cryptography +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application +Requires-Python: >=3.8 +Description-Content-Type: text/x-rst +License-File: LICENSE +Requires-Dist: cryptography + +Authlib +======= + +The ultimate Python library in building OAuth and OpenID Connect servers. +JWS, JWK, JWA, JWT are included. + +Useful Links +------------ + +1. Homepage: https://authlib.org/ +2. Documentation: https://docs.authlib.org/ +3. Purchase Commercial License: https://authlib.org/plans +4. Blog: https://blog.authlib.org/ +5. More Repositories: https://github.com/authlib +6. Twitter: https://twitter.com/authlib +7. Donate: https://www.patreon.com/lepture + +Specifications +-------------- + +- RFC5849: The OAuth 1.0 Protocol +- RFC6749: The OAuth 2.0 Authorization Framework +- RFC6750: The OAuth 2.0 Authorization Framework: Bearer Token Usage +- RFC7009: OAuth 2.0 Token Revocation +- RFC7515: JSON Web Signature +- RFC7516: JSON Web Encryption +- RFC7517: JSON Web Key +- RFC7518: JSON Web Algorithms +- RFC7519: JSON Web Token +- RFC7521: Assertion Framework for OAuth 2.0 Client Authentication and Authorization Grants +- RFC7523: JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants +- RFC7591: OAuth 2.0 Dynamic Client Registration Protocol +- RFC7636: Proof Key for Code Exchange by OAuth Public Clients +- RFC7638: JSON Web Key (JWK) Thumbprint +- RFC7662: OAuth 2.0 Token Introspection +- RFC8037: CFRG Elliptic Curve Diffie-Hellman (ECDH) and Signatures in JSON Object Signing and Encryption (JOSE) +- RFC8414: OAuth 2.0 Authorization Server Metadata +- RFC8628: OAuth 2.0 Device Authorization Grant +- OpenID Connect 1.0 +- OpenID Connect Discovery 1.0 +- draft-madden-jose-ecdh-1pu-04: Public Key Authenticated Encryption for JOSE: ECDH-1PU + +Implementations +--------------- + +- Requests OAuth 1 Session +- Requests OAuth 2 Session +- Requests Assertion Session +- HTTPX OAuth 1 Session +- HTTPX OAuth 2 Session +- HTTPX Assertion Session +- Flask OAuth 1/2 Client +- Django OAuth 1/2 Client +- Starlette OAuth 1/2 Client +- Flask OAuth 1.0 Server +- Flask OAuth 2.0 Server +- Flask OpenID Connect 1.0 +- Django OAuth 1.0 Server +- Django OAuth 2.0 Server +- Django OpenID Connect 1.0 + +License +------- + +Authlib is licensed under BSD. Please see LICENSE for licensing details. + +If this license does not fit your company, consider to purchase a commercial +license. Find more information on `Authlib Plans`_. + +.. _`Authlib Plans`: https://authlib.org/plans diff --git a/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/RECORD b/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/RECORD new file mode 100644 index 00000000..a975ebaa --- /dev/null +++ b/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/RECORD @@ -0,0 +1,387 @@ +Authlib-1.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +Authlib-1.3.0.dist-info/LICENSE,sha256=jhtIUY3pxs0Ay0jH_luAI_2Q1VUsoS6-c2Kg3zDdvkU,1514 +Authlib-1.3.0.dist-info/METADATA,sha256=_uPrSFp-N_CnFcdce_ly9u374GhUS8V56C_2tNPI5IU,3756 +Authlib-1.3.0.dist-info/RECORD,, +Authlib-1.3.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +Authlib-1.3.0.dist-info/WHEEL,sha256=-G_t0oGuE7UD0DrSpVZnq1hHMBV9DD2XkS5v7XpmTnk,110 +Authlib-1.3.0.dist-info/top_level.txt,sha256=Rj3mJn0jhRuCs6x7ysI6hYE2PePbuxey6y6jswadAEY,8 +authlib/__init__.py,sha256=CoObQJQX-YGSJy-HWbJPtK6XbpfKDBc21DJwjhLnIcM,476 +authlib/__pycache__/__init__.cpython-311.pyc,, +authlib/__pycache__/consts.cpython-311.pyc,, +authlib/__pycache__/deprecate.cpython-311.pyc,, +authlib/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +authlib/common/__pycache__/__init__.cpython-311.pyc,, +authlib/common/__pycache__/encoding.cpython-311.pyc,, +authlib/common/__pycache__/errors.cpython-311.pyc,, +authlib/common/__pycache__/security.cpython-311.pyc,, +authlib/common/__pycache__/urls.cpython-311.pyc,, +authlib/common/encoding.py,sha256=sdiaZwuXZI-ruNPGAhJ0oIuZTcrzdawneS_PoJAnHYk,1546 +authlib/common/errors.py,sha256=z8kGl0qRBnimrMYqVgi1aqLsqSng8YaMtcqCy6MHff8,1684 +authlib/common/security.py,sha256=2xcxtJWVE26kosNJTWtnN3skeSzm3Jjtpm4wxoTCBYs,493 +authlib/common/urls.py,sha256=gUpc_VB9emhmCE0EunlxDiQHHZhegGYdLVPT-qoEkco,4501 +authlib/consts.py,sha256=WZWJbuAh8iBsbBm-KFWNYuT3bVDUtzMpNKydkisu3qw,300 +authlib/deprecate.py,sha256=dIjr5VmDMK3bua0cOzJh0Q2RAlAtMhW6iM6ENIynIQ8,481 +authlib/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +authlib/integrations/__pycache__/__init__.cpython-311.pyc,, +authlib/integrations/base_client/__init__.py,sha256=xCaZt-rH5n4g0tBVgrM4KKMzWUQ6NHUcLIHwlIuKqMM,653 +authlib/integrations/base_client/__pycache__/__init__.cpython-311.pyc,, +authlib/integrations/base_client/__pycache__/async_app.cpython-311.pyc,, +authlib/integrations/base_client/__pycache__/async_openid.cpython-311.pyc,, +authlib/integrations/base_client/__pycache__/errors.cpython-311.pyc,, +authlib/integrations/base_client/__pycache__/framework_integration.cpython-311.pyc,, +authlib/integrations/base_client/__pycache__/registry.cpython-311.pyc,, +authlib/integrations/base_client/__pycache__/sync_app.cpython-311.pyc,, +authlib/integrations/base_client/__pycache__/sync_openid.cpython-311.pyc,, +authlib/integrations/base_client/async_app.py,sha256=3MbucTGkyEBz8W7SIvJSwYxdGR_8wquxNKee8BHt4i8,5847 +authlib/integrations/base_client/async_openid.py,sha256=-OZl3g_8EYJNlLxCukcPAvOPd-o-OWP9b-updMs6Z-c,2803 +authlib/integrations/base_client/errors.py,sha256=fwXW7ldF-TeCIHeANGWYqv5hhaFpXzLLsGRUBwgcy4c,632 +authlib/integrations/base_client/framework_integration.py,sha256=12rBh8a-cj2r0mJkFKhREH49gv2D2v5aF1UZSUAD430,1871 +authlib/integrations/base_client/registry.py,sha256=FAjZBN0n_e-3MbC2ZYCUSUxeHCrKSdoAE21taWxSAeA,4273 +authlib/integrations/base_client/sync_app.py,sha256=eZajg-ruTMgQAIeaANMqOlYvzA8qqyzH1S7vvL3jx6w,12408 +authlib/integrations/base_client/sync_openid.py,sha256=zZZ9vp0M_w8xpZU3tRahN715Q26tfwC-JCV5WtbMUcM,2721 +authlib/integrations/django_client/__init__.py,sha256=ff_Kol2-pT-7E0zav2A6tkgqMT1YYLpmVuNaKh-Fz5g,458 +authlib/integrations/django_client/__pycache__/__init__.cpython-311.pyc,, +authlib/integrations/django_client/__pycache__/apps.cpython-311.pyc,, +authlib/integrations/django_client/__pycache__/integration.cpython-311.pyc,, +authlib/integrations/django_client/apps.py,sha256=AR7-2aa1xMJj6UX_dl8PreAVw_H_rxABPV9paqioOuw,3334 +authlib/integrations/django_client/integration.py,sha256=TfgtYs2X_IwismSdX8TI73EcpoYCfjS9OovOdEP8XLA,650 +authlib/integrations/django_oauth1/__init__.py,sha256=yp66WLC43YdsICGgVDbu6AfIRyPR17M43umIUcxjH10,221 +authlib/integrations/django_oauth1/__pycache__/__init__.cpython-311.pyc,, +authlib/integrations/django_oauth1/__pycache__/authorization_server.cpython-311.pyc,, +authlib/integrations/django_oauth1/__pycache__/nonce.cpython-311.pyc,, +authlib/integrations/django_oauth1/__pycache__/resource_protector.cpython-311.pyc,, +authlib/integrations/django_oauth1/authorization_server.py,sha256=UKkJuE4nwTPNrC8emL5ENqxwP1t3-Qu7kZn6c59zdng,4536 +authlib/integrations/django_oauth1/nonce.py,sha256=m6j4FWsSeQ1S-LJEgF4BF0TPGRZQuseOumkrbuF6KhY,396 +authlib/integrations/django_oauth1/resource_protector.py,sha256=TL1kRvuuF91kZBBe4FZzo7nY0iOKpGWIdjKvdlOcXAY,2343 +authlib/integrations/django_oauth2/__init__.py,sha256=HGqxRud5D9EGZIthXmySYhB7d-90qzZlXZDrd4mPHnQ,278 +authlib/integrations/django_oauth2/__pycache__/__init__.cpython-311.pyc,, +authlib/integrations/django_oauth2/__pycache__/authorization_server.cpython-311.pyc,, +authlib/integrations/django_oauth2/__pycache__/endpoints.cpython-311.pyc,, +authlib/integrations/django_oauth2/__pycache__/requests.cpython-311.pyc,, +authlib/integrations/django_oauth2/__pycache__/resource_protector.cpython-311.pyc,, +authlib/integrations/django_oauth2/__pycache__/signals.cpython-311.pyc,, +authlib/integrations/django_oauth2/authorization_server.py,sha256=rtlQlDyeNME3Hdv4Tnu5tYBZ2zJ9GUn-kHEvNCF5Jh8,4388 +authlib/integrations/django_oauth2/endpoints.py,sha256=lKkDmQklHNTCXK_L-6-_PrHa6XvnFBT7a2BAciYkv7o,1853 +authlib/integrations/django_oauth2/requests.py,sha256=_KpI8ecABAZ026y3OcjyNfYNK1MyiDhVH5cFIO5rrSs,1023 +authlib/integrations/django_oauth2/resource_protector.py,sha256=O3Snq0LO4divy6sZwDjh4UoMoDVn3qhLvGILaqNUWnM,2595 +authlib/integrations/django_oauth2/signals.py,sha256=8SlnOsi1IuBPmrCi7dOLXK70N_m9y6B3msjMCtBMnSk,236 +authlib/integrations/flask_client/__init__.py,sha256=DCSIvVck7aBh-zDiGILsYJp_pJSl1qHzR3p-pDGfhNk,1677 +authlib/integrations/flask_client/__pycache__/__init__.cpython-311.pyc,, +authlib/integrations/flask_client/__pycache__/apps.cpython-311.pyc,, +authlib/integrations/flask_client/__pycache__/integration.cpython-311.pyc,, +authlib/integrations/flask_client/apps.py,sha256=4LWY81JpXgg8C5TliVOsObegPqgzZdt9Jyr9rJx2x0w,3607 +authlib/integrations/flask_client/integration.py,sha256=T_O0-YZbezOvvyJUJZKhW_lyHTbSkEZvdQkAGwHLyjY,805 +authlib/integrations/flask_oauth1/__init__.py,sha256=PGDVdNJ9oGs5bYJr7oGdpQX0tE2nQJNcHJ8t-SxEAEY,260 +authlib/integrations/flask_oauth1/__pycache__/__init__.cpython-311.pyc,, +authlib/integrations/flask_oauth1/__pycache__/authorization_server.cpython-311.pyc,, +authlib/integrations/flask_oauth1/__pycache__/cache.cpython-311.pyc,, +authlib/integrations/flask_oauth1/__pycache__/resource_protector.cpython-311.pyc,, +authlib/integrations/flask_oauth1/authorization_server.py,sha256=qa0C73Qu7lEOM24-dYQ6wOqmXoHiSdlwxcmtqTMYNug,6299 +authlib/integrations/flask_oauth1/cache.py,sha256=x1bOuGhHKrCUO0X2XrR80f898ca8sM2edQfT6nuDFwY,2996 +authlib/integrations/flask_oauth1/resource_protector.py,sha256=feMGEpwRI5DfgJjJhyumI3XdoaAEjhZHzId_-sFDkBE,3805 +authlib/integrations/flask_oauth2/__init__.py,sha256=8xa6R7Otk9DSHzKFcyGeDv-H7OLUbFwtF73ybpe9jNY,243 +authlib/integrations/flask_oauth2/__pycache__/__init__.cpython-311.pyc,, +authlib/integrations/flask_oauth2/__pycache__/authorization_server.cpython-311.pyc,, +authlib/integrations/flask_oauth2/__pycache__/errors.cpython-311.pyc,, +authlib/integrations/flask_oauth2/__pycache__/requests.cpython-311.pyc,, +authlib/integrations/flask_oauth2/__pycache__/resource_protector.cpython-311.pyc,, +authlib/integrations/flask_oauth2/__pycache__/signals.cpython-311.pyc,, +authlib/integrations/flask_oauth2/authorization_server.py,sha256=Lz4b_77aGIJ7Rmh3LxWQzWZeyWhtKpFpjBzy18JRibI,5859 +authlib/integrations/flask_oauth2/errors.py,sha256=d4YT-I_atPUQjV8ohrHCossYpTvErOscXwBhCyLzidA,1090 +authlib/integrations/flask_oauth2/requests.py,sha256=Z78A_rCTmmJW6FJ-PfWQTe5sdYHW3hYZg2s4SYgDkIk,765 +authlib/integrations/flask_oauth2/resource_protector.py,sha256=Kpgw5UAy1dPXv3T2f5o2KbPXO6naRmsc25KL3VuMkC4,3843 +authlib/integrations/flask_oauth2/signals.py,sha256=CKao8F778CkUzl7mKjF96smr7WKJ0nfxBT0onVFq10Y,341 +authlib/integrations/httpx_client/__init__.py,sha256=zuO_FIAdLEJ9Ch25kTa-Nsyi2gqkPuAsXdHAeYc0nBI,804 +authlib/integrations/httpx_client/__pycache__/__init__.cpython-311.pyc,, +authlib/integrations/httpx_client/__pycache__/assertion_client.cpython-311.pyc,, +authlib/integrations/httpx_client/__pycache__/oauth1_client.cpython-311.pyc,, +authlib/integrations/httpx_client/__pycache__/oauth2_client.cpython-311.pyc,, +authlib/integrations/httpx_client/__pycache__/utils.cpython-311.pyc,, +authlib/integrations/httpx_client/assertion_client.py,sha256=1T2ZEM3cboubUu2Zme-6KKTY1Y06BCIQMhHSQ_LC6ZY,3179 +authlib/integrations/httpx_client/oauth1_client.py,sha256=rkb-wwh3Oqryj3QZop9bo3q0td2OjFptf6rDX5VUUBY,4084 +authlib/integrations/httpx_client/oauth2_client.py,sha256=d7VLXPo_6Gboko6jVn9ooFRVFJWNKm9bLHKcsP_lzlY,8439 +authlib/integrations/httpx_client/utils.py,sha256=XF8d4xz4d7tDoaaq3LQ3GZonED1_EtW8zH_FoTcUPL4,888 +authlib/integrations/requests_client/__init__.py,sha256=Nco-Q1_wOswQ9qCgBgh0rVWPYO9ddEKnlnnJ9rGZE_U,652 +authlib/integrations/requests_client/__pycache__/__init__.cpython-311.pyc,, +authlib/integrations/requests_client/__pycache__/assertion_session.cpython-311.pyc,, +authlib/integrations/requests_client/__pycache__/oauth1_session.cpython-311.pyc,, +authlib/integrations/requests_client/__pycache__/oauth2_session.cpython-311.pyc,, +authlib/integrations/requests_client/__pycache__/utils.cpython-311.pyc,, +authlib/integrations/requests_client/assertion_session.py,sha256=8TAEs9s_SuB1-LymwOgfkxUOgEWCWX0Lp7eagbw3xZo,1832 +authlib/integrations/requests_client/oauth1_session.py,sha256=aXC3vFLy4ytV8G3yL-on6dJitNfdKmkttcItTHTejfU,2209 +authlib/integrations/requests_client/oauth2_session.py,sha256=4USZnWGgw8v-67Os0y17UeNi0n2JjONvRoFvtbMYAv4,4498 +authlib/integrations/requests_client/utils.py,sha256=4ohGF-9JUR9Ayw63glEednsZSbscrSD4Rx0BPkPrSeA,274 +authlib/integrations/sqla_oauth2/__init__.py,sha256=d8g3ipiiPtyk1JnmTDzeAKCdm-ozjNoERDWLEkpBgL8,548 +authlib/integrations/sqla_oauth2/__pycache__/__init__.cpython-311.pyc,, +authlib/integrations/sqla_oauth2/__pycache__/client_mixin.cpython-311.pyc,, +authlib/integrations/sqla_oauth2/__pycache__/functions.cpython-311.pyc,, +authlib/integrations/sqla_oauth2/__pycache__/tokens_mixins.cpython-311.pyc,, +authlib/integrations/sqla_oauth2/client_mixin.py,sha256=qxoJLpnH3ncdvQPYnk8HoqllOoiUZAl_md3RteELQpQ,4116 +authlib/integrations/sqla_oauth2/functions.py,sha256=0smHFpiQ6srSLR-ynLCmbFIq7iPvbBjoQUDibtD_4e8,3195 +authlib/integrations/sqla_oauth2/tokens_mixins.py,sha256=9cBNIUxKLsaP8DTkOKlkZQ1m5guxeOnpJ9t-K8Kuy0c,2008 +authlib/integrations/starlette_client/__init__.py,sha256=3bOTtevT4LmMurKF6dz0HusPbiVrPjBLVRuf6P0wHXk,666 +authlib/integrations/starlette_client/__pycache__/__init__.cpython-311.pyc,, +authlib/integrations/starlette_client/__pycache__/apps.cpython-311.pyc,, +authlib/integrations/starlette_client/__pycache__/integration.cpython-311.pyc,, +authlib/integrations/starlette_client/apps.py,sha256=BHO3DRhLv8x14DAF6CCJKaTVI6Lr9WKh4vIm4eTJPjY,3556 +authlib/integrations/starlette_client/integration.py,sha256=b2ZUKcX_L9P3DA7tdeSP3mRCmiPfzwUwVzp9cepsBA0,1964 +authlib/jose/__init__.py,sha256=qpIwbdODthy50cit_FeHECvwRGd7pIABiYEA4aiFV48,1399 +authlib/jose/__pycache__/__init__.cpython-311.pyc,, +authlib/jose/__pycache__/errors.cpython-311.pyc,, +authlib/jose/__pycache__/jwk.cpython-311.pyc,, +authlib/jose/__pycache__/util.cpython-311.pyc,, +authlib/jose/drafts/__init__.py,sha256=A--_H-kGg_s_Yf4m_P3Whb7HRQbKynDGtQYZlnOtkFc,518 +authlib/jose/drafts/__pycache__/__init__.cpython-311.pyc,, +authlib/jose/drafts/__pycache__/_jwe_algorithms.cpython-311.pyc,, +authlib/jose/drafts/__pycache__/_jwe_enc_cryptodome.cpython-311.pyc,, +authlib/jose/drafts/__pycache__/_jwe_enc_cryptography.cpython-311.pyc,, +authlib/jose/drafts/_jwe_algorithms.py,sha256=zbDaWazb4HdYtQmstf0MofDDaMexVwqkmnfIPfc6luY,6917 +authlib/jose/drafts/_jwe_enc_cryptodome.py,sha256=a4Vb0AUZWZWlCoTKqOfBaLZ-o1D1bgS0hKuBKJT7Kqo,1860 +authlib/jose/drafts/_jwe_enc_cryptography.py,sha256=N2Bm9zp7MMSe_kbPwjyUAyD3MMOTj5BmpEUc1k_IqUw,1743 +authlib/jose/errors.py,sha256=j-vg5TV7uiIS-xBgq-0pwxuerCDV31n5VKerCsddJR4,2977 +authlib/jose/jwk.py,sha256=VZiMATxt4UPyU6spf7wKE0rwql4udvl3jZqW85Endwo,490 +authlib/jose/rfc7515/__init__.py,sha256=0NhWGkry69LiJH6cAkwIUNmQUpuGh463TNwIpoQjtE4,360 +authlib/jose/rfc7515/__pycache__/__init__.cpython-311.pyc,, +authlib/jose/rfc7515/__pycache__/jws.cpython-311.pyc,, +authlib/jose/rfc7515/__pycache__/models.cpython-311.pyc,, +authlib/jose/rfc7515/jws.py,sha256=0JEEGLkI6vsERYdViRGRrZBQD9hJUS9j8OPoOxD0-2c,11270 +authlib/jose/rfc7515/models.py,sha256=B3HygZbTamiXc-rhnncMwCHL1LlblU69TCkyV2gezTo,2445 +authlib/jose/rfc7516/__init__.py,sha256=SCAxvSIWD0NF2_Gcq1BrIkKx3Bqr_6WYhFpDFt3AQ6A,465 +authlib/jose/rfc7516/__pycache__/__init__.cpython-311.pyc,, +authlib/jose/rfc7516/__pycache__/jwe.cpython-311.pyc,, +authlib/jose/rfc7516/__pycache__/models.cpython-311.pyc,, +authlib/jose/rfc7516/jwe.py,sha256=j26ji9QSRTuWbH3E3vz10YtDzIoteqZ5bY5VDA7Vp7U,29706 +authlib/jose/rfc7516/models.py,sha256=RdtLB8_KzxZ35DcgkXFCy25rkXEFp9tg22m5oqeBv-A,4341 +authlib/jose/rfc7517/__init__.py,sha256=LfowmYyTdC0t5wB6ptJs45Qkj-6nRmHmhRONAh-UFxY,424 +authlib/jose/rfc7517/__pycache__/__init__.cpython-311.pyc,, +authlib/jose/rfc7517/__pycache__/_cryptography_key.cpython-311.pyc,, +authlib/jose/rfc7517/__pycache__/asymmetric_key.cpython-311.pyc,, +authlib/jose/rfc7517/__pycache__/base_key.cpython-311.pyc,, +authlib/jose/rfc7517/__pycache__/jwk.cpython-311.pyc,, +authlib/jose/rfc7517/__pycache__/key_set.cpython-311.pyc,, +authlib/jose/rfc7517/_cryptography_key.py,sha256=1-EQ1YD7ZR7Gp7FBntrWEN-76Su_vlunuzC77VPJ_sg,1257 +authlib/jose/rfc7517/asymmetric_key.py,sha256=cP5ka_7Ez5gUvVsb54WqVsuuSLDxXGwMsqGqXAvTQlw,6229 +authlib/jose/rfc7517/base_key.py,sha256=udNnaEw7_pHCfUPNc2SyfgVwZDm32DWH7p3J3Ssgk80,3261 +authlib/jose/rfc7517/jwk.py,sha256=xUPIgYiAuyo7kDHFuVfaKeyY3MY9tJURfCIMZMo70o0,2042 +authlib/jose/rfc7517/key_set.py,sha256=CAStzaaCCq5IcPwc_6I3lqYWJdhw1E_JuMqouAF0IW8,883 +authlib/jose/rfc7518/__init__.py,sha256=69w8-62wS4DJNaCCHBUYiueiORtRl6Mlek36CNoTKOQ,879 +authlib/jose/rfc7518/__pycache__/__init__.cpython-311.pyc,, +authlib/jose/rfc7518/__pycache__/ec_key.cpython-311.pyc,, +authlib/jose/rfc7518/__pycache__/jwe_algs.cpython-311.pyc,, +authlib/jose/rfc7518/__pycache__/jwe_encs.cpython-311.pyc,, +authlib/jose/rfc7518/__pycache__/jwe_zips.cpython-311.pyc,, +authlib/jose/rfc7518/__pycache__/jws_algs.cpython-311.pyc,, +authlib/jose/rfc7518/__pycache__/oct_key.cpython-311.pyc,, +authlib/jose/rfc7518/__pycache__/rsa_key.cpython-311.pyc,, +authlib/jose/rfc7518/__pycache__/util.cpython-311.pyc,, +authlib/jose/rfc7518/ec_key.py,sha256=_cot3xwrpuER_tj8eiHkx-L2EJHnYSy4iWieD0RvYKo,3511 +authlib/jose/rfc7518/jwe_algs.py,sha256=yOgfh7WYo7MCHENw4EiucP9ep5nbCd1-zKmyUSbn6Ko,11311 +authlib/jose/rfc7518/jwe_encs.py,sha256=0Mjl9wD3VYpc8ApgjWF_T3n7m2S-qtNH-cnyI-P8pAw,5047 +authlib/jose/rfc7518/jwe_zips.py,sha256=9Qron3QW-1GHqoZHGa6EjLF1VAMMlB2gvHlr2anWqtY,561 +authlib/jose/rfc7518/jws_algs.py,sha256=dfWu1QwmMtlJDB4J1JFnmKxYbCzXNmicn8djnKKNqMM,6493 +authlib/jose/rfc7518/oct_key.py,sha256=gegg3PLgdDgC9J87h4oJ5hNf06j_j-nf4C6cTI-N6yU,2375 +authlib/jose/rfc7518/rsa_key.py,sha256=hxCJAs-Ljl_RRv6D5ezAhQCpjwYhp2OU3zXtCqfO_6k,4192 +authlib/jose/rfc7518/util.py,sha256=LpOgX10QHuqss6x015QPgApTlnYJ_cQyd0hzeYALnaE,265 +authlib/jose/rfc7519/__init__.py,sha256=vJKdsUGkdKlGBKctdh5CLM2jc20903rIfAlsHjbr-hA,309 +authlib/jose/rfc7519/__pycache__/__init__.cpython-311.pyc,, +authlib/jose/rfc7519/__pycache__/claims.cpython-311.pyc,, +authlib/jose/rfc7519/__pycache__/jwt.cpython-311.pyc,, +authlib/jose/rfc7519/claims.py,sha256=CCm4EJiv_BKxaLFhc-34sH5cIQ6Y960I1yRaB3d9_vM,8709 +authlib/jose/rfc7519/jwt.py,sha256=myFXsrFfQLV6xxsOAVv--tQF4FuwhLtvCajZtRcIKSs,5950 +authlib/jose/rfc8037/__init__.py,sha256=MV25hs0RY6HU0pE5UKB2hmRI0Avv-V8BaPtNxIshh0A,119 +authlib/jose/rfc8037/__pycache__/__init__.cpython-311.pyc,, +authlib/jose/rfc8037/__pycache__/jws_eddsa.cpython-311.pyc,, +authlib/jose/rfc8037/__pycache__/okp_key.cpython-311.pyc,, +authlib/jose/rfc8037/jws_eddsa.py,sha256=dpg6ZKOdpqGcp582mP5yqsRLlnC81y_Mnl3xL0_tgLQ,716 +authlib/jose/rfc8037/okp_key.py,sha256=SlpI-u0J0l1K0J5rh1L9g7yiUqEn6YTpmoJc7tpRmhw,3560 +authlib/jose/util.py,sha256=eZGduiUbhgqYYxzjT-b1OaKZFTTICZE16Sq1UpyBK48,1065 +authlib/oauth1/__init__.py,sha256=8c5_O3G8lWOUqd3NgWR8CGpCnKEubMA4jeVNHocRQvQ,735 +authlib/oauth1/__pycache__/__init__.cpython-311.pyc,, +authlib/oauth1/__pycache__/client.cpython-311.pyc,, +authlib/oauth1/__pycache__/errors.cpython-311.pyc,, +authlib/oauth1/client.py,sha256=Vyo3cfAzU1f1WavJ-WosZy3B_eV0RShW_19sx1kc5I8,6524 +authlib/oauth1/errors.py,sha256=pg0NaUgENjfTN_ba50_yQB9aSNe5Mte5MDlikFuypBY,46 +authlib/oauth1/rfc5849/__init__.py,sha256=S4rdtQiDd83QsR1hBqdsvuI-VgmgoG7rFuJH2fLP_K4,1036 +authlib/oauth1/rfc5849/__pycache__/__init__.cpython-311.pyc,, +authlib/oauth1/rfc5849/__pycache__/authorization_server.cpython-311.pyc,, +authlib/oauth1/rfc5849/__pycache__/base_server.cpython-311.pyc,, +authlib/oauth1/rfc5849/__pycache__/client_auth.cpython-311.pyc,, +authlib/oauth1/rfc5849/__pycache__/errors.cpython-311.pyc,, +authlib/oauth1/rfc5849/__pycache__/models.cpython-311.pyc,, +authlib/oauth1/rfc5849/__pycache__/parameters.cpython-311.pyc,, +authlib/oauth1/rfc5849/__pycache__/resource_protector.cpython-311.pyc,, +authlib/oauth1/rfc5849/__pycache__/rsa.cpython-311.pyc,, +authlib/oauth1/rfc5849/__pycache__/signature.cpython-311.pyc,, +authlib/oauth1/rfc5849/__pycache__/util.cpython-311.pyc,, +authlib/oauth1/rfc5849/__pycache__/wrapper.cpython-311.pyc,, +authlib/oauth1/rfc5849/authorization_server.py,sha256=nHnxaNgOfTZ0FwnFXe0--A81-rgFTBoT72OSDmjzZl8,13869 +authlib/oauth1/rfc5849/base_server.py,sha256=-9Il95qaOhoFEQYJPkSMqQailAfQRYBtbdt1b0dZagc,3849 +authlib/oauth1/rfc5849/client_auth.py,sha256=SnCp8R50CAJxyHMtkuYN5ZvbHJcLfnldctVaZtz9hnY,6920 +authlib/oauth1/rfc5849/errors.py,sha256=z7LM1IMKzzTb3vnjRziRJk1tH0dQZm1axHnw8DXKXtA,2303 +authlib/oauth1/rfc5849/models.py,sha256=qdNruenkQVjrOjRkPku4EtU7ak3giIpxwirrRJd8Hi0,3418 +authlib/oauth1/rfc5849/parameters.py,sha256=bHgF_EwyJqWi1rvqYsbDKWf9I7z5RJh1OUpNvARHYEg,3455 +authlib/oauth1/rfc5849/resource_protector.py,sha256=v4EsTBnqYAQMarwukpYmgiyT3J9khnp8Apj6n_RRabI,1258 +authlib/oauth1/rfc5849/rsa.py,sha256=z2cx8e-p2pdvzx_WQm9mcMzkGfsBJniWoy6SLn6XZa4,896 +authlib/oauth1/rfc5849/signature.py,sha256=z1xPJmbA19zXJsfOdHSUOdIjAeMYUauSJm3Q1COvnpY,14123 +authlib/oauth1/rfc5849/util.py,sha256=89kP-xwQHop8SaBjCEkppxzYO7GQFbmi3ekVyI-zFvE,136 +authlib/oauth1/rfc5849/wrapper.py,sha256=FCyqlpSnCmNT5U0H_cM2yqkdTALoRLFnOu409xUBOQ0,3945 +authlib/oauth2/__init__.py,sha256=SlhZAaE8Tudl1W5KE57rfitY-9lLSvHJa02blVg9kJo,423 +authlib/oauth2/__pycache__/__init__.cpython-311.pyc,, +authlib/oauth2/__pycache__/auth.cpython-311.pyc,, +authlib/oauth2/__pycache__/base.cpython-311.pyc,, +authlib/oauth2/__pycache__/client.cpython-311.pyc,, +authlib/oauth2/auth.py,sha256=n-QNzkXpy6uh6vDwpqDMhvMiBjE0n2Fv7PX8pVO6R6Q,3484 +authlib/oauth2/base.py,sha256=cadG08-t_9mhgwzdo73bLeAa1Qvbw3qj4j-g1tbl6uo,958 +authlib/oauth2/client.py,sha256=2betIXTZq9WZGgrW8x5j87Z5lPZDuNUtKh3wEuO3z0w,17626 +authlib/oauth2/rfc6749/__init__.py,sha256=2WVrM30q6NM-DbUjEX2wUwqJwrR0nBr-9HFvjP80b5A,2323 +authlib/oauth2/rfc6749/__pycache__/__init__.cpython-311.pyc,, +authlib/oauth2/rfc6749/__pycache__/authenticate_client.cpython-311.pyc,, +authlib/oauth2/rfc6749/__pycache__/authorization_server.cpython-311.pyc,, +authlib/oauth2/rfc6749/__pycache__/errors.cpython-311.pyc,, +authlib/oauth2/rfc6749/__pycache__/models.cpython-311.pyc,, +authlib/oauth2/rfc6749/__pycache__/parameters.cpython-311.pyc,, +authlib/oauth2/rfc6749/__pycache__/requests.cpython-311.pyc,, +authlib/oauth2/rfc6749/__pycache__/resource_protector.cpython-311.pyc,, +authlib/oauth2/rfc6749/__pycache__/token_endpoint.cpython-311.pyc,, +authlib/oauth2/rfc6749/__pycache__/util.cpython-311.pyc,, +authlib/oauth2/rfc6749/__pycache__/wrappers.cpython-311.pyc,, +authlib/oauth2/rfc6749/authenticate_client.py,sha256=8ZmUuxuodBQeRe2Z4vMXi_OdPjTJbbnSnY7V8ODNNZ4,3748 +authlib/oauth2/rfc6749/authorization_server.py,sha256=u4D4_hN9G8Zw3q_qKIUhOoeoQVrE5E3YGpaHyWZhEAk,11898 +authlib/oauth2/rfc6749/errors.py,sha256=J93QcmMsS_eBgsBa_P4wepkAw87C7ZDW8-JGvc3X6c8,7371 +authlib/oauth2/rfc6749/grants/__init__.py,sha256=jJZOtFgyBztuIGQxcuK1qtvnR3hWRDU-G59RuyWmqKI,1314 +authlib/oauth2/rfc6749/grants/__pycache__/__init__.cpython-311.pyc,, +authlib/oauth2/rfc6749/grants/__pycache__/authorization_code.cpython-311.pyc,, +authlib/oauth2/rfc6749/grants/__pycache__/base.cpython-311.pyc,, +authlib/oauth2/rfc6749/grants/__pycache__/client_credentials.cpython-311.pyc,, +authlib/oauth2/rfc6749/grants/__pycache__/implicit.cpython-311.pyc,, +authlib/oauth2/rfc6749/grants/__pycache__/refresh_token.cpython-311.pyc,, +authlib/oauth2/rfc6749/grants/__pycache__/resource_owner_password_credentials.cpython-311.pyc,, +authlib/oauth2/rfc6749/grants/authorization_code.py,sha256=ktdVV-2_Mp5tl7TTSj2Jxx4xpV53Mmouzb0APZmmaS8,15367 +authlib/oauth2/rfc6749/grants/base.py,sha256=IQpjcs1CtiUOkJIkGb1T-oWIlKC8NfHb4toGwNxGXsg,5132 +authlib/oauth2/rfc6749/grants/client_credentials.py,sha256=OeG_V5aR-oHxkpj5ejOo9pqfa7wu1rKRCzUZ6F9ukJk,3892 +authlib/oauth2/rfc6749/grants/implicit.py,sha256=qNBYKp8GG3sNLZSfC1VL6xRiloTXDl3c1qPXsGf3XF8,9297 +authlib/oauth2/rfc6749/grants/refresh_token.py,sha256=fBAcFH35PhdW15rkQwpK_tH88JdOCRH7XFX8vcfLRZY,6432 +authlib/oauth2/rfc6749/grants/resource_owner_password_credentials.py,sha256=bmOAvYmjEhOlV77xsKQy7JndZNspfaeYkQXUGVao0Ak,5755 +authlib/oauth2/rfc6749/models.py,sha256=lpqMhIwZbnEJazleH4cM3G3jQh14Zs5Sx_csuPy1Z64,7502 +authlib/oauth2/rfc6749/parameters.py,sha256=qjvtW7-APiQ91MVm4cu0LzHNTNFC_3HLZ44uxhlZzog,8308 +authlib/oauth2/rfc6749/requests.py,sha256=LWUOIkySStPI0J_nDm2gHMa4QdUa7Vmeqwre1XIYzgs,2148 +authlib/oauth2/rfc6749/resource_protector.py,sha256=G62crN3HobWrU9DnSNm3iEKXls2cutvpkSEdXfqP_Pg,5309 +authlib/oauth2/rfc6749/token_endpoint.py,sha256=IUx79XxDS12s3QHQukzCwqXS3s1K9l3OrkvlbApnLS0,1103 +authlib/oauth2/rfc6749/util.py,sha256=xzebTUJciyJ9qy1jrYqiXfNBq6GfqCkb9Ok0XMoPWFc,1122 +authlib/oauth2/rfc6749/wrappers.py,sha256=USYF6s4Enpgk883Ye3-vg7_0-2iX7fgeW0-ZRG2kDQE,688 +authlib/oauth2/rfc6750/__init__.py,sha256=NmL2KnczR-sddyzk3lZAnFT1Aj5nJ21B77W05gMLoVU,635 +authlib/oauth2/rfc6750/__pycache__/__init__.cpython-311.pyc,, +authlib/oauth2/rfc6750/__pycache__/errors.cpython-311.pyc,, +authlib/oauth2/rfc6750/__pycache__/parameters.cpython-311.pyc,, +authlib/oauth2/rfc6750/__pycache__/token.cpython-311.pyc,, +authlib/oauth2/rfc6750/__pycache__/validator.cpython-311.pyc,, +authlib/oauth2/rfc6750/errors.py,sha256=8jmPrtinFNL3qkxuTlKWscsWmVjdUhYPNWYOZXes90g,2827 +authlib/oauth2/rfc6750/parameters.py,sha256=-9xyt87e5uHFcjvibmYZN-CIEvxy105Hzt4VaHJ6ICI,1204 +authlib/oauth2/rfc6750/token.py,sha256=5ciVR8G3AR0xqCDPTHP858UViaE_qhA5rKkjk0vcA0E,3350 +authlib/oauth2/rfc6750/validator.py,sha256=Nb1Tg_uz5ZBWRZqzbS0Ag3_zq0GlznA0YkTGSP7TBc8,1377 +authlib/oauth2/rfc7009/__init__.py,sha256=kXO-Miq9N7fFStVJp6uqRgbleitHc_DJII5QyDCvQ10,353 +authlib/oauth2/rfc7009/__pycache__/__init__.cpython-311.pyc,, +authlib/oauth2/rfc7009/__pycache__/parameters.cpython-311.pyc,, +authlib/oauth2/rfc7009/__pycache__/revocation.cpython-311.pyc,, +authlib/oauth2/rfc7009/parameters.py,sha256=klTaHudte5Oncfw6M5Mr6LL9Y-cVnN29Th1ix-uVYAU,854 +authlib/oauth2/rfc7009/revocation.py,sha256=VTA6JLVKlyedN6SUlHO-_v0J0MGU8r7jVxPLgnFpy40,4061 +authlib/oauth2/rfc7521/__init__.py,sha256=sI-EfGOAZTLM-LxfBfYEXU_74cd3ib63g8fkGu39PJA,67 +authlib/oauth2/rfc7521/__pycache__/__init__.cpython-311.pyc,, +authlib/oauth2/rfc7521/__pycache__/client.cpython-311.pyc,, +authlib/oauth2/rfc7521/client.py,sha256=MAqHEfl6f11AmZYxwT2GNqV1xA64hUO4-ksxujSR8dA,2683 +authlib/oauth2/rfc7523/__init__.py,sha256=0vllgNHhuHqWawuXy7vKtBT7wjHrn3YRA6ftmAkKOkA,852 +authlib/oauth2/rfc7523/__pycache__/__init__.cpython-311.pyc,, +authlib/oauth2/rfc7523/__pycache__/assertion.cpython-311.pyc,, +authlib/oauth2/rfc7523/__pycache__/auth.cpython-311.pyc,, +authlib/oauth2/rfc7523/__pycache__/client.cpython-311.pyc,, +authlib/oauth2/rfc7523/__pycache__/jwt_bearer.cpython-311.pyc,, +authlib/oauth2/rfc7523/__pycache__/token.cpython-311.pyc,, +authlib/oauth2/rfc7523/__pycache__/validator.cpython-311.pyc,, +authlib/oauth2/rfc7523/assertion.py,sha256=ZFklvOm9ulLdUCoWn245igaK4LjXsFIJn5GcWJRl7iU,2024 +authlib/oauth2/rfc7523/auth.py,sha256=owAbFXkftxI79uPjchtfsFmvhUAquyA02McmaovVrNw,3346 +authlib/oauth2/rfc7523/client.py,sha256=dfleCVFY3VXJk6OKXVZBXKSVUY4817jqtD6qWA6nO9I,4388 +authlib/oauth2/rfc7523/jwt_bearer.py,sha256=e-G12oauDZiz8QTWrHXIXGuLcOpXgqZTrw5y3jjlGoQ,6532 +authlib/oauth2/rfc7523/token.py,sha256=Ovy75iNBC6BhMx44sZ6OjsWXxxIoZUrsYiCNqeGR1Fs,3321 +authlib/oauth2/rfc7523/validator.py,sha256=VXx11aa1nF3cp-fdsbQSkx0oXchiArhCtIGdnK-A9Ks,1602 +authlib/oauth2/rfc7591/__init__.py,sha256=Wb4PkmuGy8makvgceRVV1472cGL1udCS2bD9SGbqJyg,667 +authlib/oauth2/rfc7591/__pycache__/__init__.cpython-311.pyc,, +authlib/oauth2/rfc7591/__pycache__/claims.cpython-311.pyc,, +authlib/oauth2/rfc7591/__pycache__/endpoint.cpython-311.pyc,, +authlib/oauth2/rfc7591/__pycache__/errors.cpython-311.pyc,, +authlib/oauth2/rfc7591/claims.py,sha256=4eMNWjY0Osh4IvdxAZE-bHXf0gqfk0VoERxtkSL07AQ,9809 +authlib/oauth2/rfc7591/endpoint.py,sha256=3EYBDrBhp8G7iK12hBZBns_95yDmLeXzEiP5I1JRW6g,8104 +authlib/oauth2/rfc7591/errors.py,sha256=nx_1-wyT1kznHXh1R91uwa1gbRJ5YKUxWY1SiFVRTWg,1098 +authlib/oauth2/rfc7592/__init__.py,sha256=4du9AjzDNRXbmtkTWBPbpXz5ivugseKIuXtp3oAsk4w,315 +authlib/oauth2/rfc7592/__pycache__/__init__.cpython-311.pyc,, +authlib/oauth2/rfc7592/__pycache__/endpoint.cpython-311.pyc,, +authlib/oauth2/rfc7592/endpoint.py,sha256=Ec_QncWPPtK-1hM6KVlBM_94ufb_ci6ZfC8ydQxC8yE,9759 +authlib/oauth2/rfc7636/__init__.py,sha256=U-568f2yopL7jOGbL-6js5AMm9mSu74PgK21AkmfAN8,340 +authlib/oauth2/rfc7636/__pycache__/__init__.cpython-311.pyc,, +authlib/oauth2/rfc7636/__pycache__/challenge.cpython-311.pyc,, +authlib/oauth2/rfc7636/challenge.py,sha256=MugGeYxa9Vwz9_D5EtQD3FekN29nmmtQ2wj6zRaKyFk,5173 +authlib/oauth2/rfc7662/__init__.py,sha256=buYHq9DwjRGLIENJkDJ0-9VNyo_8Sui--5C3WyFc6O4,423 +authlib/oauth2/rfc7662/__pycache__/__init__.cpython-311.pyc,, +authlib/oauth2/rfc7662/__pycache__/introspection.cpython-311.pyc,, +authlib/oauth2/rfc7662/__pycache__/models.cpython-311.pyc,, +authlib/oauth2/rfc7662/__pycache__/token_validator.cpython-311.pyc,, +authlib/oauth2/rfc7662/introspection.py,sha256=BZ5ET90mL22R3wp5OobUnAXwzrbTFJkqcyZ8uuixPqQ,5244 +authlib/oauth2/rfc7662/models.py,sha256=vlmy-_UJmzy4rFjOjLsKpybpodoMsxt4FRi-URDoCKQ,868 +authlib/oauth2/rfc7662/token_validator.py,sha256=x7s4funp-7edBTWs64hsTkxZLxf5O8yPKkDdKPwMMWA,1339 +authlib/oauth2/rfc8414/__init__.py,sha256=ilEoqCBQ-lqXM7RBVlqAzbHbW39d_5oTKbKzJU4bfIY,361 +authlib/oauth2/rfc8414/__pycache__/__init__.cpython-311.pyc,, +authlib/oauth2/rfc8414/__pycache__/models.cpython-311.pyc,, +authlib/oauth2/rfc8414/__pycache__/well_known.cpython-311.pyc,, +authlib/oauth2/rfc8414/models.py,sha256=-ajtcMT5OleAEwnUNzvRGVdpDEDJ2nfhXn9WuLPNwpE,17450 +authlib/oauth2/rfc8414/well_known.py,sha256=-2eObCyYbBJHBokeBfuVHLqL2gvaLOK-aOVcy4M-5i8,727 +authlib/oauth2/rfc8628/__init__.py,sha256=TqyFJ_dAH5XjFdHFzxuiYrfpvX8rR0UiCyDoEPXPhhc,678 +authlib/oauth2/rfc8628/__pycache__/__init__.cpython-311.pyc,, +authlib/oauth2/rfc8628/__pycache__/device_code.cpython-311.pyc,, +authlib/oauth2/rfc8628/__pycache__/endpoint.cpython-311.pyc,, +authlib/oauth2/rfc8628/__pycache__/errors.cpython-311.pyc,, +authlib/oauth2/rfc8628/__pycache__/models.cpython-311.pyc,, +authlib/oauth2/rfc8628/device_code.py,sha256=drtONNm2ZNzqNN5Ts93GEE68RaTVqhJFJPUnb16STT0,7715 +authlib/oauth2/rfc8628/endpoint.py,sha256=bA4U9n7I6rt1FblM5eVTx3jhfbJ0-7ptCD9kUV_wLuo,7107 +authlib/oauth2/rfc8628/errors.py,sha256=c761U-GWU58bmfyEPw1VveaOkmOgXElBVlWaE-tXMTg,919 +authlib/oauth2/rfc8628/models.py,sha256=o5734crJs0HZ8d_Iyqoh5O3i_D4_Pf2nml-HU62Re80,827 +authlib/oauth2/rfc8693/__init__.py,sha256=Omkb_UdGC1dsrqP8SUD1f562SnEyOs_pd5G03pouMrE,182 +authlib/oauth2/rfc8693/__pycache__/__init__.cpython-311.pyc,, +authlib/oauth2/rfc9068/__init__.py,sha256=XWpuGChgg0Rvyy7ZZ3c26q5LiTcQQbZboJknSCpKg4s,332 +authlib/oauth2/rfc9068/__pycache__/__init__.cpython-311.pyc,, +authlib/oauth2/rfc9068/__pycache__/claims.cpython-311.pyc,, +authlib/oauth2/rfc9068/__pycache__/introspection.cpython-311.pyc,, +authlib/oauth2/rfc9068/__pycache__/revocation.cpython-311.pyc,, +authlib/oauth2/rfc9068/__pycache__/token.cpython-311.pyc,, +authlib/oauth2/rfc9068/__pycache__/token_validator.cpython-311.pyc,, +authlib/oauth2/rfc9068/claims.py,sha256=omSrkPIBtOwPGmgIl8ERc8IAk9bzAewoQw9fkvDZauE,1866 +authlib/oauth2/rfc9068/introspection.py,sha256=rJ7QfzYM0ynQFkzYJ-icEByeaBzX1AcgxgLyQGwwOt8,4251 +authlib/oauth2/rfc9068/revocation.py,sha256=vqwfdE5sWEL2bJUrjoYVLllkFaAOt_BuSxU9UxQFnPs,2521 +authlib/oauth2/rfc9068/token.py,sha256=LZgwzqRtjiaZv-EKwUSl07IM2v7XfvgTioTmfwgqFoE,8639 +authlib/oauth2/rfc9068/token_validator.py,sha256=I8ZWuEGMByR0KV4KxUnr-iLHTITBvCf9lfzzpgh_Dbk,6890 +authlib/oidc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +authlib/oidc/__pycache__/__init__.cpython-311.pyc,, +authlib/oidc/core/__init__.py,sha256=NX_zhew3om9I0qVozcXyHshqqCqbk2V1qhiHO8Q4Ztk,650 +authlib/oidc/core/__pycache__/__init__.cpython-311.pyc,, +authlib/oidc/core/__pycache__/claims.cpython-311.pyc,, +authlib/oidc/core/__pycache__/errors.cpython-311.pyc,, +authlib/oidc/core/__pycache__/models.cpython-311.pyc,, +authlib/oidc/core/__pycache__/util.cpython-311.pyc,, +authlib/oidc/core/claims.py,sha256=AvHWg9GPMjQCLDS8uKtOxlXi_prz-fyWGJAF34vD5w0,10187 +authlib/oidc/core/errors.py,sha256=2nZdVIlTweNwXapWa7QodgCR0_5neGlCbGB2U4xUT6o,2883 +authlib/oidc/core/grants/__init__.py,sha256=E6KAaqJMyRYWD2635gdcfE-oN_RRaIAL_imHATP12Uo,226 +authlib/oidc/core/grants/__pycache__/__init__.cpython-311.pyc,, +authlib/oidc/core/grants/__pycache__/code.cpython-311.pyc,, +authlib/oidc/core/grants/__pycache__/hybrid.cpython-311.pyc,, +authlib/oidc/core/grants/__pycache__/implicit.cpython-311.pyc,, +authlib/oidc/core/grants/__pycache__/util.cpython-311.pyc,, +authlib/oidc/core/grants/code.py,sha256=Jl7Asl_PzMPHHaileADIkSn8cODbYCLSC14F4zkUy4U,4848 +authlib/oidc/core/grants/hybrid.py,sha256=t20y1cX83vX-fgHL0v8JOtrjcs1pbe4zhMRnYarHKFM,3362 +authlib/oidc/core/grants/implicit.py,sha256=wzpMiiC0z31dvSrZVrZThBL5WsTWowvlu2MN5JI97dM,5288 +authlib/oidc/core/grants/util.py,sha256=0Zmyd_ofSrzAyJYf7dxtuQ7wcx2shkha4aDIIIeo-F8,4122 +authlib/oidc/core/models.py,sha256=eYGC-NcIuu1m50h5o1bJFwUjwGF9l-AytTic8B07zmU,413 +authlib/oidc/core/util.py,sha256=LggTWoq-qHvF5JW6MsMxBa76rxVlxCARIlQXkxkZD_o,382 +authlib/oidc/discovery/__init__.py,sha256=sI40mT-HXoRPqxAE5UfPg-r3xa_wrQZ8jIuN5n5nm70,321 +authlib/oidc/discovery/__pycache__/__init__.cpython-311.pyc,, +authlib/oidc/discovery/__pycache__/models.cpython-311.pyc,, +authlib/oidc/discovery/__pycache__/well_known.cpython-311.pyc,, +authlib/oidc/discovery/models.py,sha256=dNpNiDyss3T-6FGkoWe_t0_D2xTHSppd4wMY_BsoQNg,12575 +authlib/oidc/discovery/well_known.py,sha256=3VmfTsVReChVVxBuN1eoL7fIRHL0-tN0aXH2XVKeiDM,574 diff --git a/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/REQUESTED b/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/REQUESTED new file mode 100644 index 00000000..e69de29b diff --git a/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/WHEEL b/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/WHEEL new file mode 100644 index 00000000..4724c457 --- /dev/null +++ b/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.42.0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/top_level.txt b/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/top_level.txt new file mode 100644 index 00000000..b91e7e46 --- /dev/null +++ b/.venv/Lib/site-packages/Authlib-1.3.0.dist-info/top_level.txt @@ -0,0 +1 @@ +authlib diff --git a/.venv/Lib/site-packages/_cffi_backend.cp311-win_amd64.pyd b/.venv/Lib/site-packages/_cffi_backend.cp311-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..6d30f70e0a0630305de378fa456d29c6cb83beae GIT binary patch literal 181248 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 X4ddJJ;Sr2K5sY%t!>r)%@9+Nra%ne0 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/__init__.py b/.venv/Lib/site-packages/authlib/__init__.py new file mode 100644 index 00000000..2a2e5adc --- /dev/null +++ b/.venv/Lib/site-packages/authlib/__init__.py @@ -0,0 +1,17 @@ +""" + authlib + ~~~~~~~ + + The ultimate Python library in building OAuth 1.0, OAuth 2.0 and OpenID + Connect clients and providers. It covers from low level specification + implementation to high level framework integrations. + + :copyright: (c) 2017 by Hsiaoming Yang. + :license: BSD, see LICENSE for more details. +""" +from .consts import version, homepage, author + +__version__ = version +__homepage__ = homepage +__author__ = author +__license__ = 'BSD-3-Clause' diff --git a/.venv/Lib/site-packages/authlib/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6a82191d2b32e50ec0002dd90ec3d09226d05070 GIT binary patch literal 745 zcmZ{i!EVz)5Qf)r+Jv-e4+yw$m?M!I)0P8LgpeSu+DcW6XgOe6T5aq}vg&%*+TElI z2b8zq5fBf+dvL5G4oIB1RqCx=7`y3_u{HX~`}_0EuD`b1Ek^P8;5+^d82eoo_fcDl zn~200ma&*+K~_^iUW;pa7>9X1t_KWj@d}3VD%Rsh7RJr2e#Sa0;(%~1pb!&3R&r43 z&v((Pit{nTM0uGDkMM5h$3_Dgt*|qY8U_=oGO0&!`i2Ow6K!uTQ3L8WLt7y`>|<~4~XGht@3(wz2R zD3o5js6W8}(PPNfKd{i-dU4`*ACK?7d3^7Cyf;7k{Z*vx@2lVN1S9mPdo0bqNv@yi zpc#*MW>m$*ySHM9IrK$w@F)#M(L8??KcY}Z|8htL3V2*>@+wGy&&}01CSk*^sDkCZGqNkO&x2 zBXUSel0jZVTE67!V)fb@T$n{bqiMWOFkXomP!a-v!Jm8DbayPXlBW%aR(02`*EV&h zX4bZgY0+0St)|;l)BL!m*>$67aXz7Guba9RT0X*vhrfD}&y}ln13xUks&8$q=+!+| zUZ*y-E7YN^N^4bG&a`N)Reokx%FJ}>d;^{IZOY1em_*jN&Vptd2abec1Kv7Q!fQH!^3KWroOCC&wfOiR9OQ^v67zI^>NU$M;Ep4K!CKNfI2GUIhr zksLnFer(bgXBOpKc$kaOfq^_d1QJ;x10~s=DSX{T2zO5@9LWPY$<6EJcs0BOx3$j? zyEALJFVf+S*i+Vy?m%-2$MZ#PrnS zn8ebOjGW9Q{p9@I-26QK`1s7c%#!$cy@JYL95%W6DWy57c15f}Yd{Vu<_8iVm>C%v MKQO?EB4(f%0F?wYmjD0& literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/common/__pycache__/encoding.cpython-311.pyc b/.venv/Lib/site-packages/authlib/common/__pycache__/encoding.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..869a069728eef882b9aa4402c23dc8b8043cab29 GIT binary patch literal 4022 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/common/__pycache__/security.cpython-311.pyc b/.venv/Lib/site-packages/authlib/common/__pycache__/security.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4487dbcf9c1a7eb1d7a3f59f9a3cd03438676d87 GIT binary patch literal 1424 zcmZ`&L2DaF6rNd0E7==4I1ZHBjo6grAVQ?l76P`UR+dFA8k8c*J_rR>-W_Y#mb7AK zpc$DGoJw2(vlKP1pWECd3jkQ@pEUyOU{n{_3ux}Dv5`^}rT-+Qy~ z+aH6$X$0f1FMcC`VuXGdi_wt&0Vi1i$4EyyuA$=j6Bn_&mWmR=Tb|J?fW0H!22k|r z67g+Hx@R93W!<}vihdpEQP}rRgk|4_z-psJ!X?8LbSE7!Pw*4z7;z|UG`7b0Ik;Yq z+^8ez_}N9C@y-E0ke~o*KfwKCCwh#Y1Jlbf+X|ZGo7{zhJy{27<8UAn=llfb$ugMl zr7sbNZ}b>Fe18ugdY*yr@;H~*BbM-DDKKFz35 z=6GqPp)-+ERc-rhePywvS-RP%me#Dz!fHj^W~CgdlllgsglVLqky2!bG zIl0?}ph}gnQl-U>nz<3xta{yQL>bXq)a1L7=I+^4tV$Z>n!oRqn>O&XC{ z&C)70mWYf)gm73C%;{V77TKtKEe`ijH^2S#cjVd>&NJbSfOo&7M`g3{(p3clua()p66z^xUs3Iqff78r*SUAG8oXGoM^5tlrNomowRXI<=NdmkYUMHviRwT%iz_+5v;}CR>a~+p_`zaJy_+ zj4uieTFjBFgoBP8U(I?%s58xYg>v@DIqZ>9b`?5a{2-6 z2Vt^BFgE(bKefNxoxR)hNBaKA5Mkf-!PU6~{$@IO6z+r%?>xO@rv}Q*QKFOR&M)

EwB2hA r-h^)TLm$6d|Mg)nwA@7tLm4gH=-&Elh$Ni&x0#l4e26X^w~W65+*(wv literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/common/__pycache__/urls.cpython-311.pyc b/.venv/Lib/site-packages/authlib/common/__pycache__/urls.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2555f8e687535ce7dfff386baedea340c9a60b7a GIT binary patch literal 5899 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' + + +class AuthlibHTTPError(AuthlibBaseError): + #: HTTP status code + status_code = 400 + + def __init__(self, error=None, description=None, uri=None, + status_code=None): + super().__init__(error, description, uri) + if status_code is not None: + self.status_code = status_code + + def get_error_description(self): + return self.description + + def get_body(self): + error = [('error', self.error)] + + if self.description: + error.append(('error_description', self.description)) + + if self.uri: + error.append(('error_uri', self.uri)) + return error + + def get_headers(self): + return default_json_headers[:] + + def __call__(self, uri=None): + self.uri = uri + body = dict(self.get_body()) + headers = self.get_headers() + return self.status_code, body, headers + + +class ContinueIteration(AuthlibBaseError): + pass diff --git a/.venv/Lib/site-packages/authlib/common/security.py b/.venv/Lib/site-packages/authlib/common/security.py new file mode 100644 index 00000000..b05ea144 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/common/security.py @@ -0,0 +1,19 @@ +import os +import string +import random + +UNICODE_ASCII_CHARACTER_SET = string.ascii_letters + string.digits + + +def generate_token(length=30, chars=UNICODE_ASCII_CHARACTER_SET): + rand = random.SystemRandom() + return ''.join(rand.choice(chars) for _ in range(length)) + + +def is_secure_transport(uri): + """Check if the uri is over ssl.""" + if os.getenv('AUTHLIB_INSECURE_TRANSPORT'): + return True + + uri = uri.lower() + return uri.startswith(('https://', 'http://localhost:')) diff --git a/.venv/Lib/site-packages/authlib/common/urls.py b/.venv/Lib/site-packages/authlib/common/urls.py new file mode 100644 index 00000000..1d1847fa --- /dev/null +++ b/.venv/Lib/site-packages/authlib/common/urls.py @@ -0,0 +1,146 @@ +""" + authlib.util.urls + ~~~~~~~~~~~~~~~~~ + + Wrapper functions for URL encoding and decoding. +""" + +import re +from urllib.parse import quote as _quote +from urllib.parse import unquote as _unquote +from urllib.parse import urlencode as _urlencode +import urllib.parse as urlparse + +from .encoding import to_unicode, to_bytes + +always_safe = ( + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz' + '0123456789_.-' +) +urlencoded = set(always_safe) | set('=&;:%+~,*@!()/?') +INVALID_HEX_PATTERN = re.compile(r'%[^0-9A-Fa-f]|%[0-9A-Fa-f][^0-9A-Fa-f]') + + +def url_encode(params): + encoded = [] + for k, v in params: + encoded.append((to_bytes(k), to_bytes(v))) + return to_unicode(_urlencode(encoded)) + + +def url_decode(query): + """Decode a query string in x-www-form-urlencoded format into a sequence + of two-element tuples. + + Unlike urlparse.parse_qsl(..., strict_parsing=True) urldecode will enforce + correct formatting of the query string by validation. If validation fails + a ValueError will be raised. urllib.parse_qsl will only raise errors if + any of name-value pairs omits the equals sign. + """ + # Check if query contains invalid characters + if query and not set(query) <= urlencoded: + error = ("Error trying to decode a non urlencoded string. " + "Found invalid characters: %s " + "in the string: '%s'. " + "Please ensure the request/response body is " + "x-www-form-urlencoded.") + raise ValueError(error % (set(query) - urlencoded, query)) + + # Check for correctly hex encoded values using a regular expression + # All encoded values begin with % followed by two hex characters + # correct = %00, %A0, %0A, %FF + # invalid = %G0, %5H, %PO + if INVALID_HEX_PATTERN.search(query): + raise ValueError('Invalid hex encoding in query string.') + + # We encode to utf-8 prior to parsing because parse_qsl behaves + # differently on unicode input in python 2 and 3. + # Python 2.7 + # >>> urlparse.parse_qsl(u'%E5%95%A6%E5%95%A6') + # u'\xe5\x95\xa6\xe5\x95\xa6' + # Python 2.7, non unicode input gives the same + # >>> urlparse.parse_qsl('%E5%95%A6%E5%95%A6') + # '\xe5\x95\xa6\xe5\x95\xa6' + # but now we can decode it to unicode + # >>> urlparse.parse_qsl('%E5%95%A6%E5%95%A6').decode('utf-8') + # u'\u5566\u5566' + # Python 3.3 however + # >>> urllib.parse.parse_qsl(u'%E5%95%A6%E5%95%A6') + # u'\u5566\u5566' + + # We want to allow queries such as "c2" whereas urlparse.parse_qsl + # with the strict_parsing flag will not. + params = urlparse.parse_qsl(query, keep_blank_values=True) + + # unicode all the things + decoded = [] + for k, v in params: + decoded.append((to_unicode(k), to_unicode(v))) + return decoded + + +def add_params_to_qs(query, params): + """Extend a query with a list of two-tuples.""" + if isinstance(params, dict): + params = params.items() + + qs = urlparse.parse_qsl(query, keep_blank_values=True) + qs.extend(params) + return url_encode(qs) + + +def add_params_to_uri(uri, params, fragment=False): + """Add a list of two-tuples to the uri query components.""" + sch, net, path, par, query, fra = urlparse.urlparse(uri) + if fragment: + fra = add_params_to_qs(fra, params) + else: + query = add_params_to_qs(query, params) + return urlparse.urlunparse((sch, net, path, par, query, fra)) + + +def quote(s, safe=b'/'): + return to_unicode(_quote(to_bytes(s), safe)) + + +def unquote(s): + return to_unicode(_unquote(s)) + + +def quote_url(s): + return quote(s, b'~@#$&()*!+=:;,.?/\'') + + +def extract_params(raw): + """Extract parameters and return them as a list of 2-tuples. + + Will successfully extract parameters from urlencoded query strings, + dicts, or lists of 2-tuples. Empty strings/dicts/lists will return an + empty list of parameters. Any other input will result in a return + value of None. + """ + if isinstance(raw, (list, tuple)): + try: + raw = dict(raw) + except (TypeError, ValueError): + return None + + if isinstance(raw, dict): + params = [] + for k, v in raw.items(): + params.append((to_unicode(k), to_unicode(v))) + return params + + if not raw: + return None + + try: + return url_decode(raw) + except ValueError: + return None + + +def is_valid_url(url): + parsed = urlparse.urlparse(url) + return parsed.scheme and parsed.hostname diff --git a/.venv/Lib/site-packages/authlib/consts.py b/.venv/Lib/site-packages/authlib/consts.py new file mode 100644 index 00000000..e310e793 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/consts.py @@ -0,0 +1,11 @@ +name = 'Authlib' +version = '1.3.0' +author = 'Hsiaoming Yang ' +homepage = 'https://authlib.org/' +default_user_agent = f'{name}/{version} (+{homepage})' + +default_json_headers = [ + ('Content-Type', 'application/json'), + ('Cache-Control', 'no-store'), + ('Pragma', 'no-cache'), +] diff --git a/.venv/Lib/site-packages/authlib/deprecate.py b/.venv/Lib/site-packages/authlib/deprecate.py new file mode 100644 index 00000000..7d581d69 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/deprecate.py @@ -0,0 +1,16 @@ +import warnings + + +class AuthlibDeprecationWarning(DeprecationWarning): + pass + + +warnings.simplefilter('always', AuthlibDeprecationWarning) + + +def deprecate(message, version=None, link_uid=None, link_file=None): + if version: + message += f'\nIt will be compatible before version {version}.' + if link_uid and link_file: + message += f'\nRead more ' + warnings.warn(AuthlibDeprecationWarning(message), stacklevel=2) diff --git a/.venv/Lib/site-packages/authlib/integrations/__init__.py b/.venv/Lib/site-packages/authlib/integrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/.venv/Lib/site-packages/authlib/integrations/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bbf0c0dd30bdafb4bb8121951205696c05640abf GIT binary patch literal 201 zcmZ3^%ge<81i#(4rh@3lAOZ#$p^VRLK*n^26oz01O-8?!3`I;p{%4TnuNW7rnB@GF z%)IoN(EPLzkHqBc;+UY++|=Bp)S}el?m%-2$MZ#PrnS zn8ebOjGW9Q{mi_Q)bygnlFax S5+9fu85ut?z=$GdpcnudK{hJ@ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/base_client/__init__.py b/.venv/Lib/site-packages/authlib/integrations/base_client/__init__.py new file mode 100644 index 00000000..077301f2 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/base_client/__init__.py @@ -0,0 +1,18 @@ +from .registry import BaseOAuth +from .sync_app import BaseApp, OAuth1Mixin, OAuth2Mixin +from .sync_openid import OpenIDMixin +from .framework_integration import FrameworkIntegration +from .errors import ( + OAuthError, MissingRequestTokenError, MissingTokenError, + TokenExpiredError, InvalidTokenError, UnsupportedTokenTypeError, + MismatchingStateError, +) + +__all__ = [ + 'BaseOAuth', + 'BaseApp', 'OAuth1Mixin', 'OAuth2Mixin', + 'OpenIDMixin', 'FrameworkIntegration', + 'OAuthError', 'MissingRequestTokenError', 'MissingTokenError', + 'TokenExpiredError', 'InvalidTokenError', 'UnsupportedTokenTypeError', + 'MismatchingStateError', +] diff --git a/.venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..348bb9e92929669695290f65463b23ba48284123 GIT binary patch literal 941 zcmcJNKabNe6u|AKZPKQ_UV#(b#KMw+t6)Jw2%7O_~Flv#yT3Y(QwnN93ME+-DFky;^Fk~(vV%NnG? znxx6L$QEmn7TYG5HT109Hp+gM32pPOh#i+{_3`D4C$~`-;7a^Vsk&67*A(fKy!7;oU zgH*kA1bn&DUaf4JmhyQ<1;i__E}w)6jW@h@Pq`dtSt=AP&An*`OYa>WlZ7f8>Wn8U zR7vA^ss^@!V^A|NHzizyhC$O{%b=z4%DbLB0tQqnF)gCyj-2u+2(#?B zxVc*_q`Fl!E|TOsXX{1<^jD{f+<6sDpX5K(klR5JCP@%{Mi;sybU8eD=tpU+&+4D1 zXT29;G?M-?FkpQUAS2)r_810CrSUj{$6{9}Ht$D%)mT^<<2kxLyE^CS!R+sIj_%B^&OiMZr7|up U(EmWgc6H=6-r438H}zqD0^*_wssI20 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/async_app.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/async_app.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef500c9b3303589c88ff01e5200ad6cdbb7214c2 GIT binary patch literal 10260 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 ADgXcg literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/async_openid.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/async_openid.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..186d8f722d5e529e2b3caa4787be8d6d0113725a GIT binary patch literal 4462 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/errors.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/errors.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5c3ef8b17485ba3be6c9ed2168287d48b17a510a GIT binary patch literal 1998 zcmcIkJ8#oa6uvi3+B6Sn3Mp+V!WHR|fmC8(KnRIPDYOuzK7ZI`J({rf4)183eh%i#4I;kaeT9fnyyhidf@9+iUNk40=5GxE{Q$0!gX+^PAlPQXy zQ54hGTTP5}in7~Mn<0}D>J!q%OqZK49@RBlH>|DthP}D|O4WAU`YJP-*wetDa$7?m`3RrD#oqS>A$3nj-OaS z5(4)IK>PQ3mYZ%b;>q(p)sQurdTY2Y%wd)7wwUX!+dIq(DpWKBM&SXac*s@xC}zqb zh@96j8t*|Gf|$p9{T@*|q{l+&vCmw-XYL=Suv8oY&32=OyWMXJ$ze?eZuT96Gd-wS zUYJo>FgCbSx6l-VC|MEjL>X~tSO>4IJ+*1*{bdOp7y&WZ!3^d^xQW4)0~{LC!SsgZ zwj9Ui9t&KoA2`9v^e0cjL>6|RYvSoWRtOB(u8Z^NZo`QPFJEw5>|8S8xgFV7Cyxg*`1gO?+%oUXd)~;xhd>*zTV25tig-k>a@dsuD{fiiy2T1G{ybz>+v0O>m)312x_q6wTP4SeCSR z#&Kh0YKkA!VrXg%659my(5A`eB`huUp)dUpq#%eG2!t+u*f$mLgXzBPId`OyMpl#d zYINp)oH=vvJ-_=qXTI+5_Y)}pyY#L0ZXY54#zw1%&C1Rnpi(3%QMojkvG3dr$CFD$ zG1BPy?#4!Oe)OxItzl zRRZZzJs|tkK9FA33(}{`st>gMT0r%0kOyGpv15NmR(W`DzZJPilS|r4mM&h&nA$u| zntC>)hk`g8!BHm!XM^pX;~iE^^+>Nx7;6o)xkg~F>!cnTE{L1H`u>A(^B3T^1N|h`@)b4^32diIP=TEyx3HI$ zva?669=zwd2hji68C&D?yusrx`iLpDHE%io$n)+erpX8~ahlCyGMw6tIX*_H$dL~K zi_>I*(-LnP*^DKnvq{ykeAn;fv`I>{)big*rkCw{LZCi) z%n}y0JC<}C`&&Mw_(p3$0ZR&Vx1uJ^u`Dwh{- z6FQXV%AGKQ$=D??xSh$7&BJ-2++nw+Nq|D!x^w~#qVSrduqNika*K+bUaSD|xIrf6 zCF;pbd47@U(fz+;erbeKLY%UEO7r+BR-a;+NmElSLHjV5kSx*E;p~g5o-!>Vm(5vz z7^kMOqMHj8=mpWo(9~yWh5@8w37PB)4Z{e5ANI4KUv&dEC_(8Qs3uix6d|+*B57^aK1ipu#~C{9E0mc=s+>B z6)2srhN87lw8F0XV5E3->uA|m9XwSVJk=m#f4n~YdRe$9-<9e^hl=`^UY4puCu&0{ z?h5q-2LYLb@lvXM{vUctuSX6QuWnr}3)M)h7Kv3NvE9aC>*W-Wgo}P1Qu!B*KzITA zZPUsZfQvl;1-UP-3DEE07BEMC8|K!;4Enz(=DP8T7z4D3y|ue>HqB@UutJAn<`$;_ zB!C$bVml5{bcziLi9v!MMOBI6sSOANsjveIL1YmdbBt?7dV;{MbPP-w3m|}Mf}mU`@@eGc!*Dfnx)wQIm@G`baJ#KASr3GeapLvx zaPiHpH%m7hTB;9(3#RSK&J&5@5BGWJM-VUZr0DYGpE_H=;#1K?+s$&zd8aDm1-&c8 zfHfzuJb>9ec0A89f0_L)JHUN-23hIiJ}EB%e{@({1ua#)#{(ycZ(|)jzF zAQC*gvGbkiYs0`249%oS(w3wyFXar&4@{y%0svu}9>gbY#$fQEv6ej>A+JMo4_gGm z;;SLzRvJY^cR;)fBBJjySC>PZ?|e4(=~U^Buf#9?4=+Bs@bFwUI#G*Ge0SmdcdPQX zntZL&x_;U>w4L~TbbA!YC3f;j_=)+=N7X-GtQ@)oSK-p#^PgNR!0#oe|9hC%OEBX; z{fB=8X1bz+?fqY80+qPaR}Rvf-tne8sj)35gbp+$qz>nMR4uKU8a)gvq)`yS5Evdh zoQehKmvM+|!<$dVlq@kp1s2I-I?k2H=QO%dXx7=$gC@DR_w2H)!Y zS%BuoY`cT0+snWez_$QWHREM_NoTQ%i3?liFW$H9Z9GTO2bhx>S3p2E&T(}TSZ6<{ V((t^+!Ho8bpRw=1JqFmT{tpt?X!-yE literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/registry.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/registry.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7d2c8ead94c119ec769d973be6f3d9d22cfaf19a GIT binary patch literal 5667 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 NZ)MsJ(Q!hh`!72CaVr1- literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/sync_app.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/base_client/__pycache__/sync_app.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5634bec30006d08faaab5b3a015748594def39ad GIT binary patch literal 16623 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/base_client/async_app.py b/.venv/Lib/site-packages/authlib/integrations/base_client/async_app.py new file mode 100644 index 00000000..640896e7 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/base_client/async_app.py @@ -0,0 +1,144 @@ +import time +import logging +from authlib.common.urls import urlparse +from .errors import ( + MissingRequestTokenError, + MissingTokenError, +) +from .sync_app import OAuth1Base, OAuth2Base + +log = logging.getLogger(__name__) + +__all__ = ['AsyncOAuth1Mixin', 'AsyncOAuth2Mixin'] + + +class AsyncOAuth1Mixin(OAuth1Base): + async def request(self, method, url, token=None, **kwargs): + async with self._get_oauth_client() as session: + return await _http_request(self, session, method, url, token, kwargs) + + async def create_authorization_url(self, redirect_uri=None, **kwargs): + """Generate the authorization url and state for HTTP redirect. + + :param redirect_uri: Callback or redirect URI for authorization. + :param kwargs: Extra parameters to include. + :return: dict + """ + if not self.authorize_url: + raise RuntimeError('Missing "authorize_url" value') + + if self.authorize_params: + kwargs.update(self.authorize_params) + + async with self._get_oauth_client() as client: + client.redirect_uri = redirect_uri + params = {} + if self.request_token_params: + params.update(self.request_token_params) + request_token = await client.fetch_request_token(self.request_token_url, **params) + log.debug(f'Fetch request token: {request_token!r}') + url = client.create_authorization_url(self.authorize_url, **kwargs) + state = request_token['oauth_token'] + return {'url': url, 'request_token': request_token, 'state': state} + + async def fetch_access_token(self, request_token=None, **kwargs): + """Fetch access token in one step. + + :param request_token: A previous request token for OAuth 1. + :param kwargs: Extra parameters to fetch access token. + :return: A token dict. + """ + async with self._get_oauth_client() as client: + if request_token is None: + raise MissingRequestTokenError() + # merge request token with verifier + token = {} + token.update(request_token) + token.update(kwargs) + client.token = token + params = self.access_token_params or {} + token = await client.fetch_access_token(self.access_token_url, **params) + return token + + +class AsyncOAuth2Mixin(OAuth2Base): + async def _on_update_token(self, token, refresh_token=None, access_token=None): + if self._update_token: + await self._update_token( + token, + refresh_token=refresh_token, + access_token=access_token, + ) + + async def load_server_metadata(self): + if self._server_metadata_url and '_loaded_at' not in self.server_metadata: + async with self.client_cls(**self.client_kwargs) as client: + resp = await client.request('GET', self._server_metadata_url, withhold_token=True) + resp.raise_for_status() + metadata = resp.json() + metadata['_loaded_at'] = time.time() + self.server_metadata.update(metadata) + return self.server_metadata + + async def request(self, method, url, token=None, **kwargs): + metadata = await self.load_server_metadata() + async with self._get_oauth_client(**metadata) as session: + return await _http_request(self, session, method, url, token, kwargs) + + async def create_authorization_url(self, redirect_uri=None, **kwargs): + """Generate the authorization url and state for HTTP redirect. + + :param redirect_uri: Callback or redirect URI for authorization. + :param kwargs: Extra parameters to include. + :return: dict + """ + metadata = await self.load_server_metadata() + authorization_endpoint = self.authorize_url or metadata.get('authorization_endpoint') + if not authorization_endpoint: + raise RuntimeError('Missing "authorize_url" value') + + if self.authorize_params: + kwargs.update(self.authorize_params) + + async with self._get_oauth_client(**metadata) as client: + client.redirect_uri = redirect_uri + return self._create_oauth2_authorization_url( + client, authorization_endpoint, **kwargs) + + async def fetch_access_token(self, redirect_uri=None, **kwargs): + """Fetch access token in the final step. + + :param redirect_uri: Callback or Redirect URI that is used in + previous :meth:`authorize_redirect`. + :param kwargs: Extra parameters to fetch access token. + :return: A token dict. + """ + metadata = await self.load_server_metadata() + token_endpoint = self.access_token_url or metadata.get('token_endpoint') + async with self._get_oauth_client(**metadata) as client: + if redirect_uri is not None: + client.redirect_uri = redirect_uri + params = {} + if self.access_token_params: + params.update(self.access_token_params) + params.update(kwargs) + token = await client.fetch_token(token_endpoint, **params) + return token + + +async def _http_request(ctx, session, method, url, token, kwargs): + request = kwargs.pop('request', None) + withhold_token = kwargs.get('withhold_token') + if ctx.api_base_url and not url.startswith(('https://', 'http://')): + url = urlparse.urljoin(ctx.api_base_url, url) + + if withhold_token: + return await session.request(method, url, **kwargs) + + if token is None and ctx._fetch_token and request: + token = await ctx._fetch_token(request) + if token is None: + raise MissingTokenError() + + session.token = token + return await session.request(method, url, **kwargs) diff --git a/.venv/Lib/site-packages/authlib/integrations/base_client/async_openid.py b/.venv/Lib/site-packages/authlib/integrations/base_client/async_openid.py new file mode 100644 index 00000000..68100f2f --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/base_client/async_openid.py @@ -0,0 +1,79 @@ +from authlib.jose import JsonWebToken, JsonWebKey +from authlib.oidc.core import UserInfo, CodeIDToken, ImplicitIDToken + +__all__ = ['AsyncOpenIDMixin'] + + +class AsyncOpenIDMixin: + async def fetch_jwk_set(self, force=False): + metadata = await self.load_server_metadata() + jwk_set = metadata.get('jwks') + if jwk_set and not force: + return jwk_set + + uri = metadata.get('jwks_uri') + if not uri: + raise RuntimeError('Missing "jwks_uri" in metadata') + + async with self.client_cls(**self.client_kwargs) as client: + resp = await client.request('GET', uri, withhold_token=True) + resp.raise_for_status() + jwk_set = resp.json() + + self.server_metadata['jwks'] = jwk_set + return jwk_set + + async def userinfo(self, **kwargs): + """Fetch user info from ``userinfo_endpoint``.""" + metadata = await self.load_server_metadata() + resp = await self.get(metadata['userinfo_endpoint'], **kwargs) + resp.raise_for_status() + data = resp.json() + return UserInfo(data) + + async def parse_id_token(self, token, nonce, claims_options=None): + """Return an instance of UserInfo from token's ``id_token``.""" + claims_params = dict( + nonce=nonce, + client_id=self.client_id, + ) + if 'access_token' in token: + claims_params['access_token'] = token['access_token'] + claims_cls = CodeIDToken + else: + claims_cls = ImplicitIDToken + + metadata = await self.load_server_metadata() + if claims_options is None and 'issuer' in metadata: + claims_options = {'iss': {'values': [metadata['issuer']]}} + + alg_values = metadata.get('id_token_signing_alg_values_supported') + if not alg_values: + alg_values = ['RS256'] + + jwt = JsonWebToken(alg_values) + + jwk_set = await self.fetch_jwk_set() + try: + claims = jwt.decode( + token['id_token'], + key=JsonWebKey.import_key_set(jwk_set), + claims_cls=claims_cls, + claims_options=claims_options, + claims_params=claims_params, + ) + except ValueError: + jwk_set = await self.fetch_jwk_set(force=True) + claims = jwt.decode( + token['id_token'], + key=JsonWebKey.import_key_set(jwk_set), + claims_cls=claims_cls, + claims_options=claims_options, + claims_params=claims_params, + ) + + # https://github.com/lepture/authlib/issues/259 + if claims.get('nonce_supported') is False: + claims.params['nonce'] = None + claims.validate(leeway=120) + return UserInfo(claims) diff --git a/.venv/Lib/site-packages/authlib/integrations/base_client/errors.py b/.venv/Lib/site-packages/authlib/integrations/base_client/errors.py new file mode 100644 index 00000000..bb4dd2b1 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/base_client/errors.py @@ -0,0 +1,30 @@ +from authlib.common.errors import AuthlibBaseError + + +class OAuthError(AuthlibBaseError): + error = 'oauth_error' + + +class MissingRequestTokenError(OAuthError): + error = 'missing_request_token' + + +class MissingTokenError(OAuthError): + error = 'missing_token' + + +class TokenExpiredError(OAuthError): + error = 'token_expired' + + +class InvalidTokenError(OAuthError): + error = 'token_invalid' + + +class UnsupportedTokenTypeError(OAuthError): + error = 'unsupported_token_type' + + +class MismatchingStateError(OAuthError): + error = 'mismatching_state' + description = 'CSRF Warning! State not equal in request and response.' diff --git a/.venv/Lib/site-packages/authlib/integrations/base_client/framework_integration.py b/.venv/Lib/site-packages/authlib/integrations/base_client/framework_integration.py new file mode 100644 index 00000000..9243e8f0 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/base_client/framework_integration.py @@ -0,0 +1,64 @@ +import json +import time + + +class FrameworkIntegration: + expires_in = 3600 + + def __init__(self, name, cache=None): + self.name = name + self.cache = cache + + def _get_cache_data(self, key): + value = self.cache.get(key) + if not value: + return None + try: + return json.loads(value) + except (TypeError, ValueError): + return None + + def _clear_session_state(self, session): + now = time.time() + for key in dict(session): + if '_authlib_' in key: + # TODO: remove in future + session.pop(key) + elif key.startswith('_state_'): + value = session[key] + exp = value.get('exp') + if not exp or exp < now: + session.pop(key) + + def get_state_data(self, session, state): + key = f'_state_{self.name}_{state}' + if self.cache: + value = self._get_cache_data(key) + else: + value = session.get(key) + if value: + return value.get('data') + return None + + def set_state_data(self, session, state, data): + key = f'_state_{self.name}_{state}' + if self.cache: + self.cache.set(key, json.dumps({'data': data}), self.expires_in) + else: + now = time.time() + session[key] = {'data': data, 'exp': now + self.expires_in} + + def clear_state_data(self, session, state): + key = f'_state_{self.name}_{state}' + if self.cache: + self.cache.delete(key) + else: + session.pop(key, None) + self._clear_session_state(session) + + def update_token(self, token, refresh_token=None, access_token=None): + raise NotImplementedError() + + @staticmethod + def load_config(oauth, name, params): + raise NotImplementedError() diff --git a/.venv/Lib/site-packages/authlib/integrations/base_client/registry.py b/.venv/Lib/site-packages/authlib/integrations/base_client/registry.py new file mode 100644 index 00000000..68d1be5d --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/base_client/registry.py @@ -0,0 +1,131 @@ +import functools +from .framework_integration import FrameworkIntegration + +__all__ = ['BaseOAuth'] + + +OAUTH_CLIENT_PARAMS = ( + 'client_id', 'client_secret', + 'request_token_url', 'request_token_params', + 'access_token_url', 'access_token_params', + 'refresh_token_url', 'refresh_token_params', + 'authorize_url', 'authorize_params', + 'api_base_url', 'client_kwargs', + 'server_metadata_url', +) + + +class BaseOAuth: + """Registry for oauth clients. + + Create an instance for registry:: + + oauth = OAuth() + """ + oauth1_client_cls = None + oauth2_client_cls = None + framework_integration_cls = FrameworkIntegration + + def __init__(self, cache=None, fetch_token=None, update_token=None): + self._registry = {} + self._clients = {} + self.cache = cache + self.fetch_token = fetch_token + self.update_token = update_token + + def create_client(self, name): + """Create or get the given named OAuth client. For instance, the + OAuth registry has ``.register`` a twitter client, developers may + access the client with:: + + client = oauth.create_client('twitter') + + :param: name: Name of the remote application + :return: OAuth remote app + """ + if name in self._clients: + return self._clients[name] + + if name not in self._registry: + return None + + overwrite, config = self._registry[name] + client_cls = config.pop('client_cls', None) + + if client_cls and client_cls.OAUTH_APP_CONFIG: + kwargs = client_cls.OAUTH_APP_CONFIG + kwargs.update(config) + else: + kwargs = config + + kwargs = self.generate_client_kwargs(name, overwrite, **kwargs) + framework = self.framework_integration_cls(name, self.cache) + if client_cls: + client = client_cls(framework, name, **kwargs) + elif kwargs.get('request_token_url'): + client = self.oauth1_client_cls(framework, name, **kwargs) + else: + client = self.oauth2_client_cls(framework, name, **kwargs) + + self._clients[name] = client + return client + + def register(self, name, overwrite=False, **kwargs): + """Registers a new remote application. + + :param name: Name of the remote application. + :param overwrite: Overwrite existing config with framework settings. + :param kwargs: Parameters for :class:`RemoteApp`. + + Find parameters for the given remote app class. When a remote app is + registered, it can be accessed with *named* attribute:: + + oauth.register('twitter', client_id='', ...) + oauth.twitter.get('timeline') + """ + self._registry[name] = (overwrite, kwargs) + return self.create_client(name) + + def generate_client_kwargs(self, name, overwrite, **kwargs): + fetch_token = kwargs.pop('fetch_token', None) + update_token = kwargs.pop('update_token', None) + + config = self.load_config(name, OAUTH_CLIENT_PARAMS) + if config: + kwargs = _config_client(config, kwargs, overwrite) + + if not fetch_token and self.fetch_token: + fetch_token = functools.partial(self.fetch_token, name) + + kwargs['fetch_token'] = fetch_token + + if not kwargs.get('request_token_url'): + if not update_token and self.update_token: + update_token = functools.partial(self.update_token, name) + + kwargs['update_token'] = update_token + return kwargs + + def load_config(self, name, params): + return self.framework_integration_cls.load_config(self, name, params) + + def __getattr__(self, key): + try: + return object.__getattribute__(self, key) + except AttributeError: + if key in self._registry: + return self.create_client(key) + raise AttributeError('No such client: %s' % key) + + +def _config_client(config, kwargs, overwrite): + for k in OAUTH_CLIENT_PARAMS: + v = config.get(k, None) + if k not in kwargs: + kwargs[k] = v + elif overwrite and v: + if isinstance(kwargs[k], dict): + kwargs[k].update(v) + else: + kwargs[k] = v + return kwargs diff --git a/.venv/Lib/site-packages/authlib/integrations/base_client/sync_app.py b/.venv/Lib/site-packages/authlib/integrations/base_client/sync_app.py new file mode 100644 index 00000000..50fa27a7 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/base_client/sync_app.py @@ -0,0 +1,343 @@ +import time +import logging +from authlib.common.urls import urlparse +from authlib.consts import default_user_agent +from authlib.common.security import generate_token +from .errors import ( + MismatchingStateError, + MissingRequestTokenError, + MissingTokenError, +) + +log = logging.getLogger(__name__) + + +class BaseApp: + client_cls = None + OAUTH_APP_CONFIG = None + + def request(self, method, url, token=None, **kwargs): + raise NotImplementedError() + + def get(self, url, **kwargs): + """Invoke GET http request. + + If ``api_base_url`` configured, shortcut is available:: + + client.get('users/lepture') + """ + return self.request('GET', url, **kwargs) + + def post(self, url, **kwargs): + """Invoke POST http request. + + If ``api_base_url`` configured, shortcut is available:: + + client.post('timeline', json={'text': 'Hi'}) + """ + return self.request('POST', url, **kwargs) + + def patch(self, url, **kwargs): + """Invoke PATCH http request. + + If ``api_base_url`` configured, shortcut is available:: + + client.patch('profile', json={'name': 'Hsiaoming Yang'}) + """ + return self.request('PATCH', url, **kwargs) + + def put(self, url, **kwargs): + """Invoke PUT http request. + + If ``api_base_url`` configured, shortcut is available:: + + client.put('profile', json={'name': 'Hsiaoming Yang'}) + """ + return self.request('PUT', url, **kwargs) + + def delete(self, url, **kwargs): + """Invoke DELETE http request. + + If ``api_base_url`` configured, shortcut is available:: + + client.delete('posts/123') + """ + return self.request('DELETE', url, **kwargs) + + +class _RequestMixin: + def _get_requested_token(self, request): + if self._fetch_token and request: + return self._fetch_token(request) + + def _send_token_request(self, session, method, url, token, kwargs): + request = kwargs.pop('request', None) + withhold_token = kwargs.get('withhold_token') + if self.api_base_url and not url.startswith(('https://', 'http://')): + url = urlparse.urljoin(self.api_base_url, url) + + if withhold_token: + return session.request(method, url, **kwargs) + + if token is None: + token = self._get_requested_token(request) + + if token is None: + raise MissingTokenError() + + session.token = token + return session.request(method, url, **kwargs) + + +class OAuth1Base: + client_cls = None + + def __init__( + self, framework, name=None, fetch_token=None, + client_id=None, client_secret=None, + request_token_url=None, request_token_params=None, + access_token_url=None, access_token_params=None, + authorize_url=None, authorize_params=None, + api_base_url=None, client_kwargs=None, user_agent=None, **kwargs): + self.framework = framework + self.name = name + self.client_id = client_id + self.client_secret = client_secret + self.request_token_url = request_token_url + self.request_token_params = request_token_params + self.access_token_url = access_token_url + self.access_token_params = access_token_params + self.authorize_url = authorize_url + self.authorize_params = authorize_params + self.api_base_url = api_base_url + self.client_kwargs = client_kwargs or {} + + self._fetch_token = fetch_token + self._user_agent = user_agent or default_user_agent + self._kwargs = kwargs + + def _get_oauth_client(self): + session = self.client_cls(self.client_id, self.client_secret, **self.client_kwargs) + session.headers['User-Agent'] = self._user_agent + return session + + +class OAuth1Mixin(_RequestMixin, OAuth1Base): + def request(self, method, url, token=None, **kwargs): + with self._get_oauth_client() as session: + return self._send_token_request(session, method, url, token, kwargs) + + def create_authorization_url(self, redirect_uri=None, **kwargs): + """Generate the authorization url and state for HTTP redirect. + + :param redirect_uri: Callback or redirect URI for authorization. + :param kwargs: Extra parameters to include. + :return: dict + """ + if not self.authorize_url: + raise RuntimeError('Missing "authorize_url" value') + + if self.authorize_params: + kwargs.update(self.authorize_params) + + with self._get_oauth_client() as client: + client.redirect_uri = redirect_uri + params = self.request_token_params or {} + request_token = client.fetch_request_token(self.request_token_url, **params) + log.debug(f'Fetch request token: {request_token!r}') + url = client.create_authorization_url(self.authorize_url, **kwargs) + state = request_token['oauth_token'] + return {'url': url, 'request_token': request_token, 'state': state} + + def fetch_access_token(self, request_token=None, **kwargs): + """Fetch access token in one step. + + :param request_token: A previous request token for OAuth 1. + :param kwargs: Extra parameters to fetch access token. + :return: A token dict. + """ + with self._get_oauth_client() as client: + if request_token is None: + raise MissingRequestTokenError() + # merge request token with verifier + token = {} + token.update(request_token) + token.update(kwargs) + client.token = token + params = self.access_token_params or {} + token = client.fetch_access_token(self.access_token_url, **params) + return token + + +class OAuth2Base: + client_cls = None + + def __init__( + self, framework, name=None, fetch_token=None, update_token=None, + client_id=None, client_secret=None, + access_token_url=None, access_token_params=None, + authorize_url=None, authorize_params=None, + api_base_url=None, client_kwargs=None, server_metadata_url=None, + compliance_fix=None, client_auth_methods=None, user_agent=None, **kwargs): + self.framework = framework + self.name = name + self.client_id = client_id + self.client_secret = client_secret + self.access_token_url = access_token_url + self.access_token_params = access_token_params + self.authorize_url = authorize_url + self.authorize_params = authorize_params + self.api_base_url = api_base_url + self.client_kwargs = client_kwargs or {} + + self.compliance_fix = compliance_fix + self.client_auth_methods = client_auth_methods + self._fetch_token = fetch_token + self._update_token = update_token + self._user_agent = user_agent or default_user_agent + + self._server_metadata_url = server_metadata_url + self.server_metadata = kwargs + + def _on_update_token(self, token, refresh_token=None, access_token=None): + raise NotImplementedError() + + def _get_oauth_client(self, **metadata): + client_kwargs = {} + client_kwargs.update(self.client_kwargs) + client_kwargs.update(metadata) + + if self.authorize_url: + client_kwargs['authorization_endpoint'] = self.authorize_url + if self.access_token_url: + client_kwargs['token_endpoint'] = self.access_token_url + + session = self.client_cls( + client_id=self.client_id, + client_secret=self.client_secret, + update_token=self._on_update_token, + **client_kwargs + ) + if self.client_auth_methods: + for f in self.client_auth_methods: + session.register_client_auth_method(f) + + if self.compliance_fix: + self.compliance_fix(session) + + session.headers['User-Agent'] = self._user_agent + return session + + @staticmethod + def _format_state_params(state_data, params): + if state_data is None: + raise MismatchingStateError() + + code_verifier = state_data.get('code_verifier') + if code_verifier: + params['code_verifier'] = code_verifier + + redirect_uri = state_data.get('redirect_uri') + if redirect_uri: + params['redirect_uri'] = redirect_uri + return params + + @staticmethod + def _create_oauth2_authorization_url(client, authorization_endpoint, **kwargs): + rv = {} + if client.code_challenge_method: + code_verifier = kwargs.get('code_verifier') + if not code_verifier: + code_verifier = generate_token(48) + kwargs['code_verifier'] = code_verifier + rv['code_verifier'] = code_verifier + log.debug(f'Using code_verifier: {code_verifier!r}') + + scope = kwargs.get('scope', client.scope) + if scope and 'openid' in scope.split(): + # this is an OpenID Connect service + nonce = kwargs.get('nonce') + if not nonce: + nonce = generate_token(20) + kwargs['nonce'] = nonce + rv['nonce'] = nonce + + url, state = client.create_authorization_url( + authorization_endpoint, **kwargs) + rv['url'] = url + rv['state'] = state + return rv + + +class OAuth2Mixin(_RequestMixin, OAuth2Base): + def _on_update_token(self, token, refresh_token=None, access_token=None): + if callable(self._update_token): + self._update_token( + token, + refresh_token=refresh_token, + access_token=access_token, + ) + self.framework.update_token( + token, + refresh_token=refresh_token, + access_token=access_token, + ) + + def request(self, method, url, token=None, **kwargs): + metadata = self.load_server_metadata() + with self._get_oauth_client(**metadata) as session: + return self._send_token_request(session, method, url, token, kwargs) + + def load_server_metadata(self): + if self._server_metadata_url and '_loaded_at' not in self.server_metadata: + with self.client_cls(**self.client_kwargs) as session: + resp = session.request('GET', self._server_metadata_url, withhold_token=True) + resp.raise_for_status() + metadata = resp.json() + + metadata['_loaded_at'] = time.time() + self.server_metadata.update(metadata) + return self.server_metadata + + def create_authorization_url(self, redirect_uri=None, **kwargs): + """Generate the authorization url and state for HTTP redirect. + + :param redirect_uri: Callback or redirect URI for authorization. + :param kwargs: Extra parameters to include. + :return: dict + """ + metadata = self.load_server_metadata() + authorization_endpoint = self.authorize_url or metadata.get('authorization_endpoint') + + if not authorization_endpoint: + raise RuntimeError('Missing "authorize_url" value') + + if self.authorize_params: + kwargs.update(self.authorize_params) + + + with self._get_oauth_client(**metadata) as client: + if redirect_uri is not None: + client.redirect_uri = redirect_uri + return self._create_oauth2_authorization_url( + client, authorization_endpoint, **kwargs) + + def fetch_access_token(self, redirect_uri=None, **kwargs): + """Fetch access token in the final step. + + :param redirect_uri: Callback or Redirect URI that is used in + previous :meth:`authorize_redirect`. + :param kwargs: Extra parameters to fetch access token. + :return: A token dict. + """ + metadata = self.load_server_metadata() + token_endpoint = self.access_token_url or metadata.get('token_endpoint') + with self._get_oauth_client(**metadata) as client: + if redirect_uri is not None: + client.redirect_uri = redirect_uri + params = {} + if self.access_token_params: + params.update(self.access_token_params) + params.update(kwargs) + token = client.fetch_token(token_endpoint, **params) + return token diff --git a/.venv/Lib/site-packages/authlib/integrations/base_client/sync_openid.py b/.venv/Lib/site-packages/authlib/integrations/base_client/sync_openid.py new file mode 100644 index 00000000..ac51907a --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/base_client/sync_openid.py @@ -0,0 +1,77 @@ +from authlib.jose import jwt, JsonWebToken, JsonWebKey +from authlib.oidc.core import UserInfo, CodeIDToken, ImplicitIDToken + + +class OpenIDMixin: + def fetch_jwk_set(self, force=False): + metadata = self.load_server_metadata() + jwk_set = metadata.get('jwks') + if jwk_set and not force: + return jwk_set + + uri = metadata.get('jwks_uri') + if not uri: + raise RuntimeError('Missing "jwks_uri" in metadata') + + with self.client_cls(**self.client_kwargs) as session: + resp = session.request('GET', uri, withhold_token=True) + resp.raise_for_status() + jwk_set = resp.json() + + self.server_metadata['jwks'] = jwk_set + return jwk_set + + def userinfo(self, **kwargs): + """Fetch user info from ``userinfo_endpoint``.""" + metadata = self.load_server_metadata() + resp = self.get(metadata['userinfo_endpoint'], **kwargs) + resp.raise_for_status() + data = resp.json() + return UserInfo(data) + + def parse_id_token(self, token, nonce, claims_options=None, leeway=120): + """Return an instance of UserInfo from token's ``id_token``.""" + if 'id_token' not in token: + return None + + def load_key(header, _): + jwk_set = JsonWebKey.import_key_set(self.fetch_jwk_set()) + try: + return jwk_set.find_by_kid(header.get('kid')) + except ValueError: + # re-try with new jwk set + jwk_set = JsonWebKey.import_key_set(self.fetch_jwk_set(force=True)) + return jwk_set.find_by_kid(header.get('kid')) + + claims_params = dict( + nonce=nonce, + client_id=self.client_id, + ) + if 'access_token' in token: + claims_params['access_token'] = token['access_token'] + claims_cls = CodeIDToken + else: + claims_cls = ImplicitIDToken + + metadata = self.load_server_metadata() + if claims_options is None and 'issuer' in metadata: + claims_options = {'iss': {'values': [metadata['issuer']]}} + + alg_values = metadata.get('id_token_signing_alg_values_supported') + if alg_values: + _jwt = JsonWebToken(alg_values) + else: + _jwt = jwt + + claims = _jwt.decode( + token['id_token'], key=load_key, + claims_cls=claims_cls, + claims_options=claims_options, + claims_params=claims_params, + ) + # https://github.com/lepture/authlib/issues/259 + if claims.get('nonce_supported') is False: + claims.params['nonce'] = None + + claims.validate(leeway=leeway) + return UserInfo(claims) diff --git a/.venv/Lib/site-packages/authlib/integrations/django_client/__init__.py b/.venv/Lib/site-packages/authlib/integrations/django_client/__init__.py new file mode 100644 index 00000000..5839c945 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/django_client/__init__.py @@ -0,0 +1,19 @@ +# flake8: noqa + +from .integration import DjangoIntegration, token_update +from .apps import DjangoOAuth1App, DjangoOAuth2App +from ..base_client import BaseOAuth, OAuthError + + +class OAuth(BaseOAuth): + oauth1_client_cls = DjangoOAuth1App + oauth2_client_cls = DjangoOAuth2App + framework_integration_cls = DjangoIntegration + + +__all__ = [ + 'OAuth', + 'DjangoOAuth1App', 'DjangoOAuth2App', + 'DjangoIntegration', + 'token_update', 'OAuthError', +] diff --git a/.venv/Lib/site-packages/authlib/integrations/django_client/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/django_client/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9286f7a03bcf52ed70819d5ec422093acc4bbccc GIT binary patch literal 895 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 K*r$nU&Hn(e;`-eH literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/django_oauth1/__pycache__/nonce.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/django_oauth1/__pycache__/nonce.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6a865a210dfad225b48d81983141b06265aec275 GIT binary patch literal 875 zcmZWo%}X0W6raiLM^=p}D%OMjpdjR6thXYihknpnS`Ym=R2IT!cU&hXyXoviv}|Ax z9&Aa$TLmffWLxaD|3-=6VHxPD^x!Sv&0hLuV-)FQ=J$T@&CL6l+5J)|3?PudkABcL zM(DRP`jR^%Cs%-cL>}^R4b|~7#>mTUq2-)MUZA3OthN=g)LqA2r7k%;rIZ0v*(W~% zAOdcY7*~P!q@{rcS>P%wOBXRD#whuiVocD!MoQJ;krME^91}#{xlp?g$nJ(VSOx0zWK= zYH@xptFqMCloND=MItI^jxr0%*(boqp&AWl^d2BV>F8AQBpsPN8o7}yp6j8p_Os++ zTA1t%+}@o4fbn^%r@y}L>EwQD4s{XMucf2oo#Cr6cA7oCP5xMg546p8$-AH(99q*y z)^u|3mu77(Zo514yM9NTIn-v3v>71jU?EvNfojlFk;u_rJ0&;dwA3qEJw;acH^e6t q9|Jhe->HXQvqtZ7^$Vysj&1>T3C1`@H#?U{*BHdZUGzU>5&r?Sx88^V literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/django_oauth1/__pycache__/resource_protector.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/django_oauth1/__pycache__/resource_protector.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..71f52d91bc874d9268d208812e5be28bfe448762 GIT binary patch literal 4465 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 xSSfgld$c9FA+i{~rvf{>(Q%g=7LhYI6ousq* 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/django_oauth2/__pycache__/endpoints.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/django_oauth2/__pycache__/endpoints.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..73abf664295913f5c2128705a4e1def654947068 GIT binary patch literal 2739 zcmc&$&2Jk;6rbI-lhhx$PMbiZ(5{j;#A@nP2t?z4h*k{+sdY<|9-11hHoIeIV|&-k zjGZQOr3&?6P$f7Zg$q(nfi@g+LEQKooXQf`N|h=h4%~vmAu1Q%%-Wk;aaC@Ny>Dk{ z=Kbb<{NC*T5RHZqw12Msj4$>g^gDlOw_vNYn}W_7GLb12P*IwfB_yM3$dn%!5SaaiWmZD(tVgwh$4@A+w@o24IWXZ+lFTxH^7U2vaPDM-55Vej>P_c zA9gcm{O-uDo3nExpCyFr9NolOu&M$f*F+S?xgMr0k@A=DWdyS_vD>zIVf8K1+5sK! z(BXOqZA?z5uim=(NqSC8U%oLtaX_QBf5*6IuHn}V5IF!Bf8PBS#2TuiCAfQSsa+Q6 zzEXu^$OGjOB5~HPPk5>-RcQmpH^m&EzaOxtV72V8hU#v&uB%60hgS{I!|XLERbHCP z>d8;bn5;mQMeLz6JVtul)0w`YQ=D`oUV(Uta-*&4@g5Tax5s0O8y3o1(J^tsJ)!|5 zSqT|=Q6jQ z?A*t?k*Ap%T*So%45TnH5IK{qV7rpJZY^Y}#qgODEYfqBX837Quofl(8|R>);FP12 zUZrUcpL}<+&2^eAt+-*&6Jgfs@h;4IY5o|PNF5Ll(DT8eZ}W}8GqrFtJoKIYG(1rc zPdtmCT)(?@YCC?e5kFVEQoGWO4zI_aMknjh$!GCX>-nwsx8qZd_!OV}qjPcd$iNPg zqL-cxBz`=-Ro))B*ciC@jr=?ouN~TjEl~$iIl%-`FF*%g3Q|?l_#)A&(z;L9_87l! zz_sZQNbu?qG&ylYCwXzw=B!HlSkq~%fX(DwIw8BgUOAhPO}&B>3W)#^iGtu$f?$*z z1oZKC9p3qcn4JI5D19uTf?>BqiC})`gQ25(3g=%k(&6Cewa=tdfYxu zv-Kj@G&iJiK9&o-AJKq*dZ9Jbt7)cVXc~!w5_uEEV^#n?<8s z&&NH9NI*h&;4@$rEu(wN9keVZvjcrZWV`JN~R3nzE_oeol z;lW0D6et@!x-XisBQ;iII|_{M?d|Pyl6*1rHu^qvT6rR!R{qcU@H3O}PZ}};qQn0% zALZgbKJzO7Zwvp=H)7}Oedqs^|6~;K(utru*gBPx-U*Z>S>uDVXQu=O;V?Z|99~L< zUBlcs&V51M7kw8z%3mV9W;jo19t4D3lA7pxz4O1*GbRCN4~qJ+iNE;p-}`ejQb2-S P`r-}0w?D>v!kB*nZo$Z2 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/django_oauth2/__pycache__/requests.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/django_oauth2/__pycache__/requests.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7da7a989454502d71fd3b14b20f9bc8dd56a7d31 GIT binary patch literal 2962 zcmdT`O>7%g5PrK}+b?m9Y2!9&Dby)#k<)l9l>(wF2-H@s5VWW%0$HwBo89MR!>%`d zyRK-JN;yO#ph|F{B!?by3Pd?^;Lec)LUv>+)=Ef7hyyoA?g5np%)Iqa90v)?iRblr zc4ppt^WMxiz zjMnzzr|nF$2(KT*5gEx#CdtdD#3Ds`i4-MMUL49RENVs;$r@N~bmr${AXWOLaYpgL zyKD!R$VXCs5Dpa!hA+FRnch?tyvh(Cd*v@t9rYn2W)HrWv;Gd79>- z!4!K}kQ>U$x&!)NVTW-laZHgFZE-KHQZu#MBi~LT}bbk1i?q zlS}Yv!hB-vj2iMH+J}KzCi7$#O~jb(*i8~X1fs0Whv6rPT)uQ;UE&9T_s}N8M^LQj zeA>G^y4N94gDZGRAPeN@)bRa#wN$1;GyD)p{uXAZ#5d0GetiimE&Rk6T)&Au{(z644CdQNP z&<<-fh?VC|-De`a{25p>P)y74`B7jY>KJK|=)UeDvNK`8`ElU)zFssWG*_d!3eEMHoZL#E+DxCSrgOD)u1eJ! zRV!4jr-qjjB1YK+LcgRt44^-#X^v}_ZRCeE?N(X0Lk-8s33vsxUApD*#0zRIht8bGzk3sJ)tD_R6~}cV+{gi zI|8qZAB2KfOLYuY$9AZWH9&QsAuG{zg8)I*fkmw=5YjFYcO(2Xz{SqMYrxSw2jt&( z9nneR&`FeFUkLCW?M+nB|630c6^&y(;v!S=f}rY$u@>d{aNj{Y#aJZJD9-IGU$_o_ zn`eRaHqRdHc3NaF^4pk=mqeU; literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/django_oauth2/__pycache__/resource_protector.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/django_oauth2/__pycache__/resource_protector.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6ca39f62718d117db5b7a7f73567df10c948628c GIT binary patch literal 4751 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 u+gI}(|t&yFCneYD-fRp$D literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/django_oauth2/__pycache__/signals.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/django_oauth2/__pycache__/signals.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eb39d91c64d3f66dd1ee4edda23f93aa12135d2f GIT binary patch literal 433 zcmZusF-rq66i)86oXR0$p)NYOb+83T5hqax>0os!fs!V#cd>U#xui$k{0S`-{0E9S z`#(C$txkeNp<7+dSvwT^c**y^FJInEUVMKO+4#A9hi{9YIa!4BUrcMZctRX;9HAID zFh&jn{A|^?g%>rP6`H$3TjNe0mEEuWW*KLNx(FnVYUTB8o8MCzs0tUlOAQMX*IKe7 ziv&p1q&*W_6pR|+nQv4FWHW)(BF}c`bjkCIrumGSI6omwaUlb8r`oqylyx+@ff(Wz zB%m2c2BeaLOv$xq5iJZHb*+g8ph?~_60NF`27-hdp`@}eLz>b4>RvH zR=gL%S+Zp(W4rW)-6k%^_yZk|mviEwy@NqI?2r0mRGbvhPH9jWdL!@Ax1_W`Xb;0t MI7YkkOg3z*UxO%n=>Px# literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/django_oauth2/authorization_server.py b/.venv/Lib/site-packages/authlib/integrations/django_oauth2/authorization_server.py new file mode 100644 index 00000000..08a27595 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/django_oauth2/authorization_server.py @@ -0,0 +1,118 @@ +from django.http import HttpResponse +from django.utils.module_loading import import_string +from django.conf import settings +from authlib.oauth2 import ( + AuthorizationServer as _AuthorizationServer, +) +from authlib.oauth2.rfc6750 import BearerTokenGenerator +from authlib.common.security import generate_token as _generate_token +from authlib.common.encoding import json_dumps +from .requests import DjangoOAuth2Request, DjangoJsonRequest +from .signals import client_authenticated, token_revoked + + +class AuthorizationServer(_AuthorizationServer): + """Django implementation of :class:`authlib.oauth2.rfc6749.AuthorizationServer`. + Initialize it with client model and token model:: + + from authlib.integrations.django_oauth2 import AuthorizationServer + from your_project.models import OAuth2Client, OAuth2Token + + server = AuthorizationServer(OAuth2Client, OAuth2Token) + """ + + def __init__(self, client_model, token_model): + self.config = getattr(settings, 'AUTHLIB_OAUTH2_PROVIDER', {}) + self.client_model = client_model + self.token_model = token_model + scopes_supported = self.config.get('scopes_supported') + super().__init__(scopes_supported=scopes_supported) + # add default token generator + self.register_token_generator('default', self.create_bearer_token_generator()) + + def query_client(self, client_id): + """Default method for ``AuthorizationServer.query_client``. Developers MAY + rewrite this function to meet their own needs. + """ + try: + return self.client_model.objects.get(client_id=client_id) + except self.client_model.DoesNotExist: + return None + + def save_token(self, token, request): + """Default method for ``AuthorizationServer.save_token``. Developers MAY + rewrite this function to meet their own needs. + """ + client = request.client + if request.user: + user_id = request.user.pk + else: + user_id = client.user_id + item = self.token_model( + client_id=client.client_id, + user_id=user_id, + **token + ) + item.save() + return item + + def create_oauth2_request(self, request): + return DjangoOAuth2Request(request) + + def create_json_request(self, request): + return DjangoJsonRequest(request) + + def handle_response(self, status_code, payload, headers): + if isinstance(payload, dict): + payload = json_dumps(payload) + resp = HttpResponse(payload, status=status_code) + for k, v in headers: + resp[k] = v + return resp + + def send_signal(self, name, *args, **kwargs): + if name == 'after_authenticate_client': + client_authenticated.send(sender=self.__class__, *args, **kwargs) + elif name == 'after_revoke_token': + token_revoked.send(sender=self.__class__, *args, **kwargs) + + def create_bearer_token_generator(self): + """Default method to create BearerToken generator.""" + conf = self.config.get('access_token_generator', True) + access_token_generator = create_token_generator(conf, 42) + + conf = self.config.get('refresh_token_generator', False) + refresh_token_generator = create_token_generator(conf, 48) + + conf = self.config.get('token_expires_in') + expires_generator = create_token_expires_in_generator(conf) + + return BearerTokenGenerator( + access_token_generator=access_token_generator, + refresh_token_generator=refresh_token_generator, + expires_generator=expires_generator, + ) + + +def create_token_generator(token_generator_conf, length=42): + if callable(token_generator_conf): + return token_generator_conf + + if isinstance(token_generator_conf, str): + return import_string(token_generator_conf) + elif token_generator_conf is True: + def token_generator(*args, **kwargs): + return _generate_token(length) + return token_generator + + +def create_token_expires_in_generator(expires_in_conf=None): + data = {} + data.update(BearerTokenGenerator.GRANT_TYPES_EXPIRES_IN) + if expires_in_conf: + data.update(expires_in_conf) + + def expires_in(client, grant_type): + return data.get(grant_type, BearerTokenGenerator.DEFAULT_EXPIRES_IN) + + return expires_in diff --git a/.venv/Lib/site-packages/authlib/integrations/django_oauth2/endpoints.py b/.venv/Lib/site-packages/authlib/integrations/django_oauth2/endpoints.py new file mode 100644 index 00000000..686675d5 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/django_oauth2/endpoints.py @@ -0,0 +1,56 @@ +from authlib.oauth2.rfc7009 import RevocationEndpoint as _RevocationEndpoint + + +class RevocationEndpoint(_RevocationEndpoint): + """The revocation endpoint for OAuth authorization servers allows clients + to notify the authorization server that a previously obtained refresh or + access token is no longer needed. + + Register it into authorization server, and create token endpoint response + for token revocation:: + + from django.views.decorators.http import require_http_methods + + # see register into authorization server instance + server.register_endpoint(RevocationEndpoint) + + @require_http_methods(["POST"]) + def revoke_token(request): + return server.create_endpoint_response( + RevocationEndpoint.ENDPOINT_NAME, + request + ) + """ + + def query_token(self, token, token_type_hint): + """Query requested token from database.""" + token_model = self.server.token_model + if token_type_hint == 'access_token': + rv = _query_access_token(token_model, token) + elif token_type_hint == 'refresh_token': + rv = _query_refresh_token(token_model, token) + else: + rv = _query_access_token(token_model, token) + if not rv: + rv = _query_refresh_token(token_model, token) + + return rv + + def revoke_token(self, token, request): + """Mark the give token as revoked.""" + token.revoked = True + token.save() + + +def _query_access_token(token_model, token): + try: + return token_model.objects.get(access_token=token) + except token_model.DoesNotExist: + return None + + +def _query_refresh_token(token_model, token): + try: + return token_model.objects.get(refresh_token=token) + except token_model.DoesNotExist: + return None diff --git a/.venv/Lib/site-packages/authlib/integrations/django_oauth2/requests.py b/.venv/Lib/site-packages/authlib/integrations/django_oauth2/requests.py new file mode 100644 index 00000000..e9f2d95a --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/django_oauth2/requests.py @@ -0,0 +1,35 @@ +from django.http import HttpRequest +from django.utils.functional import cached_property +from authlib.common.encoding import json_loads +from authlib.oauth2.rfc6749 import OAuth2Request, JsonRequest + + +class DjangoOAuth2Request(OAuth2Request): + def __init__(self, request: HttpRequest): + super().__init__(request.method, request.build_absolute_uri(), None, request.headers) + self._request = request + + @property + def args(self): + return self._request.GET + + @property + def form(self): + return self._request.POST + + @cached_property + def data(self): + data = {} + data.update(self._request.GET.dict()) + data.update(self._request.POST.dict()) + return data + + +class DjangoJsonRequest(JsonRequest): + def __init__(self, request: HttpRequest): + super().__init__(request.method, request.build_absolute_uri(), None, request.headers) + self._request = request + + @cached_property + def data(self): + return json_loads(self._request.body) diff --git a/.venv/Lib/site-packages/authlib/integrations/django_oauth2/resource_protector.py b/.venv/Lib/site-packages/authlib/integrations/django_oauth2/resource_protector.py new file mode 100644 index 00000000..b89257ba --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/django_oauth2/resource_protector.py @@ -0,0 +1,75 @@ +import functools +from django.http import JsonResponse +from authlib.oauth2 import ( + OAuth2Error, + ResourceProtector as _ResourceProtector, +) +from authlib.oauth2.rfc6749 import ( + MissingAuthorizationError, +) +from authlib.oauth2.rfc6750 import ( + BearerTokenValidator as _BearerTokenValidator +) +from .requests import DjangoJsonRequest +from .signals import token_authenticated + + +class ResourceProtector(_ResourceProtector): + def acquire_token(self, request, scopes=None, **kwargs): + """A method to acquire current valid token with the given scope. + + :param request: Django HTTP request instance + :param scopes: a list of scope values + :return: token object + """ + req = DjangoJsonRequest(request) + # backward compatibility + kwargs['scopes'] = scopes + for claim in kwargs: + if isinstance(kwargs[claim], str): + kwargs[claim] = [kwargs[claim]] + token = self.validate_request(request=req, **kwargs) + token_authenticated.send(sender=self.__class__, token=token) + return token + + def __call__(self, scopes=None, optional=False, **kwargs): + claims = kwargs + # backward compatibility + claims['scopes'] = scopes + def wrapper(f): + @functools.wraps(f) + def decorated(request, *args, **kwargs): + try: + token = self.acquire_token(request, **claims) + request.oauth_token = token + except MissingAuthorizationError as error: + if optional: + request.oauth_token = None + return f(request, *args, **kwargs) + return return_error_response(error) + except OAuth2Error as error: + return return_error_response(error) + return f(request, *args, **kwargs) + return decorated + return wrapper + + +class BearerTokenValidator(_BearerTokenValidator): + def __init__(self, token_model, realm=None, **extra_attributes): + self.token_model = token_model + super().__init__(realm, **extra_attributes) + + def authenticate_token(self, token_string): + try: + return self.token_model.objects.get(access_token=token_string) + except self.token_model.DoesNotExist: + return None + + +def return_error_response(error): + body = dict(error.get_body()) + resp = JsonResponse(body, status=error.status_code) + headers = error.get_headers() + for k, v in headers: + resp[k] = v + return resp diff --git a/.venv/Lib/site-packages/authlib/integrations/django_oauth2/signals.py b/.venv/Lib/site-packages/authlib/integrations/django_oauth2/signals.py new file mode 100644 index 00000000..0e9c2659 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/django_oauth2/signals.py @@ -0,0 +1,11 @@ +from django.dispatch import Signal + + +#: signal when client is authenticated +client_authenticated = Signal() + +#: signal when token is revoked +token_revoked = Signal() + +#: signal when token is authenticated +token_authenticated = Signal() diff --git a/.venv/Lib/site-packages/authlib/integrations/flask_client/__init__.py b/.venv/Lib/site-packages/authlib/integrations/flask_client/__init__.py new file mode 100644 index 00000000..ecdca2df --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/flask_client/__init__.py @@ -0,0 +1,51 @@ +from werkzeug.local import LocalProxy +from .integration import FlaskIntegration, token_update +from .apps import FlaskOAuth1App, FlaskOAuth2App +from ..base_client import BaseOAuth, OAuthError + + +class OAuth(BaseOAuth): + oauth1_client_cls = FlaskOAuth1App + oauth2_client_cls = FlaskOAuth2App + framework_integration_cls = FlaskIntegration + + def __init__(self, app=None, cache=None, fetch_token=None, update_token=None): + super().__init__( + cache=cache, fetch_token=fetch_token, update_token=update_token) + self.app = app + if app: + self.init_app(app) + + def init_app(self, app, cache=None, fetch_token=None, update_token=None): + """Initialize lazy for Flask app. This is usually used for Flask application + factory pattern. + """ + self.app = app + if cache is not None: + self.cache = cache + + if fetch_token: + self.fetch_token = fetch_token + if update_token: + self.update_token = update_token + + app.extensions = getattr(app, 'extensions', {}) + app.extensions['authlib.integrations.flask_client'] = self + + def create_client(self, name): + if not self.app: + raise RuntimeError('OAuth is not init with Flask app.') + return super().create_client(name) + + def register(self, name, overwrite=False, **kwargs): + self._registry[name] = (overwrite, kwargs) + if self.app: + return self.create_client(name) + return LocalProxy(lambda: self.create_client(name)) + + +__all__ = [ + 'OAuth', 'FlaskIntegration', + 'FlaskOAuth1App', 'FlaskOAuth2App', + 'token_update', 'OAuthError', +] diff --git a/.venv/Lib/site-packages/authlib/integrations/flask_client/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/flask_client/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..336618e8a883a72be9aea62e503534a4e1b229c6 GIT binary patch literal 3001 zcmai0&2Jk;6rb5$+v|_mC2pIBk7nry;HJ1A0*XRaL0ig)+EA5pSt7QZ-Ep#HZHL)S z(^x(P6sZXcq6eyS!{Sgt<-i4rKf|sf#aby665`OCtMq`%h4*H?jzfbO&%T*A^XBXK zdvC@+3=E_Qq`%+!m3yhH5760ud5yekuO556$z=_z6-zo&Y}PJKuU=?BiZM59n?3`Jtg!gttvP@C z#9Ono{rXAJA4uUu$+M=%gjJ9d#oL@$xrHl7DcaxW1!%bmr)NZ`Hqj*}>k5nMahA|k zJF!ek)RvauoVIGqOH@yZ7G+7*({|F1LrZ3v+@SgZoGlf^#A@SKgeibGE$2J61yffu$T)@sC9t zEzU0RJgi#F3UZ23dj{G(1H@m8WJ4WTNvtN;)qVHXeeJ=a#>cOtA8BWHeSPW6OWz)BW%jRS_BW&4k)cyqY{C*`XOH+2dhUcgqLD~- z>GK3IPK+K~b(tr?1NymEphba}9@~C08c$$8TXM*DZ>dwG=aY4?__U|l@@W`qQ}AD< z2Epg}j_EozrnzQqK`T|cCSpzlj*HsWX~)wb&v|pE>n=da?CmzLV~NmB36epSOv|tG z1#Q;!ea0)rUdMQlVmEwN@gUH>+VfpPi~WQa`w1cY6gwGu zcw(_Bz7I|IfQVcoa$IH^!>5+z)olCBSuC1EV=eWKrpSC4mauw}3kvcm z?g$PQyd&!5Q>cZ>%lSQ?k*V#m`~~%UToUrH`=oDNG#mQI_8EYAX}tElhz=yTQuQ@N zM4NZ~=|1)gioi9#N=MFWl zwsJ?-az~o#5drH3tN+Xj%$0_3vku}WxrxZaZCa96`tV($7y;1Ii#Wb#g*5v4f&MV9 zJb|5`i24XwrtmsQHeFJ8K-k){3&}=r+bn{(E!`n2w9((+tFMqJrlR8o$`QkY#5E`c z*dA_oF$DOrdfGM1leT%LriCbTHsyE_e#O%+zPjESsDu_rVVH-p0FXBhtsi*h{()D1 zx!O7~wsv4_kqAiP@=qG!416IBEnJ-=(BKmy;54WQ$?A2+=Q-TdL40Q3@Kisfe z`O&rfXfrdqksEG4J=ULFxi{8w7;D|_k3%ZRDCmVk7N0P5OnAalhEcBCb1v31hVdC( zYGDsYQiG?ecqyIedNmXtSGU?v_P1jQ2E!!|^UhcK47`!OKQUq)axJbLK^%V(%?G-# zqQzX-Fo07LDd>c6hH)~0gHYgZyl+4NI?=Da?}etarz^GNP35_c5{to;^IsyHjh&+% z@`Tjn*l36BAW}-~bcg(}5Fm?f!VN99j9>@^1za4Te2!5#UKj|n^Ni2b*xXc6c%pEk zAl(NS7o%}Zpun5sZA}!UC*f~h7j=$*YsIW$%^+bI@FE$;Pod8W03i-Sde3mYR1jJ3 zI}q?TQ`#nno7;1noNDfr+vIq2r`#sTnmgrA{4fRJo)pXPJ;c^WTV0o_l9mADu2@Xq HPXPK4jNr!i literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/flask_client/__pycache__/apps.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/flask_client/__pycache__/apps.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65d25cec3eaee3cee97a730a1528376175a044b8 GIT binary patch literal 6189 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 C*^j0G literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/flask_client/apps.py b/.venv/Lib/site-packages/authlib/integrations/flask_client/apps.py new file mode 100644 index 00000000..7567f4b3 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/flask_client/apps.py @@ -0,0 +1,107 @@ +from flask import g, redirect, request, session +from ..requests_client import OAuth1Session, OAuth2Session +from ..base_client import ( + BaseApp, OAuthError, + OAuth1Mixin, OAuth2Mixin, OpenIDMixin, +) + + +class FlaskAppMixin: + @property + def token(self): + attr = f'_oauth_token_{self.name}' + token = g.get(attr) + if token: + return token + if self._fetch_token: + token = self._fetch_token() + self.token = token + return token + + @token.setter + def token(self, token): + attr = f'_oauth_token_{self.name}' + setattr(g, attr, token) + + def _get_requested_token(self, *args, **kwargs): + return self.token + + def save_authorize_data(self, **kwargs): + state = kwargs.pop('state', None) + if state: + self.framework.set_state_data(session, state, kwargs) + else: + raise RuntimeError('Missing state value') + + def authorize_redirect(self, redirect_uri=None, **kwargs): + """Create a HTTP Redirect for Authorization Endpoint. + + :param redirect_uri: Callback or redirect URI for authorization. + :param kwargs: Extra parameters to include. + :return: A HTTP redirect response. + """ + rv = self.create_authorization_url(redirect_uri, **kwargs) + self.save_authorize_data(redirect_uri=redirect_uri, **rv) + return redirect(rv['url']) + + +class FlaskOAuth1App(FlaskAppMixin, OAuth1Mixin, BaseApp): + client_cls = OAuth1Session + + def authorize_access_token(self, **kwargs): + """Fetch access token in one step. + + :return: A token dict. + """ + params = request.args.to_dict(flat=True) + state = params.get('oauth_token') + if not state: + raise OAuthError(description='Missing "oauth_token" parameter') + + data = self.framework.get_state_data(session, state) + if not data: + raise OAuthError(description='Missing "request_token" in temporary data') + + params['request_token'] = data['request_token'] + params.update(kwargs) + self.framework.clear_state_data(session, state) + token = self.fetch_access_token(**params) + self.token = token + return token + + +class FlaskOAuth2App(FlaskAppMixin, OAuth2Mixin, OpenIDMixin, BaseApp): + client_cls = OAuth2Session + + def authorize_access_token(self, **kwargs): + """Fetch access token in one step. + + :return: A token dict. + """ + if request.method == 'GET': + error = request.args.get('error') + if error: + description = request.args.get('error_description') + raise OAuthError(error=error, description=description) + + params = { + 'code': request.args['code'], + 'state': request.args.get('state'), + } + else: + params = { + 'code': request.form['code'], + 'state': request.form.get('state'), + } + + claims_options = kwargs.pop('claims_options', None) + state_data = self.framework.get_state_data(session, params.get('state')) + self.framework.clear_state_data(session, params.get('state')) + params = self._format_state_params(state_data, params) + token = self.fetch_access_token(**params, **kwargs) + self.token = token + + if 'id_token' in token and 'nonce' in state_data: + userinfo = self.parse_id_token(token, nonce=state_data['nonce'], claims_options=claims_options) + token['userinfo'] = userinfo + return token diff --git a/.venv/Lib/site-packages/authlib/integrations/flask_client/integration.py b/.venv/Lib/site-packages/authlib/integrations/flask_client/integration.py new file mode 100644 index 00000000..f4ea57e3 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/flask_client/integration.py @@ -0,0 +1,28 @@ +from flask import current_app +from flask.signals import Namespace +from ..base_client import FrameworkIntegration + +_signal = Namespace() +#: signal when token is updated +token_update = _signal.signal('token_update') + + +class FlaskIntegration(FrameworkIntegration): + def update_token(self, token, refresh_token=None, access_token=None): + token_update.send( + current_app, + name=self.name, + token=token, + refresh_token=refresh_token, + access_token=access_token, + ) + + @staticmethod + def load_config(oauth, name, params): + rv = {} + for k in params: + conf_key = f'{name}_{k}'.upper() + v = oauth.app.config.get(conf_key, None) + if v is not None: + rv[k] = v + return rv diff --git a/.venv/Lib/site-packages/authlib/integrations/flask_oauth1/__init__.py b/.venv/Lib/site-packages/authlib/integrations/flask_oauth1/__init__.py new file mode 100644 index 00000000..780b0594 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/flask_oauth1/__init__.py @@ -0,0 +1,9 @@ +# flake8: noqa + +from .authorization_server import AuthorizationServer +from .resource_protector import ResourceProtector, current_credential +from .cache import ( + register_nonce_hooks, + register_temporary_credential_hooks, + create_exists_nonce_func, +) diff --git a/.venv/Lib/site-packages/authlib/integrations/flask_oauth1/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/flask_oauth1/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f01f1f62a4764ad41e4638dfabbff7217f2ba9f0 GIT binary patch literal 588 zcmbVIy-FlO5bmCt{ZUxt)WF%YFP+g@*#k-Qw;LBbh(Xqk{_2X)6UwalXXlt>ryN^V`=M=rm~dR8^5YBcBrpq(9WI#&H&S> z{&ou9RjA+uT>upv*6XT51RI1xDCpI)OyhbJVWfQk6xLYW;Wo#n@Rkb50qXG%qK1U_#V zm3q+EHoyqq?&bT#Qu>K-O>VC*gtj^eu{*tb?j9IdR3-exHQL-<+Z%#;%sHR88Q;HW X-z(@|Y4Rflg5| z{AE&fnu#$q)@>oA$+gr0z`l(}7rkrWi`3 zt_Ld%icQaGiuw$`Mv3iUsI!#dx=RUe(eum(eef;!xdnQLig>=l=46D{{mJxVR#JFb zk&>AOc;K2A<;8497NPEx#E+IlS&1;Zf9lkda_!)>@jwq@D=Q^)aV43}%!txWQF>16 zfdw%mN^wQxmFx{M15`-~i|poB&<8yO>*W1M~rUD_lkpcB8%P}G@JT)x2pby8wl%qV1^Ty~xt zPC$n|{9zmjkV?))rTN5>V~3AN8xZ8fsE31cK9f|E@l-M=a!G}|l~k^A#^mwEMJ}0< zm3Ss04snT864v3;K&ccoU=c2!5x7J=aZMZ^_K>M?I++lgJHa(raW71H0=`2W@J+hI z8*`qpHX`Oky$L!vAo$4&cuqe*M!^()kwyTr*hZo~gJk7z_VeV7| zYFGzZk;l>VOPK@;9j9cu1yQNcZSGFF#wUd+H+xMiH_iQ6348JK%xsmnoC2fMA_%k~ zbAl)*q~x3^aC22!RG9wr3fHq(IcPHfG~wOFr`HYzFK2~hG&L+Bg|yPq5H(!Nm-HkOcsPz??^}@(RLB7NE{_j5(N-rkavA2aEDhK z^>l!Ui)bVob?z?Di4-<13=j4tIiD0IJzQB5DP~zNV%KdTPrA=4FM63W5f{KPg51jc=h3wAh6wGi-DX*v z7VqdTo+l{sxz1BoO3V=Tk5+oS5!X0?RjL?j%d-z$#m>EXR&(ttc1Q8Iv*e(5?UwqPA@O5dvF17M0*(hH}{^V;| zgi2V220a}S&TpXt!pVH>BqE6eNm;hR6BNs;kW$yp`f57}p((JHcks7f2y14bubYD0 zScHW-5nf@JS*cg?R##YN6<@Wb1giCU<{4o0nTeI;TxMZ)S7iiIKzF5ussU=D_e`C- zJbUgSKXdugrK#!JiE)1B{MpG=cdMIBA%*j>1{PKY+481k;rD|lMA{H zG)MO&<%)CA*%T<9ZdaDT8|fX}EJLI?VwWH&q3R@Bca}|@jC@1U=A>OXEDWHrkX3YK zKa7w+1^`0l4XfVXA~%#D*L=H+-ged7SL{86E$)>!sCm0pZ-243|7Gv!i{8;Mn94~<68JQd05YKEgt}YBo97R9{o)9_P}SOxl`SJq|kg+Yd)&_jutyP)ZmBX z1=lW>d<+Vi0t_>t$`T4a0@eG(_6hrm9qClv^_r=YFw!jbw7PFsDxocmxo1}#=1{6m zX_^#MMQ~)TN4am$aBr|WBiL$Zy>H9gAdqA4y6)TG;Qjhl*&6KGH^!c=!=8O3>>Yx$ zA@(l7p3Sp)`#b}|t80Z>W-uI|)Z5A?WOnMu6O;VeiOGrSQ?pakdZ_04`xBFAXU}~# z0F+Nusc*0s{nzUr0H4y2DaFFldsOWfW~k@%q=Y67B6deg%q%F^WE{V0*aLKbxzmj# zw6WQWj-;}QcuF3P);ZfB!$hxl0Qh#5+6ez(ZN3oRr-k>aP5X$D>bq<9HZyU0dSceH z_4Y>HWeT8X{9h;_;RJ*R(m|+Mwy!tIBJ5MC25q_Vx1mM-EVH=ay9kI0gNj*DISKco zQ2CU34EfzX`We(eGl#$vs`iOMKSj}jpp4PIB$hC8F1^{(;0-LE!#L>}OlE{OXdG4z zX6rsHPjh2$vs3E~S72&60svV4syq7R7lrNvTK9os-%+*iXrb?z)_1IAx3vUHlmYw! zLJsg)7|2K*f;|9q8ziI>5+>rXII|Pje+WT!H)w{y&W??Z8RFXo?cBhdZ{#$Lm%jt> z?YDq*v3>W`f!{@c6ICOp3hh7A+JBS}{>|I^F#AWj;2qSwgC)x0j&5`fu1^)ZMzpSx z{8WDGRqM`2vBw|$`UCZy<6j;sw2o@6qxmx>mi9-%k!=PJsuGNqF0H%=90Ryvwp_f7KMUY$DRR|7h!9mqEXzT@XuM`vzvX|dN z1@}_*d;*OTkWp4_)<|L5R%DFb_N?tqn2o7NZhue3gf_^Bx8}Wc8eS$A-C(#6Nzcnzx=_c^-Qvh!uj z-WM%<3oQd$%RrUOx4Xq0o4XU! znz=$aqJ<;*b8vu`AAcCucJ!`Y`NP#Ojum_(nr}q)jTA#2`6;4bC%;#}SXh!6ICMR4 z&Gmk8OVwxvj^NgC&P}Dxy|KhBvcPwEw|WQ$Jh$ZY^)h5cEzK}@Zm_~`BN41Jt`Vc{ z7HfD3-ZnfLaa-l{E7NW1Esai!jZg&#p))H7Dh3|gaJwG0e}?yEJX1IMd{_$}spIpJ zV();~dqnkdTX{6K``tq5uogP3`VJFLA8*KMOIl92OgJ5b)sfR{@VmJPb?N&G+ySgv z=P_TYkH$e?;j+(&$Qix0Ebhj+Ghe>i)4RwK7aro*>VbLnXGDxPXxBvV9dIp`xY78f z-2R3P*!qR1um>5lUtmI@`DI}5i@@IXmO>z^1)_Od(dB#T8hqgzTt8iK9nf3{RM&xG zusL5253G`HYR@^Cto|URR@%3s;d0#(aFv2~d1(=DAR1p#z*T^8ZEA_RbPt^QXCNK} ztEIbnNOs^>kLN1}%1FVbtAOhN!a!9P`aRN&0{~g;MzH1Htp~UM%RlhKKd}D8FD?}P zCpG`cl8ttc(c1)3sBLdYrTT!WEM?M9VMbHb3|*@rTs|ZnsR|-Lhc#f#9Bb#^bfES3){Q)YVbM&ecevTQ1a^4-8G@X#k+O-sb$tjkfOmS*Sf2eZs5WA@~$S?TGRHc7FfVN8d5CIB` zv}p&VGn)qlX$ZA~4LQ$UjzKG9zDr9?;p!Uy1SCT_p-ZSHRv~qG|!> zw}-LU3c76eJ#c_n0iIp<&JtyUqqH3k&rINO*-w@z6SO$(c=1^Q&1Q`}t8cn-oC(^@ z8hO@cvxg9kGVn0=F&eVg?VyXcA4S|61BcW8cQAtmHro+_?EujdLflBR?o4GD7T}^< z58M)^8#!@lA-bd_Q!+V7)$PPw7&4BkB#8j@0J?qrM;1e|iOC@I=`DN%5!S<%@ri6Y zoy|nygc*(-lsgg$)Df)0;}Y&NbOZ?KSiott^E|KKDG8!Vr(=6-1=VNqUd*3>X7wQqz2U5 q&nriGbwP84pSTK+J(^?Bs;%T$U})e~W2m-Azb0MZY%zck;eP;a_B8JR literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/flask_oauth1/__pycache__/cache.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/flask_oauth1/__pycache__/cache.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef86ad5dd2988f10ef79aa799d11fe81e804b6e2 GIT binary patch literal 4502 zcmds4-A^0Y6~FUkj|~`NCmRUMY81AxMgdB9Nm4IDY6+XPijW!-sac_QjAslk#-?}1 zG@(Pq!%8vHN}*L(L5jBWQ@X3OS-mW`epOBUxAHNwnhy+Z+{~$aQ0NEk_gd&I~nlBWtA-nS)c7HyKaX zXJbjJ_CnUlxY_gm-$3pPcf|*!AQZ%us0*K}n^J8oVl3Cj62?kxEMx4mNfCPwH(jx% zM>yPL?|?)gNAmh?`L%idw({D%s_lD~R}VmO!HvIMGnUe(Wl*iIC9R<)jT)JRW$4;+ zF1KQ8R!&Rgt>qj|ZzQaAE~}XaT{q}hFsPx$))F+a+R71kIbzz6n)l7~ZCW~OT8V7Z zXx^PnB$thtHp9BM3@gT+_!>1*>Dw_4W6d3Fsa*RLaM>-kR$!wD?)@#0&td6p#fG!> z;mK_q=r$!=z^pihu`N=?7V#vpr){|idbrsVIOHeFBlywdx^D@@s*fRwJQA>q+ikFb zZ_eq+F{Q?>+=`KP0?AAoej88gPRN~4CNi1DL~`ZD*3Sg;mEicT^s14|TT#)GOv9o~ ze$?kEd_Pt3@jOjC64c};hM2(tS%bVFp~zXv@o`AWY-t2rWY5?v}KI0fhnbZ(~uB4v(w)<>xvfLf5bVo~SbRU9AvTj2>Fbi;xN@2h}$|k0$lX>`x zO}IA++fos0hnp?5dc>v(Z|iRH8L^dP9?&=sKbT|oU-Im)P(Osz9uP-aPh|22J;5fz zASUy8ZfDBA(&@#nwkqD3eIpATCFU*m&YyrV^>?3PTJEhzPVaocZ1G_^Gz2sBoO%%W zU0`?cx1ryM3QD!3hjER48yPC*%aPGaWVF;dx+h_Z&(l+o)?Ve8u;QwmzP*hQtf^Zp zV*YS@RowztCQ~Rq4Q^x*pKfFf%ZSPig*IuD#o} zv*WEjA_m^6hTq=(bvZmzn5lN2xPSHD)!j(BbD+{WQ1Y%l1#FzxRbCSckvanY0a85# zEMk1PJ;K!E`g9E$85Rl*3vHp;90zs2)?FTs0y*nBu+GY)Fyxe;$gd)&4YNd*IS&Vs zXws>)K^=b{Nd*8&SusITN06xGbTe;k2GR~T;c+rV07eEInav3Ts(`bM!%;oiJb;?) z?ZZAqPTk@IHPmUzf^l#6#!ufUevXwjh&P)*2dQCL?0Ns>v;N6)|Ak8bg>vWuVrY20 z5G+Lo%j&yTZRELj{+V{ZtX-^V7Yo6iAC}dDY8}otzMN!mHc?S0O6o+lyRW47akro+ z@dkQ^kpV`AK;{qyUG;-7)Q$R`ldUIqvwA~O?c|sYk+fU4nEu>&8LUffhyO0X(y|7;y*&|1huulO<97TF01yOJm2`UQU=_nE+O5byN=$SlJRlipn{_)=> zLAfOSgD?tM0{u?z^%%~U-ko9$(`^(gcg*ci zKKrB~Ht^|}#bJg|BNcU|q>fa(PZR>&-M@l@nn31#rlt?rw=m=0g1^=Zni`Tee=ek67a5L3SO32gGW!H+~mH{ODn|QT)T7 zNPC}v-yQnV(?$4$wDIq2-VYf!{{P7z*y{%_H!zA@ZaX>*MMo9-9=f)UP%CY{40E!c zVYu>YDdi$|e}vnd0NEn{43m@RzMOp;`_r$=k;|3H<*ln#56FwZd1{yCOBMN2$-B54 zASqJj3HYuNbR2)9iW92+`;56iI{aUZXE68c*^B8UBdmbs&U&Cut>*N6#+art%rOr# w^B^d81))mDO0CzPN+ys8q)~xogG2O|&@J@tkybK9W*D~=6lSsKILbfkKjLVPmjD0& literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/flask_oauth1/__pycache__/resource_protector.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/flask_oauth1/__pycache__/resource_protector.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..13ea15ad2dc5d334812fc8232b56cb02b77c8c17 GIT binary patch literal 6040 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 HroaCJ3B}?M literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/flask_oauth1/authorization_server.py b/.venv/Lib/site-packages/authlib/integrations/flask_oauth1/authorization_server.py new file mode 100644 index 00000000..3a2a5600 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/flask_oauth1/authorization_server.py @@ -0,0 +1,182 @@ +import logging +from werkzeug.utils import import_string +from flask import Response +from flask import request as flask_req +from authlib.oauth1 import ( + OAuth1Request, + AuthorizationServer as _AuthorizationServer, +) +from authlib.common.security import generate_token +from authlib.common.urls import url_encode + +log = logging.getLogger(__name__) + + +class AuthorizationServer(_AuthorizationServer): + """Flask implementation of :class:`authlib.rfc5849.AuthorizationServer`. + Initialize it with Flask app instance, client model class and cache:: + + server = AuthorizationServer(app=app, query_client=query_client) + # or initialize lazily + server = AuthorizationServer() + server.init_app(app, query_client=query_client) + + :param app: A Flask app instance + :param query_client: A function to get client by client_id. The client + model class MUST implement the methods described by + :class:`~authlib.oauth1.rfc5849.ClientMixin`. + :param token_generator: A function to generate token + """ + + def __init__(self, app=None, query_client=None, token_generator=None): + self.app = app + self.query_client = query_client + self.token_generator = token_generator + + self._hooks = { + 'exists_nonce': None, + 'create_temporary_credential': None, + 'get_temporary_credential': None, + 'delete_temporary_credential': None, + 'create_authorization_verifier': None, + 'create_token_credential': None, + } + if app is not None: + self.init_app(app) + + def init_app(self, app, query_client=None, token_generator=None): + if query_client is not None: + self.query_client = query_client + if token_generator is not None: + self.token_generator = token_generator + + if self.token_generator is None: + self.token_generator = self.create_token_generator(app) + + methods = app.config.get('OAUTH1_SUPPORTED_SIGNATURE_METHODS') + if methods and isinstance(methods, (list, tuple)): + self.SUPPORTED_SIGNATURE_METHODS = methods + + self.app = app + + def register_hook(self, name, func): + if name not in self._hooks: + raise ValueError('Invalid "name" of hook') + self._hooks[name] = func + + def create_token_generator(self, app): + token_generator = app.config.get('OAUTH1_TOKEN_GENERATOR') + + if isinstance(token_generator, str): + token_generator = import_string(token_generator) + else: + length = app.config.get('OAUTH1_TOKEN_LENGTH', 42) + + def token_generator(): + return generate_token(length) + + secret_generator = app.config.get('OAUTH1_TOKEN_SECRET_GENERATOR') + if isinstance(secret_generator, str): + secret_generator = import_string(secret_generator) + else: + length = app.config.get('OAUTH1_TOKEN_SECRET_LENGTH', 48) + + def secret_generator(): + return generate_token(length) + + def create_token(): + return { + 'oauth_token': token_generator(), + 'oauth_token_secret': secret_generator() + } + return create_token + + def get_client_by_id(self, client_id): + return self.query_client(client_id) + + def exists_nonce(self, nonce, request): + func = self._hooks['exists_nonce'] + if callable(func): + timestamp = request.timestamp + client_id = request.client_id + token = request.token + return func(nonce, timestamp, client_id, token) + + raise RuntimeError('"exists_nonce" hook is required.') + + def create_temporary_credential(self, request): + func = self._hooks['create_temporary_credential'] + if callable(func): + token = self.token_generator() + return func(token, request.client_id, request.redirect_uri) + raise RuntimeError( + '"create_temporary_credential" hook is required.' + ) + + def get_temporary_credential(self, request): + func = self._hooks['get_temporary_credential'] + if callable(func): + return func(request.token) + + raise RuntimeError( + '"get_temporary_credential" hook is required.' + ) + + def delete_temporary_credential(self, request): + func = self._hooks['delete_temporary_credential'] + if callable(func): + return func(request.token) + + raise RuntimeError( + '"delete_temporary_credential" hook is required.' + ) + + def create_authorization_verifier(self, request): + func = self._hooks['create_authorization_verifier'] + if callable(func): + verifier = generate_token(36) + func(request.credential, request.user, verifier) + return verifier + + raise RuntimeError( + '"create_authorization_verifier" hook is required.' + ) + + def create_token_credential(self, request): + func = self._hooks['create_token_credential'] + if callable(func): + temporary_credential = request.credential + token = self.token_generator() + return func(token, temporary_credential) + + raise RuntimeError( + '"create_token_credential" hook is required.' + ) + + def check_authorization_request(self): + req = self.create_oauth1_request(None) + self.validate_authorization_request(req) + return req + + def create_authorization_response(self, request=None, grant_user=None): + return super()\ + .create_authorization_response(request, grant_user) + + def create_token_response(self, request=None): + return super().create_token_response(request) + + def create_oauth1_request(self, request): + if request is None: + request = flask_req + if request.method in ('POST', 'PUT'): + body = request.form.to_dict(flat=True) + else: + body = None + return OAuth1Request(request.method, request.url, body, request.headers) + + def handle_response(self, status_code, payload, headers): + return Response( + url_encode(payload), + status=status_code, + headers=headers + ) diff --git a/.venv/Lib/site-packages/authlib/integrations/flask_oauth1/cache.py b/.venv/Lib/site-packages/authlib/integrations/flask_oauth1/cache.py new file mode 100644 index 00000000..fdfc9a5a --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/flask_oauth1/cache.py @@ -0,0 +1,80 @@ +from authlib.oauth1 import TemporaryCredential + + +def register_temporary_credential_hooks( + authorization_server, cache, key_prefix='temporary_credential:'): + """Register temporary credential related hooks to authorization server. + + :param authorization_server: AuthorizationServer instance + :param cache: Cache instance + :param key_prefix: key prefix for temporary credential + """ + + def create_temporary_credential(token, client_id, redirect_uri): + key = key_prefix + token['oauth_token'] + token['client_id'] = client_id + if redirect_uri: + token['oauth_callback'] = redirect_uri + + cache.set(key, token, timeout=86400) # cache for one day + return TemporaryCredential(token) + + def get_temporary_credential(oauth_token): + if not oauth_token: + return None + key = key_prefix + oauth_token + value = cache.get(key) + if value: + return TemporaryCredential(value) + + def delete_temporary_credential(oauth_token): + if oauth_token: + key = key_prefix + oauth_token + cache.delete(key) + + def create_authorization_verifier(credential, grant_user, verifier): + key = key_prefix + credential.get_oauth_token() + credential['oauth_verifier'] = verifier + credential['user_id'] = grant_user.get_user_id() + cache.set(key, credential, timeout=86400) + return credential + + authorization_server.register_hook( + 'create_temporary_credential', create_temporary_credential) + authorization_server.register_hook( + 'get_temporary_credential', get_temporary_credential) + authorization_server.register_hook( + 'delete_temporary_credential', delete_temporary_credential) + authorization_server.register_hook( + 'create_authorization_verifier', create_authorization_verifier) + + +def create_exists_nonce_func(cache, key_prefix='nonce:', expires=86400): + """Create an ``exists_nonce`` function that can be used in hooks and + resource protector. + + :param cache: Cache instance + :param key_prefix: key prefix for temporary credential + :param expires: Expire time for nonce + """ + def exists_nonce(nonce, timestamp, client_id, oauth_token): + key = f'{key_prefix}{nonce}-{timestamp}-{client_id}' + if oauth_token: + key = f'{key}-{oauth_token}' + rv = cache.has(key) + cache.set(key, 1, timeout=expires) + return rv + return exists_nonce + + +def register_nonce_hooks( + authorization_server, cache, key_prefix='nonce:', expires=86400): + """Register nonce related hooks to authorization server. + + :param authorization_server: AuthorizationServer instance + :param cache: Cache instance + :param key_prefix: key prefix for temporary credential + :param expires: Expire time for nonce + """ + exists_nonce = create_exists_nonce_func(cache, key_prefix, expires) + authorization_server.register_hook('exists_nonce', exists_nonce) diff --git a/.venv/Lib/site-packages/authlib/integrations/flask_oauth1/resource_protector.py b/.venv/Lib/site-packages/authlib/integrations/flask_oauth1/resource_protector.py new file mode 100644 index 00000000..c941eb42 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/flask_oauth1/resource_protector.py @@ -0,0 +1,113 @@ +import functools +from flask import g, json, Response +from flask import request as _req +from werkzeug.local import LocalProxy +from authlib.consts import default_json_headers +from authlib.oauth1 import ResourceProtector as _ResourceProtector +from authlib.oauth1.errors import OAuth1Error + + +class ResourceProtector(_ResourceProtector): + """A protecting method for resource servers. Initialize a resource + protector with the these method: + + 1. query_client + 2. query_token, + 3. exists_nonce + + Usually, a ``query_client`` method would look like (if using SQLAlchemy):: + + def query_client(client_id): + return Client.query.filter_by(client_id=client_id).first() + + A ``query_token`` method accept two parameters, ``client_id`` and ``oauth_token``:: + + def query_token(client_id, oauth_token): + return Token.query.filter_by(client_id=client_id, oauth_token=oauth_token).first() + + And for ``exists_nonce``, if using cache, we have a built-in hook to create this method:: + + from authlib.integrations.flask_oauth1 import create_exists_nonce_func + + exists_nonce = create_exists_nonce_func(cache) + + Then initialize the resource protector with those methods:: + + require_oauth = ResourceProtector( + app, query_client=query_client, + query_token=query_token, exists_nonce=exists_nonce, + ) + """ + def __init__(self, app=None, query_client=None, + query_token=None, exists_nonce=None): + self.query_client = query_client + self.query_token = query_token + self._exists_nonce = exists_nonce + + self.app = app + if app: + self.init_app(app) + + def init_app(self, app, query_client=None, query_token=None, + exists_nonce=None): + if query_client is not None: + self.query_client = query_client + if query_token is not None: + self.query_token = query_token + if exists_nonce is not None: + self._exists_nonce = exists_nonce + + methods = app.config.get('OAUTH1_SUPPORTED_SIGNATURE_METHODS') + if methods and isinstance(methods, (list, tuple)): + self.SUPPORTED_SIGNATURE_METHODS = methods + + self.app = app + + def get_client_by_id(self, client_id): + return self.query_client(client_id) + + def get_token_credential(self, request): + return self.query_token(request.client_id, request.token) + + def exists_nonce(self, nonce, request): + if not self._exists_nonce: + raise RuntimeError('"exists_nonce" function is required.') + + timestamp = request.timestamp + client_id = request.client_id + token = request.token + return self._exists_nonce(nonce, timestamp, client_id, token) + + def acquire_credential(self): + req = self.validate_request( + _req.method, + _req.url, + _req.form.to_dict(flat=True), + _req.headers + ) + g.authlib_server_oauth1_credential = req.credential + return req.credential + + def __call__(self, scope=None): + def wrapper(f): + @functools.wraps(f) + def decorated(*args, **kwargs): + try: + self.acquire_credential() + except OAuth1Error as error: + body = dict(error.get_body()) + return Response( + json.dumps(body), + status=error.status_code, + headers=default_json_headers, + ) + return f(*args, **kwargs) + return decorated + return wrapper + + +def _get_current_credential(): + return g.get('authlib_server_oauth1_credential') + + +current_credential = LocalProxy(_get_current_credential) diff --git a/.venv/Lib/site-packages/authlib/integrations/flask_oauth2/__init__.py b/.venv/Lib/site-packages/authlib/integrations/flask_oauth2/__init__.py new file mode 100644 index 00000000..170a7190 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/flask_oauth2/__init__.py @@ -0,0 +1,12 @@ +# flake8: noqa + +from .authorization_server import AuthorizationServer +from .resource_protector import ( + ResourceProtector, + current_token, +) +from .signals import ( + client_authenticated, + token_authenticated, + token_revoked, +) diff --git a/.venv/Lib/site-packages/authlib/integrations/flask_oauth2/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/flask_oauth2/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..783bd2707e01ca5720c6769d32649b5446afcd64 GIT binary patch literal 574 zcmbVI%}N6?5KeZt?J6vy?Mv*z76f|`5d=XGBGT$*Sy;B&X${>ZWs(*Yd=4K$d;s6W z^Iko9EA&<`Ce?~~5e(s*pKoTqVIHGsli2ru`V0$eUtO?%-j}oJTIYcjq@X1cG@;b_ zUg-%x@kNjXtJp7VqMp=6BWZ{*32iRuleqRqZF5Yk=JC|rDCBp!;Y#)aXMnL+ZTCQ{ zDKfZ3Wq=ulRm7%^~1lAne(0nBGQe)kv8V*7WPsH7cEcwYn%2dJSD7{w0tFxSq zb=m^~VgPn71IZw5&p^)7b3RBlH?TXgMfnJH>UJvmpu?qs5w0$xJHs;9<4iejuajk5 za+784$?Y;c6snk(aD-b{+1*p$TbTQl(s`ZG?hD!f`RATby*c?C!ob!23ox=9d;kus Brg8uP literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/flask_oauth2/__pycache__/authorization_server.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/flask_oauth2/__pycache__/authorization_server.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cec81608ce2ca7172913df89c7215492ac814178 GIT binary patch literal 8964 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/flask_oauth2/__pycache__/requests.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/flask_oauth2/__pycache__/requests.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bc0a973f2c2b91602fe310c83e852db79599351c GIT binary patch literal 2430 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 Orrw{q7RNsxGXDizq9!l^ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/flask_oauth2/__pycache__/signals.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/flask_oauth2/__pycache__/signals.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ac7a5f7e6250d47ac2dac47e25831ba2a5f7743b GIT binary patch literal 582 zcmZ`#y-UMD6u;|7s+EY+(mLrN3PEhZu^&!?4&va)QUc+cJnPZqQgUg*rFK+s>Jmo> zQN-E*BZUr^Uu9x(i(q%`g|2zchPFCX|mY!doRy zn~Yf8joue#^tcSAIJzmpy6Ffc0rzMu5WSyll{LdLDQjv+&hg<6Fo# z!KN#V#?e1>5b&177(b!q;I}_#bLYy%+T~h5^CqE%CBHZ51*_Fzu{J8!0+biz{DMC_ kn7uk1&Z(n0wJ!^*xahM13s%a*LS$vSc~&HMQ{Bk?lrw<6E$^ zAU*)!qa(VNDO;p6m4$m8hlU^+5YFkRd;a&&^WyWzLLrO9^S%3-9?1xOg<$(g@#c0Z zHt&&zEbJhL31$+Jm`r4rAPJTvNtPlhj4a8L9fhSynq^3aWl1*D5>AfgNuCu*ffY%S zl}IVllTMjcNQG5NRm3SvaSm9G)G(SOEByhJLn|{xYIX%ps40FhJn8ne(Rk1?dM~w> zG3;r_ym~JVhT2BkF`l1lC;d_9^@tzd8%L9Kk)oruI|E+ZlV6QHgUN2G$o%}QJy~IB zL+05t?JB%H2Jng&T)VT4&~j|*hCII;sfpO$jO?4UX6!6S&N$jn7t5-|OIi?6KeRnJ z{$DLBx~Hz-s#F}8>-fIst0liCL?5o#&jG~sB0m900#X14kOmY0B|s5S22=o5fxh~H z7fmsxk)ju$pAV-~%aoi6esU3}Wyo<_B!vQYz2o0rY);9J+vZg_5L26QXK zlw2_k({T*r6S@^4y0hC)^qFVb?pz;x7o(mzdlTpb$|##sp9VAP&Zu5rQg^AJ+EYES zL;83jOy-;hdOT>uc0)S%O?df1<1!2vZ{wN`!?0aDG>rP<`Y!#HdDfLfpZSkOW%x{j zZvtx>W4x9WEUnT1LmA;NzCkbkwAPXg1^*3cgxex{>-Y5q9o_u8)+r?ilf`(az|Vgu G2LAz8M<<>D literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/httpx_client/__pycache__/assertion_client.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/httpx_client/__pycache__/assertion_client.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..22e61d27042e613c004954751d319ea9d0c394d1 GIT binary patch literal 4427 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 Sxt}+O2*{(?Q}Vwk&Ej8OLSUu< literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/httpx_client/assertion_client.py b/.venv/Lib/site-packages/authlib/integrations/httpx_client/assertion_client.py new file mode 100644 index 00000000..83dc58b2 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/httpx_client/assertion_client.py @@ -0,0 +1,81 @@ +import httpx +from httpx import Response, USE_CLIENT_DEFAULT +from authlib.oauth2.rfc7521 import AssertionClient as _AssertionClient +from authlib.oauth2.rfc7523 import JWTBearerGrant +from .utils import extract_client_kwargs +from .oauth2_client import OAuth2Auth +from ..base_client import OAuthError + +__all__ = ['AsyncAssertionClient'] + + +class AsyncAssertionClient(_AssertionClient, httpx.AsyncClient): + token_auth_class = OAuth2Auth + oauth_error_class = OAuthError + JWT_BEARER_GRANT_TYPE = JWTBearerGrant.GRANT_TYPE + ASSERTION_METHODS = { + JWT_BEARER_GRANT_TYPE: JWTBearerGrant.sign, + } + DEFAULT_GRANT_TYPE = JWT_BEARER_GRANT_TYPE + + def __init__(self, token_endpoint, issuer, subject, audience=None, grant_type=None, + claims=None, token_placement='header', scope=None, **kwargs): + + client_kwargs = extract_client_kwargs(kwargs) + httpx.AsyncClient.__init__(self, **client_kwargs) + + _AssertionClient.__init__( + self, session=None, + token_endpoint=token_endpoint, issuer=issuer, subject=subject, + audience=audience, grant_type=grant_type, claims=claims, + token_placement=token_placement, scope=scope, **kwargs + ) + + async def request(self, method, url, withhold_token=False, auth=USE_CLIENT_DEFAULT, **kwargs) -> Response: + """Send request with auto refresh token feature.""" + if not withhold_token and auth is USE_CLIENT_DEFAULT: + if not self.token or self.token.is_expired(): + await self.refresh_token() + + auth = self.token_auth + return await super().request( + method, url, auth=auth, **kwargs) + + async def _refresh_token(self, data): + resp = await self.request( + 'POST', self.token_endpoint, data=data, withhold_token=True) + + return self.parse_response_token(resp) + + +class AssertionClient(_AssertionClient, httpx.Client): + token_auth_class = OAuth2Auth + oauth_error_class = OAuthError + JWT_BEARER_GRANT_TYPE = JWTBearerGrant.GRANT_TYPE + ASSERTION_METHODS = { + JWT_BEARER_GRANT_TYPE: JWTBearerGrant.sign, + } + DEFAULT_GRANT_TYPE = JWT_BEARER_GRANT_TYPE + + def __init__(self, token_endpoint, issuer, subject, audience=None, grant_type=None, + claims=None, token_placement='header', scope=None, **kwargs): + + client_kwargs = extract_client_kwargs(kwargs) + httpx.Client.__init__(self, **client_kwargs) + + _AssertionClient.__init__( + self, session=self, + token_endpoint=token_endpoint, issuer=issuer, subject=subject, + audience=audience, grant_type=grant_type, claims=claims, + token_placement=token_placement, scope=scope, **kwargs + ) + + def request(self, method, url, withhold_token=False, auth=USE_CLIENT_DEFAULT, **kwargs): + """Send request with auto refresh token feature.""" + if not withhold_token and auth is USE_CLIENT_DEFAULT: + if not self.token or self.token.is_expired(): + self.refresh_token() + + auth = self.token_auth + return super().request( + method, url, auth=auth, **kwargs) diff --git a/.venv/Lib/site-packages/authlib/integrations/httpx_client/oauth1_client.py b/.venv/Lib/site-packages/authlib/integrations/httpx_client/oauth1_client.py new file mode 100644 index 00000000..ce031c97 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/httpx_client/oauth1_client.py @@ -0,0 +1,102 @@ +import typing +import httpx +from httpx import Auth, Request, Response +from authlib.oauth1 import ( + SIGNATURE_HMAC_SHA1, + SIGNATURE_TYPE_HEADER, +) +from authlib.common.encoding import to_unicode +from authlib.oauth1 import ClientAuth +from authlib.oauth1.client import OAuth1Client as _OAuth1Client +from .utils import build_request, extract_client_kwargs +from ..base_client import OAuthError + + +class OAuth1Auth(Auth, ClientAuth): + """Signs the httpx request using OAuth 1 (RFC5849)""" + requires_request_body = True + + def auth_flow(self, request: Request) -> typing.Generator[Request, Response, None]: + url, headers, body = self.prepare( + request.method, str(request.url), request.headers, request.content) + headers['Content-Length'] = str(len(body)) + yield build_request(url=url, headers=headers, body=body, initial_request=request) + + +class AsyncOAuth1Client(_OAuth1Client, httpx.AsyncClient): + auth_class = OAuth1Auth + + def __init__(self, client_id, client_secret=None, + token=None, token_secret=None, + redirect_uri=None, rsa_key=None, verifier=None, + signature_method=SIGNATURE_HMAC_SHA1, + signature_type=SIGNATURE_TYPE_HEADER, + force_include_body=False, **kwargs): + + _client_kwargs = extract_client_kwargs(kwargs) + httpx.AsyncClient.__init__(self, **_client_kwargs) + + _OAuth1Client.__init__( + self, None, + client_id=client_id, client_secret=client_secret, + token=token, token_secret=token_secret, + redirect_uri=redirect_uri, rsa_key=rsa_key, verifier=verifier, + signature_method=signature_method, signature_type=signature_type, + force_include_body=force_include_body, **kwargs) + + async def fetch_access_token(self, url, verifier=None, **kwargs): + """Method for fetching an access token from the token endpoint. + + This is the final step in the OAuth 1 workflow. An access token is + obtained using all previously obtained credentials, including the + verifier from the authorization step. + + :param url: Access Token endpoint. + :param verifier: A verifier string to prove authorization was granted. + :param kwargs: Extra parameters to include for fetching access token. + :return: A token dict. + """ + if verifier: + self.auth.verifier = verifier + if not self.auth.verifier: + self.handle_error('missing_verifier', 'Missing "verifier" value') + token = await self._fetch_token(url, **kwargs) + self.auth.verifier = None + return token + + async def _fetch_token(self, url, **kwargs): + resp = await self.post(url, **kwargs) + text = await resp.aread() + token = self.parse_response_token(resp.status_code, to_unicode(text)) + self.token = token + return token + + @staticmethod + def handle_error(error_type, error_description): + raise OAuthError(error_type, error_description) + + +class OAuth1Client(_OAuth1Client, httpx.Client): + auth_class = OAuth1Auth + + def __init__(self, client_id, client_secret=None, + token=None, token_secret=None, + redirect_uri=None, rsa_key=None, verifier=None, + signature_method=SIGNATURE_HMAC_SHA1, + signature_type=SIGNATURE_TYPE_HEADER, + force_include_body=False, **kwargs): + + _client_kwargs = extract_client_kwargs(kwargs) + httpx.Client.__init__(self, **_client_kwargs) + + _OAuth1Client.__init__( + self, self, + client_id=client_id, client_secret=client_secret, + token=token, token_secret=token_secret, + redirect_uri=redirect_uri, rsa_key=rsa_key, verifier=verifier, + signature_method=signature_method, signature_type=signature_type, + force_include_body=force_include_body, **kwargs) + + @staticmethod + def handle_error(error_type, error_description): + raise OAuthError(error_type, error_description) diff --git a/.venv/Lib/site-packages/authlib/integrations/httpx_client/oauth2_client.py b/.venv/Lib/site-packages/authlib/integrations/httpx_client/oauth2_client.py new file mode 100644 index 00000000..d4ee0f58 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/httpx_client/oauth2_client.py @@ -0,0 +1,220 @@ +import typing +from contextlib import asynccontextmanager + +import httpx +from httpx import Auth, Request, Response, USE_CLIENT_DEFAULT +from anyio import Lock # Import after httpx so import errors refer to httpx +from authlib.common.urls import url_decode +from authlib.oauth2.client import OAuth2Client as _OAuth2Client +from authlib.oauth2.auth import ClientAuth, TokenAuth +from .utils import HTTPX_CLIENT_KWARGS, build_request +from ..base_client import ( + OAuthError, + InvalidTokenError, + MissingTokenError, + UnsupportedTokenTypeError, +) + +__all__ = [ + 'OAuth2Auth', 'OAuth2ClientAuth', + 'AsyncOAuth2Client', 'OAuth2Client', +] + + +class OAuth2Auth(Auth, TokenAuth): + """Sign requests for OAuth 2.0, currently only bearer token is supported.""" + requires_request_body = True + + def auth_flow(self, request: Request) -> typing.Generator[Request, Response, None]: + try: + url, headers, body = self.prepare( + str(request.url), request.headers, request.content) + headers['Content-Length'] = str(len(body)) + yield build_request(url=url, headers=headers, body=body, initial_request=request) + except KeyError as error: + description = f'Unsupported token_type: {str(error)}' + raise UnsupportedTokenTypeError(description=description) + + +class OAuth2ClientAuth(Auth, ClientAuth): + requires_request_body = True + + def auth_flow(self, request: Request) -> typing.Generator[Request, Response, None]: + url, headers, body = self.prepare( + request.method, str(request.url), request.headers, request.content) + headers['Content-Length'] = str(len(body)) + yield build_request(url=url, headers=headers, body=body, initial_request=request) + + +class AsyncOAuth2Client(_OAuth2Client, httpx.AsyncClient): + SESSION_REQUEST_PARAMS = HTTPX_CLIENT_KWARGS + + client_auth_class = OAuth2ClientAuth + token_auth_class = OAuth2Auth + oauth_error_class = OAuthError + + def __init__(self, client_id=None, client_secret=None, + token_endpoint_auth_method=None, + revocation_endpoint_auth_method=None, + scope=None, redirect_uri=None, + token=None, token_placement='header', + update_token=None, **kwargs): + + # extract httpx.Client kwargs + client_kwargs = self._extract_session_request_params(kwargs) + httpx.AsyncClient.__init__(self, **client_kwargs) + + # We use a Lock to synchronize coroutines to prevent + # multiple concurrent attempts to refresh the same token + self._token_refresh_lock = Lock() + + _OAuth2Client.__init__( + self, session=None, + client_id=client_id, client_secret=client_secret, + token_endpoint_auth_method=token_endpoint_auth_method, + revocation_endpoint_auth_method=revocation_endpoint_auth_method, + scope=scope, redirect_uri=redirect_uri, + token=token, token_placement=token_placement, + update_token=update_token, **kwargs + ) + + async def request(self, method, url, withhold_token=False, auth=USE_CLIENT_DEFAULT, **kwargs): + if not withhold_token and auth is USE_CLIENT_DEFAULT: + if not self.token: + raise MissingTokenError() + + await self.ensure_active_token(self.token) + + auth = self.token_auth + + return await super().request( + method, url, auth=auth, **kwargs) + + @asynccontextmanager + async def stream(self, method, url, withhold_token=False, auth=USE_CLIENT_DEFAULT, **kwargs): + if not withhold_token and auth is USE_CLIENT_DEFAULT: + if not self.token: + raise MissingTokenError() + + await self.ensure_active_token(self.token) + + auth = self.token_auth + + async with super().stream( + method, url, auth=auth, **kwargs) as resp: + yield resp + + async def ensure_active_token(self, token): + async with self._token_refresh_lock: + if self.token.is_expired(): + refresh_token = token.get('refresh_token') + url = self.metadata.get('token_endpoint') + if refresh_token and url: + await self.refresh_token(url, refresh_token=refresh_token) + elif self.metadata.get('grant_type') == 'client_credentials': + access_token = token['access_token'] + new_token = await self.fetch_token(url, grant_type='client_credentials') + if self.update_token: + await self.update_token(new_token, access_token=access_token) + else: + raise InvalidTokenError() + + async def _fetch_token(self, url, body='', headers=None, auth=USE_CLIENT_DEFAULT, + method='POST', **kwargs): + if method.upper() == 'POST': + resp = await self.post( + url, data=dict(url_decode(body)), headers=headers, + auth=auth, **kwargs) + else: + if '?' in url: + url = '&'.join([url, body]) + else: + url = '?'.join([url, body]) + resp = await self.get(url, headers=headers, auth=auth, **kwargs) + + for hook in self.compliance_hook['access_token_response']: + resp = hook(resp) + + return self.parse_response_token(resp) + + async def _refresh_token(self, url, refresh_token=None, body='', + headers=None, auth=USE_CLIENT_DEFAULT, **kwargs): + resp = await self.post( + url, data=dict(url_decode(body)), headers=headers, + auth=auth, **kwargs) + + for hook in self.compliance_hook['refresh_token_response']: + resp = hook(resp) + + token = self.parse_response_token(resp) + if 'refresh_token' not in token: + self.token['refresh_token'] = refresh_token + + if self.update_token: + await self.update_token(self.token, refresh_token=refresh_token) + + return self.token + + def _http_post(self, url, body=None, auth=USE_CLIENT_DEFAULT, headers=None, **kwargs): + return self.post( + url, data=dict(url_decode(body)), + headers=headers, auth=auth, **kwargs) + + +class OAuth2Client(_OAuth2Client, httpx.Client): + SESSION_REQUEST_PARAMS = HTTPX_CLIENT_KWARGS + + client_auth_class = OAuth2ClientAuth + token_auth_class = OAuth2Auth + oauth_error_class = OAuthError + + def __init__(self, client_id=None, client_secret=None, + token_endpoint_auth_method=None, + revocation_endpoint_auth_method=None, + scope=None, redirect_uri=None, + token=None, token_placement='header', + update_token=None, **kwargs): + + # extract httpx.Client kwargs + client_kwargs = self._extract_session_request_params(kwargs) + httpx.Client.__init__(self, **client_kwargs) + + _OAuth2Client.__init__( + self, session=self, + client_id=client_id, client_secret=client_secret, + token_endpoint_auth_method=token_endpoint_auth_method, + revocation_endpoint_auth_method=revocation_endpoint_auth_method, + scope=scope, redirect_uri=redirect_uri, + token=token, token_placement=token_placement, + update_token=update_token, **kwargs + ) + + @staticmethod + def handle_error(error_type, error_description): + raise OAuthError(error_type, error_description) + + def request(self, method, url, withhold_token=False, auth=USE_CLIENT_DEFAULT, **kwargs): + if not withhold_token and auth is USE_CLIENT_DEFAULT: + if not self.token: + raise MissingTokenError() + + if not self.ensure_active_token(self.token): + raise InvalidTokenError() + + auth = self.token_auth + + return super().request( + method, url, auth=auth, **kwargs) + + def stream(self, method, url, withhold_token=False, auth=USE_CLIENT_DEFAULT, **kwargs): + if not withhold_token and auth is USE_CLIENT_DEFAULT: + if not self.token: + raise MissingTokenError() + + if not self.ensure_active_token(self.token): + raise InvalidTokenError() + + auth = self.token_auth + + return super().stream( + method, url, auth=auth, **kwargs) diff --git a/.venv/Lib/site-packages/authlib/integrations/httpx_client/utils.py b/.venv/Lib/site-packages/authlib/integrations/httpx_client/utils.py new file mode 100644 index 00000000..8f19f37b --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/httpx_client/utils.py @@ -0,0 +1,30 @@ +from httpx import Request + +HTTPX_CLIENT_KWARGS = [ + 'headers', 'cookies', 'verify', 'cert', 'http1', 'http2', + 'proxies', 'timeout', 'follow_redirects', 'limits', 'max_redirects', + 'event_hooks', 'base_url', 'transport', 'app', 'trust_env', +] + + +def extract_client_kwargs(kwargs): + client_kwargs = {} + for k in HTTPX_CLIENT_KWARGS: + if k in kwargs: + client_kwargs[k] = kwargs.pop(k) + return client_kwargs + + +def build_request(url, headers, body, initial_request: Request) -> Request: + """Make sure that all the data from initial request is passed to the updated object""" + updated_request = Request( + method=initial_request.method, + url=url, + headers=headers, + content=body + ) + + if hasattr(initial_request, 'extensions'): + updated_request.extensions = initial_request.extensions + + return updated_request diff --git a/.venv/Lib/site-packages/authlib/integrations/requests_client/__init__.py b/.venv/Lib/site-packages/authlib/integrations/requests_client/__init__.py new file mode 100644 index 00000000..fcbdec32 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/requests_client/__init__.py @@ -0,0 +1,22 @@ +from .oauth1_session import OAuth1Session, OAuth1Auth +from .oauth2_session import OAuth2Session, OAuth2Auth +from .assertion_session import AssertionSession +from ..base_client import OAuthError +from authlib.oauth1 import ( + SIGNATURE_HMAC_SHA1, + SIGNATURE_RSA_SHA1, + SIGNATURE_PLAINTEXT, + SIGNATURE_TYPE_HEADER, + SIGNATURE_TYPE_QUERY, + SIGNATURE_TYPE_BODY, +) + + +__all__ = [ + 'OAuthError', + 'OAuth1Session', 'OAuth1Auth', + 'SIGNATURE_HMAC_SHA1', 'SIGNATURE_RSA_SHA1', 'SIGNATURE_PLAINTEXT', + 'SIGNATURE_TYPE_HEADER', 'SIGNATURE_TYPE_QUERY', 'SIGNATURE_TYPE_BODY', + 'OAuth2Session', 'OAuth2Auth', + 'AssertionSession', +] diff --git a/.venv/Lib/site-packages/authlib/integrations/requests_client/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/requests_client/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7d93605faed1a73abb829dee3423e0172d0173c9 GIT binary patch literal 933 zcmb`F&u`N(6vyrKNBS#mH->~bbIE~Lo3sl;NP$M{q|uH3kf;^ON*k|4*vYWdN!<7Y zxO3-%_yf4|H}p99%Bi~^gmENGD^vT{;=#6f zuoR)JJ3&_u9_B+}$|4J!j>+ z6L@yw9C!Ne>%P3d3G5HgR0`K=xm~&UoBP$k?GEpjS_VHqZ4K=TFRDg(MkA|H)~IM$ z8dZ&&MqMMPk=HO4I`*!t#=gELELQil$&@MwYh}Gx?)bMCv=((bSswX<;4uwJlq~y_ zRh^uMqsFSrzq^wr#y+JOe+Abn9k`*bC*C*?!f4_R;`4snAHNk|moUOcgcC6)(U^FR zOA=jrC*jBwVL~2Xs33nrgqK!shEYN$+}EE|G&y-UB_a`NlTD1nC`>SJT)e+2JY{h( zrQ{iZsEX^qNPJgVWFUlB;BfY*`FDSF2DauEcr@Fd3&VuQ0{lPhnPr_X#RpSA{DC^c EFPHlLMgRZ+ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/requests_client/__pycache__/assertion_session.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/requests_client/__pycache__/assertion_session.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..caaf0174748685d5d1940e12889c178564b5c8c3 GIT binary patch literal 3040 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/requests_client/__pycache__/oauth2_session.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/requests_client/__pycache__/oauth2_session.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..29d94c8daf7589967db97ab128d7a097cb9c2733 GIT binary patch literal 6306 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/requests_client/assertion_session.py b/.venv/Lib/site-packages/authlib/integrations/requests_client/assertion_session.py new file mode 100644 index 00000000..d07c0016 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/requests_client/assertion_session.py @@ -0,0 +1,46 @@ +from requests import Session +from authlib.oauth2.rfc7521 import AssertionClient +from authlib.oauth2.rfc7523 import JWTBearerGrant +from .oauth2_session import OAuth2Auth +from .utils import update_session_configure + + +class AssertionAuth(OAuth2Auth): + def ensure_active_token(self): + if not self.token or self.token.is_expired() and self.client: + return self.client.refresh_token() + + +class AssertionSession(AssertionClient, Session): + """Constructs a new Assertion Framework for OAuth 2.0 Authorization Grants + per RFC7521_. + + .. _RFC7521: https://tools.ietf.org/html/rfc7521 + """ + token_auth_class = AssertionAuth + JWT_BEARER_GRANT_TYPE = JWTBearerGrant.GRANT_TYPE + ASSERTION_METHODS = { + JWT_BEARER_GRANT_TYPE: JWTBearerGrant.sign, + } + DEFAULT_GRANT_TYPE = JWT_BEARER_GRANT_TYPE + + def __init__(self, token_endpoint, issuer, subject, audience=None, grant_type=None, + claims=None, token_placement='header', scope=None, default_timeout=None, **kwargs): + Session.__init__(self) + self.default_timeout = default_timeout + update_session_configure(self, kwargs) + AssertionClient.__init__( + self, session=self, + token_endpoint=token_endpoint, issuer=issuer, subject=subject, + audience=audience, grant_type=grant_type, claims=claims, + token_placement=token_placement, scope=scope, **kwargs + ) + + def request(self, method, url, withhold_token=False, auth=None, **kwargs): + """Send request with auto refresh token feature.""" + if self.default_timeout: + kwargs.setdefault('timeout', self.default_timeout) + if not withhold_token and auth is None: + auth = self.token_auth + return super().request( + method, url, auth=auth, **kwargs) diff --git a/.venv/Lib/site-packages/authlib/integrations/requests_client/oauth1_session.py b/.venv/Lib/site-packages/authlib/integrations/requests_client/oauth1_session.py new file mode 100644 index 00000000..8c49fa98 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/requests_client/oauth1_session.py @@ -0,0 +1,59 @@ +from requests import Session +from requests.auth import AuthBase +from authlib.oauth1 import ( + SIGNATURE_HMAC_SHA1, + SIGNATURE_TYPE_HEADER, +) +from authlib.common.encoding import to_native +from authlib.oauth1 import ClientAuth +from authlib.oauth1.client import OAuth1Client +from ..base_client import OAuthError +from .utils import update_session_configure + + +class OAuth1Auth(AuthBase, ClientAuth): + """Signs the request using OAuth 1 (RFC5849)""" + + def __call__(self, req): + url, headers, body = self.prepare( + req.method, req.url, req.headers, req.body) + + req.url = to_native(url) + req.prepare_headers(headers) + if body: + req.body = body + return req + + +class OAuth1Session(OAuth1Client, Session): + auth_class = OAuth1Auth + + def __init__(self, client_id, client_secret=None, + token=None, token_secret=None, + redirect_uri=None, rsa_key=None, verifier=None, + signature_method=SIGNATURE_HMAC_SHA1, + signature_type=SIGNATURE_TYPE_HEADER, + force_include_body=False, **kwargs): + Session.__init__(self) + update_session_configure(self, kwargs) + OAuth1Client.__init__( + self, session=self, + client_id=client_id, client_secret=client_secret, + token=token, token_secret=token_secret, + redirect_uri=redirect_uri, rsa_key=rsa_key, verifier=verifier, + signature_method=signature_method, signature_type=signature_type, + force_include_body=force_include_body, **kwargs) + + def rebuild_auth(self, prepared_request, response): + """When being redirected we should always strip Authorization + header, since nonce may not be reused as per OAuth spec. + """ + if 'Authorization' in prepared_request.headers: + # If we get redirected to a new host, we should strip out + # any authentication headers. + prepared_request.headers.pop('Authorization', True) + prepared_request.prepare_auth(self.auth) + + @staticmethod + def handle_error(error_type, error_description): + raise OAuthError(error_type, error_description) diff --git a/.venv/Lib/site-packages/authlib/integrations/requests_client/oauth2_session.py b/.venv/Lib/site-packages/authlib/integrations/requests_client/oauth2_session.py new file mode 100644 index 00000000..9e2426a2 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/requests_client/oauth2_session.py @@ -0,0 +1,110 @@ +from requests import Session +from requests.auth import AuthBase +from authlib.oauth2.client import OAuth2Client +from authlib.oauth2.auth import ClientAuth, TokenAuth +from ..base_client import ( + OAuthError, + InvalidTokenError, + MissingTokenError, + UnsupportedTokenTypeError, +) +from .utils import update_session_configure + +__all__ = ['OAuth2Session', 'OAuth2Auth'] + + +class OAuth2Auth(AuthBase, TokenAuth): + """Sign requests for OAuth 2.0, currently only bearer token is supported.""" + + def ensure_active_token(self): + if self.client and not self.client.ensure_active_token(self.token): + raise InvalidTokenError() + + def __call__(self, req): + self.ensure_active_token() + try: + req.url, req.headers, req.body = self.prepare( + req.url, req.headers, req.body) + except KeyError as error: + description = f'Unsupported token_type: {str(error)}' + raise UnsupportedTokenTypeError(description=description) + return req + + +class OAuth2ClientAuth(AuthBase, ClientAuth): + """Attaches OAuth Client Authentication to the given Request object. + """ + def __call__(self, req): + req.url, req.headers, req.body = self.prepare( + req.method, req.url, req.headers, req.body + ) + return req + + +class OAuth2Session(OAuth2Client, Session): + """Construct a new OAuth 2 client requests session. + + :param client_id: Client ID, which you get from client registration. + :param client_secret: Client Secret, which you get from registration. + :param authorization_endpoint: URL of the authorization server's + authorization endpoint. + :param token_endpoint: URL of the authorization server's token endpoint. + :param token_endpoint_auth_method: client authentication method for + token endpoint. + :param revocation_endpoint: URL of the authorization server's OAuth 2.0 + revocation endpoint. + :param revocation_endpoint_auth_method: client authentication method for + revocation endpoint. + :param scope: Scope that you needed to access user resources. + :param state: Shared secret to prevent CSRF attack. + :param redirect_uri: Redirect URI you registered as callback. + :param token: A dict of token attributes such as ``access_token``, + ``token_type`` and ``expires_at``. + :param token_placement: The place to put token in HTTP request. Available + values: "header", "body", "uri". + :param update_token: A function for you to update token. It accept a + :class:`OAuth2Token` as parameter. + :param default_timeout: If settled, every requests will have a default timeout. + """ + client_auth_class = OAuth2ClientAuth + token_auth_class = OAuth2Auth + oauth_error_class = OAuthError + SESSION_REQUEST_PARAMS = ( + 'allow_redirects', 'timeout', 'cookies', 'files', + 'proxies', 'hooks', 'stream', 'verify', 'cert', 'json' + ) + + def __init__(self, client_id=None, client_secret=None, + token_endpoint_auth_method=None, + revocation_endpoint_auth_method=None, + scope=None, state=None, redirect_uri=None, + token=None, token_placement='header', + update_token=None, default_timeout=None, **kwargs): + Session.__init__(self) + self.default_timeout = default_timeout + update_session_configure(self, kwargs) + + OAuth2Client.__init__( + self, session=self, + client_id=client_id, client_secret=client_secret, + token_endpoint_auth_method=token_endpoint_auth_method, + revocation_endpoint_auth_method=revocation_endpoint_auth_method, + scope=scope, state=state, redirect_uri=redirect_uri, + token=token, token_placement=token_placement, + update_token=update_token, **kwargs + ) + + def fetch_access_token(self, url=None, **kwargs): + """Alias for fetch_token.""" + return self.fetch_token(url, **kwargs) + + def request(self, method, url, withhold_token=False, auth=None, **kwargs): + """Send request with auto refresh token feature (if available).""" + if self.default_timeout: + kwargs.setdefault('timeout', self.default_timeout) + if not withhold_token and auth is None: + if not self.token: + raise MissingTokenError() + auth = self.token_auth + return super().request( + method, url, auth=auth, **kwargs) diff --git a/.venv/Lib/site-packages/authlib/integrations/requests_client/utils.py b/.venv/Lib/site-packages/authlib/integrations/requests_client/utils.py new file mode 100644 index 00000000..53a07db3 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/requests_client/utils.py @@ -0,0 +1,10 @@ +REQUESTS_SESSION_KWARGS = [ + 'proxies', 'hooks', 'stream', 'verify', 'cert', + 'max_redirects', 'trust_env', +] + + +def update_session_configure(session, kwargs): + for k in REQUESTS_SESSION_KWARGS: + if k in kwargs: + setattr(session, k, kwargs.pop(k)) diff --git a/.venv/Lib/site-packages/authlib/integrations/sqla_oauth2/__init__.py b/.venv/Lib/site-packages/authlib/integrations/sqla_oauth2/__init__.py new file mode 100644 index 00000000..1964aa1a --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/sqla_oauth2/__init__.py @@ -0,0 +1,17 @@ +from .client_mixin import OAuth2ClientMixin +from .tokens_mixins import OAuth2AuthorizationCodeMixin, OAuth2TokenMixin +from .functions import ( + create_query_client_func, + create_save_token_func, + create_query_token_func, + create_revocation_endpoint, + create_bearer_token_validator, +) + + +__all__ = [ + 'OAuth2ClientMixin', 'OAuth2AuthorizationCodeMixin', 'OAuth2TokenMixin', + 'create_query_client_func', 'create_save_token_func', + 'create_query_token_func', 'create_revocation_endpoint', + 'create_bearer_token_validator', +] diff --git a/.venv/Lib/site-packages/authlib/integrations/sqla_oauth2/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/sqla_oauth2/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..190f019231016324d15d94ffbaec532f7ea6f337 GIT binary patch literal 740 zcmbtR%W4!s6s_u>e#|5TF$)#Zots9?K$aqcM52NZ(70(Dikj}5Ns)R?s%jdOm1}>% zy&LfZ{EsX{ZC$w=$S!WI>gk{XU3t4W-S?ip=RWGocsxShem?yMcO!(p2j|kf-`V-D ze|=(e<5pky=M$)21F2LX}*X@D$19$*+CEc#Wk?$-M*MHsqEbmOiKL%NXpt>cDal&}T!Pf3>% zLOCboD?0ZT(8a-%2UV>aCTG<4b@f)vaMdQX=Rv&`*Z&j zoq?&SUp;5ji60tfy4!-8m?KV!3e@(55GI)=WNUtWkv|lwS#WryH+|u7vF4+PWsEUC jL-$Uvo-_3P^lxVwr8rum|AozD&8u9(hb%mL!?*JbM<~|? literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/sqla_oauth2/__pycache__/client_mixin.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/sqla_oauth2/__pycache__/client_mixin.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..17bc311c0df144094efb72273b9e118ce1313cae GIT binary patch literal 8496 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 dsv_3PwUrqaHKA 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/starlette_client/__pycache__/integration.cpython-311.pyc b/.venv/Lib/site-packages/authlib/integrations/starlette_client/__pycache__/integration.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65cdf540a2e2121ff53f9376071312966f0288e6 GIT binary patch literal 4090 zcmbVPO>7&-6`uViDJ?~cq$OESUD~2t({`u^anZzZlNkPy0tG5y*+$JOU97l6i4y<1 zyOJY!)jEh#u&sf}h5!kOUGUJl3Y>!uE}%mXDbPa>J&*zc5d#=7&`Wb;pdJMG(l@*0 zilk{+=`+;KO9STu@M;Vx1|?0(E4^aOr(iF;IL5=C9# z(&|K%C)|bX65%hU5(aUPDf+B3oyNrd)4Y+&WtH@|ESNeUOI5Uj*s9g}V9uk@~6fKPn12;v1 zaPxR6LF3dYJSd;RZ+8R4IAS0iCYo#Xq9Ws{O^V4phV~~;-)FGkzv6D7HSV|kGHbFr ztD;HdK}G`};5+9mtI4){Pog1YG?oM`4GV7e>ym5)X*`2&!W$;hE%XU@6WwCIWG12_ z5fVyb787m;8-$Vf&{ z28e&dbq7`Z23P0SvJbMw$#P$`(ibiH+wX!<^@VDP@eEXh{VQi{Eaw?`7VKX=w~ouf zNF^94Ns+y0{=<*Xm3${GyM1AKfDZ@WdwYAj4_>?xJdgg?d!d*6yPp9`Tsqcu*kD9} zFE%g{HEb+s*@Uy);NyVopHQ(urZUYi`vQ2vWWPX<_+<{-9bjp1n5ftcSMaxs$+d#0 z1%iBb&}2UCGnr!ZEE=w;-FKPK0$`VUlh+QJd}klE?R}FLAfx;Qamm()%Y=~$PgfF% ziq8TAX>_r)eky3-qJkEp`T!M_NGu>~hd|TmJ^>hp!&)C`q=!Po9@T=zP)BIA8qxRY ze*jTOM$hSW{-LMTa~kgAW&2s+s@=YO=W0ms9Ig%?-5HE+55_k1^5EN*!M97H_PcPo zaJlLYmAv6<=*ZgmgYhC)4n-=V2<>! z6hwkTpiv-+*qrkMl-Iz4Z-K*4nrp8B25->u>t)V)ugaNRs*Sf`G>4&DQ%^ITAYB3X z0HB5qZ)05GGqIt!67aHMa;DHc@@+6w`G>5@nEZLF!)Wvu6(+Pdpssz73L2#-Ydr{u zKgma3+V^QY1rgzNY-oO}3F<;7uahpYNC7d)sVw1*R0c=Ic68AJZLZ_8xm!A&t_86M z#$d?TW31IE0%PcpKpX^Pyl0H52KrV{t;HV1iorjtf12Aou@%`oT0ZeX<-`YHNB%KV z4qUASu9l=%-ZuK4!6?!Dr&muGE>7na3U^_2<>K!?D!^3}P|q;{ zt9A@#*qMK5zJCqiTKVVr0RY#=3>~5K=Bv3#MUR2uo;WPWKmsm0u!RXbr9JK1z_g&m zH9-l8W*<4Cis29dSu&r?lMv)0tY~tbvhC%M^6ki>2~wvspm?zv$zOM*6mO@i;f|ct zZgz$absxmR5Hn%{W+yPT9T+NJEC)_j0w+t-EAKivNx{#@e?Pv?tzRok$1BqDl61T( z`FEt@ZE3hTQCDOPISEhw32;U$`OXu{Z~dxaimCy_>X{FkU6BO(~Nd7LF)4JTpq z&B}IFQW6PBf_AMfaMD5^C>+~;w~uuUTC>Snc%M!Q43fKBD)29ZnKG6&%RhqBdRo)j z6wEn=Ac?Y<(8upVN@F0k0`EX-<%&*P1xKg6#9qy(KL?bKIVh%}qOaIi&@PLn_^Duu zznT%Op8_4O7!)-p!fiHWF>xMi6h4`i8i$#N#A zE~Ke0$?`83l(gNW(M7h84it+T-Hea~3{9geuZ5|IQW2wqVunaM?9EgngN@mos=ZI! ze@F!-Lu(If^jK{PifO$E&~V4OYOG5b*chlGc(jW^w-DMG+q||lw54yIeEN&ZnM*YU zZQo2O7F(V}uYrbpZj~MvumqqEw$al2)KOOq4So{wv$HXxJ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/integrations/starlette_client/apps.py b/.venv/Lib/site-packages/authlib/integrations/starlette_client/apps.py new file mode 100644 index 00000000..114cbaff --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/starlette_client/apps.py @@ -0,0 +1,86 @@ +from starlette.datastructures import URL +from starlette.responses import RedirectResponse +from ..base_client import OAuthError +from ..base_client import BaseApp +from ..base_client.async_app import AsyncOAuth1Mixin, AsyncOAuth2Mixin +from ..base_client.async_openid import AsyncOpenIDMixin +from ..httpx_client import AsyncOAuth1Client, AsyncOAuth2Client + + +class StarletteAppMixin: + async def save_authorize_data(self, request, **kwargs): + state = kwargs.pop('state', None) + if state: + if self.framework.cache: + session = None + else: + session = request.session + await self.framework.set_state_data(session, state, kwargs) + else: + raise RuntimeError('Missing state value') + + async def authorize_redirect(self, request, redirect_uri=None, **kwargs): + """Create a HTTP Redirect for Authorization Endpoint. + + :param request: HTTP request instance from Starlette view. + :param redirect_uri: Callback or redirect URI for authorization. + :param kwargs: Extra parameters to include. + :return: A HTTP redirect response. + """ + + # Handle Starlette >= 0.26.0 where redirect_uri may now be a URL and not a string + if redirect_uri and isinstance(redirect_uri, URL): + redirect_uri = str(redirect_uri) + rv = await self.create_authorization_url(redirect_uri, **kwargs) + await self.save_authorize_data(request, redirect_uri=redirect_uri, **rv) + return RedirectResponse(rv['url'], status_code=302) + + +class StarletteOAuth1App(StarletteAppMixin, AsyncOAuth1Mixin, BaseApp): + client_cls = AsyncOAuth1Client + + async def authorize_access_token(self, request, **kwargs): + params = dict(request.query_params) + state = params.get('oauth_token') + if not state: + raise OAuthError(description='Missing "oauth_token" parameter') + + data = await self.framework.get_state_data(request.session, state) + if not data: + raise OAuthError(description='Missing "request_token" in temporary data') + + params['request_token'] = data['request_token'] + params.update(kwargs) + await self.framework.clear_state_data(request.session, state) + return await self.fetch_access_token(**params) + + +class StarletteOAuth2App(StarletteAppMixin, AsyncOAuth2Mixin, AsyncOpenIDMixin, BaseApp): + client_cls = AsyncOAuth2Client + + async def authorize_access_token(self, request, **kwargs): + error = request.query_params.get('error') + if error: + description = request.query_params.get('error_description') + raise OAuthError(error=error, description=description) + + params = { + 'code': request.query_params.get('code'), + 'state': request.query_params.get('state'), + } + + if self.framework.cache: + session = None + else: + session = request.session + + claims_options = kwargs.pop('claims_options', None) + state_data = await self.framework.get_state_data(session, params.get('state')) + await self.framework.clear_state_data(session, params.get('state')) + params = self._format_state_params(state_data, params) + token = await self.fetch_access_token(**params, **kwargs) + + if 'id_token' in token and 'nonce' in state_data: + userinfo = await self.parse_id_token(token, nonce=state_data['nonce'], claims_options=claims_options) + token['userinfo'] = userinfo + return token diff --git a/.venv/Lib/site-packages/authlib/integrations/starlette_client/integration.py b/.venv/Lib/site-packages/authlib/integrations/starlette_client/integration.py new file mode 100644 index 00000000..04ffd786 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/integrations/starlette_client/integration.py @@ -0,0 +1,66 @@ +import json +import time +from typing import ( + Any, + Dict, + Hashable, + Optional, +) + +from ..base_client import FrameworkIntegration + + +class StarletteIntegration(FrameworkIntegration): + async def _get_cache_data(self, key: Hashable): + value = await self.cache.get(key) + if not value: + return None + try: + return json.loads(value) + except (TypeError, ValueError): + return None + + async def get_state_data(self, session: Optional[Dict[str, Any]], state: str) -> Dict[str, Any]: + key = f'_state_{self.name}_{state}' + if self.cache: + value = await self._get_cache_data(key) + elif session is not None: + value = session.get(key) + else: + value = None + + if value: + return value.get('data') + return None + + async def set_state_data(self, session: Optional[Dict[str, Any]], state: str, data: Any): + key = f'_state_{self.name}_{state}' + if self.cache: + await self.cache.set(key, json.dumps({'data': data}), self.expires_in) + elif session is not None: + now = time.time() + session[key] = {'data': data, 'exp': now + self.expires_in} + + async def clear_state_data(self, session: Optional[Dict[str, Any]], state: str): + key = f'_state_{self.name}_{state}' + if self.cache: + await self.cache.delete(key) + elif session is not None: + session.pop(key, None) + self._clear_session_state(session) + + def update_token(self, token, refresh_token=None, access_token=None): + pass + + @staticmethod + def load_config(oauth, name, params): + if not oauth.config: + return {} + + rv = {} + for k in params: + conf_key = f'{name}_{k}'.upper() + v = oauth.config.get(conf_key, default=None) + if v is not None: + rv[k] = v + return rv diff --git a/.venv/Lib/site-packages/authlib/jose/__init__.py b/.venv/Lib/site-packages/authlib/jose/__init__.py new file mode 100644 index 00000000..2d6638a0 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/__init__.py @@ -0,0 +1,60 @@ +""" + authlib.jose + ~~~~~~~~~~~~ + + JOSE implementation in Authlib. Tracking the status of JOSE specs at + https://tools.ietf.org/wg/jose/ +""" +from .rfc7515 import ( + JsonWebSignature, JWSAlgorithm, JWSHeader, JWSObject, +) +from .rfc7516 import ( + JsonWebEncryption, JWEAlgorithm, JWEEncAlgorithm, JWEZipAlgorithm, +) +from .rfc7517 import Key, KeySet, JsonWebKey +from .rfc7518 import ( + register_jws_rfc7518, + register_jwe_rfc7518, + ECDHESAlgorithm, + OctKey, + RSAKey, + ECKey, +) +from .rfc7519 import JsonWebToken, BaseClaims, JWTClaims +from .rfc8037 import OKPKey, register_jws_rfc8037 + +from .errors import JoseError + +# register algorithms +register_jws_rfc7518(JsonWebSignature) +register_jws_rfc8037(JsonWebSignature) + +register_jwe_rfc7518(JsonWebEncryption) + +# attach algorithms +ECDHESAlgorithm.ALLOWED_KEY_CLS = (ECKey, OKPKey) + +# register supported keys +JsonWebKey.JWK_KEY_CLS = { + OctKey.kty: OctKey, + RSAKey.kty: RSAKey, + ECKey.kty: ECKey, + OKPKey.kty: OKPKey, +} + +jwt = JsonWebToken(list(JsonWebSignature.ALGORITHMS_REGISTRY.keys())) + + +__all__ = [ + 'JoseError', + + 'JsonWebSignature', 'JWSAlgorithm', 'JWSHeader', 'JWSObject', + 'JsonWebEncryption', 'JWEAlgorithm', 'JWEEncAlgorithm', 'JWEZipAlgorithm', + + 'JsonWebKey', 'Key', 'KeySet', + + 'OctKey', 'RSAKey', 'ECKey', 'OKPKey', + + 'JsonWebToken', 'BaseClaims', 'JWTClaims', + 'jwt', +] diff --git a/.venv/Lib/site-packages/authlib/jose/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4d6b0f4efc84f4d5e9e417d755f13168b4af173b GIT binary patch literal 1914 zcmb_bO>Y`U7@pmQ1(r`6u<=KdZJXet*3hU)?L<)}idX(@sSK5s5z>l}0WaR!MYHQz z^icVbLyzvIy+%Ext#a=Fz!g%gJw@uNry}K+UOKaY1F3U~ItOJo~QRU&3Jt z(DBda@94w}z@Lnahkvwq`6CCwPoM!HXmAZ)=P(a>EI>2OyDF;y8EI&hv(ruPQesj zfD5kX(--j)T*Aw6+2wxy8omy%bASgZhWMw{<1_jn4p&{iQk_A*H_xIZT59rWR=qKf zNAb4&dW{kjEP;{}j7CndCC!5(>U-lz>TI6=-$#7=gR%DH=6E&vd`ii)OJUmIG=sNV zpb_|)gXxA;0-4~qKS(ki)nofm*J|0eX(3nmZemETvQsQ6vW7c4!pN|zwq_c#X2|(b zq+BM|`jKX|Wcv`w7Cmrm$!1e_!>kUfTXNNQ6CK)i$GV@(*`}#mSq<6EtVvqAlU9!1 zo|FD!pCRLMVmp>;9H3fBYZ){fK~8Arpp@5JCeiFe>;x#=Le&N$?y^{Gqq+l(WM$y3L9I>glVx@x82nHr969jl>*BuP>aL2Et^NkaHKD)7Aojf4O{Hx%EM)b zcf{iE*DUToCe}asbS=Zt!?cD9AtuQr$O0`S5g2$F&;|uWWZ+}K`jZ40upTC120;cP z1~Uw18N?aPGe|HS_ERjQh*)tfw>C~RzqeOBP&U+E<)K>GD>=fE-F1RH z2fLSwN2lM~iRbq=i~HN zn+@6ym2b>ud5gA&RoSPVgKLN&tB#C1s$?G_<56W#t5qz`MynlqsMwrc2HH# z&}>!BcDk?p53t!d*3su=m0rTy#QK}!K;SrTz>Az`02oAgjvs(`1M%I$+}lLJt@gmj zZ<_<&$9(;N5Ch!39$0_dya2a*SIrmTT5oy|sPkkGBznnP=OEn&=^jX5P&%!=7%Ay< zu+j%BJ+MOKZf1T>Kgpd&`{2gF54^$0J7?mBM;bl?kGH=+9Nz`$Vc?U{|m}j Bh;Pw{wz0 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 F{u`fP^%4L8 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/__pycache__/util.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/__pycache__/util.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..767c03b21e6cdcb1546918d44979376a1ae514ac GIT binary patch literal 2113 zcma)6%}*Og6rb4-V|!r@1_DhC+BCFuRmHg^m_SpBDoKgbpsGo#*0PG$-hnLjuF=dI z2r>~uIZ&yGRBZ%Rio}Ve$|Z-k>NWqty0TQXlBG&L^=1iGLiEx%i)}DXt3Ho^^Y!M< z+j+nDo_2IZ5y)Tf|44KRq2KwWAwqqy_Z|#3kcmv3M`_**d29=5!4}h^Eu|&Q*TlSR zhteS!OAk@H%?z8Nhd3QJ+h7(k@ol6>{@@0ubkXlB(mXR}$aHq(qDgWEllaj&R&b{C z1;b>1)GbUG9gDB)*jKIw8rLW-&|JeOZb^o}2>-nrzy@+Lbag4A5;pM;>^|ojfvgA- zH*$2kB)UNa4p(--qvuVpm=ai(T0L09B@tdzp7KNYh+z`CEEnCG^P|gs zH=G3{Z<*TRvc_C$IkRKha$+*j)9fO1wJgyLjX$c zu#8c3@8zxRg}DMF7mBWxPtM=>)y9_`UQD~;E*>hj0kDdy@w3~>7y8eil;hVc@$0KM zYmz9Zs$FL`Z~mG{{*p*OTP!D1l|-uCHCpK!T@S5?_Nz*74PiNT1iNbAy5;p>dT|y2 zT3H>bs3Tr@WFMp^f-dxbhEV&dM>AVySvglx&hgWu^@Ag2HC0hlUO2U@bgkZEz2Mu| zuaBUgq7&WXOQcSy;!9PAvEMdt+~+BgJ4Rc?gTv>0O8^@PNZq6=kQ%j;*T^yNE{&zpCUkOHB(m{=?_^|FK#^Pt3bMM|c5tQqHHJ;=U79L6_zF`*i4oPj@k3;^k>^gc4SddkXRMH#Fi zNgl5WVr0D9d3tMX+xYg%cUQ`tdZklepID#R=c_lo7;peb#*d&HAMge*KN|#qR*sKV z;$vR>7^G=ryqTuQE`jW=s;_ycFKvGY0IiwbzbWmjlZ=ycBXJS^Ff`FG>X`PxT#wRz z=={EVO-kkpwq06)YT;(Lt HA-Mi;=4kFs literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/drafts/__init__.py b/.venv/Lib/site-packages/authlib/jose/drafts/__init__.py new file mode 100644 index 00000000..3044585e --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/drafts/__init__.py @@ -0,0 +1,17 @@ +from ._jwe_algorithms import JWE_DRAFT_ALG_ALGORITHMS +from ._jwe_enc_cryptography import C20PEncAlgorithm +try: + from ._jwe_enc_cryptodome import XC20PEncAlgorithm +except ImportError: + XC20PEncAlgorithm = None + + +def register_jwe_draft(cls): + for alg in JWE_DRAFT_ALG_ALGORITHMS: + cls.register_algorithm(alg) + + cls.register_algorithm(C20PEncAlgorithm(256)) # C20P + if XC20PEncAlgorithm is not None: + cls.register_algorithm(XC20PEncAlgorithm(256)) # XC20P + +__all__ = ['register_jwe_draft'] diff --git a/.venv/Lib/site-packages/authlib/jose/drafts/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/drafts/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7a97f0f14eeb1e43af868f8374d8f847a3d44988 GIT binary patch literal 1063 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 R_LKYH{DHlH9x&wF@;BG0qhbI6 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/drafts/_jwe_algorithms.py b/.venv/Lib/site-packages/authlib/jose/drafts/_jwe_algorithms.py new file mode 100644 index 00000000..c01b7e7d --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/drafts/_jwe_algorithms.py @@ -0,0 +1,188 @@ +import struct +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.kdf.concatkdf import ConcatKDFHash + +from authlib.jose.errors import InvalidEncryptionAlgorithmForECDH1PUWithKeyWrappingError +from authlib.jose.rfc7516 import JWEAlgorithmWithTagAwareKeyAgreement +from authlib.jose.rfc7518 import AESAlgorithm, CBCHS2EncAlgorithm, ECKey, u32be_len_input +from authlib.jose.rfc8037 import OKPKey + + +class ECDH1PUAlgorithm(JWEAlgorithmWithTagAwareKeyAgreement): + EXTRA_HEADERS = ['epk', 'apu', 'apv', 'skid'] + ALLOWED_KEY_CLS = (ECKey, OKPKey) + + # https://datatracker.ietf.org/doc/html/draft-madden-jose-ecdh-1pu-04 + def __init__(self, key_size=None): + if key_size is None: + self.name = 'ECDH-1PU' + self.description = 'ECDH-1PU in the Direct Key Agreement mode' + else: + self.name = f'ECDH-1PU+A{key_size}KW' + self.description = ( + 'ECDH-1PU using Concat KDF and CEK wrapped ' + 'with A{}KW').format(key_size) + self.key_size = key_size + self.aeskw = AESAlgorithm(key_size) + + def prepare_key(self, raw_data): + if isinstance(raw_data, self.ALLOWED_KEY_CLS): + return raw_data + return ECKey.import_key(raw_data) + + def generate_preset(self, enc_alg, key): + epk = self._generate_ephemeral_key(key) + h = self._prepare_headers(epk) + preset = {'epk': epk, 'header': h} + if self.key_size is not None: + cek = enc_alg.generate_cek() + preset['cek'] = cek + return preset + + def compute_shared_key(self, shared_key_e, shared_key_s): + return shared_key_e + shared_key_s + + def compute_fixed_info(self, headers, bit_size, tag): + if tag is None: + cctag = b'' + else: + cctag = u32be_len_input(tag) + + # AlgorithmID + if self.key_size is None: + alg_id = u32be_len_input(headers['enc']) + else: + alg_id = u32be_len_input(headers['alg']) + + # PartyUInfo + apu_info = u32be_len_input(headers.get('apu'), True) + + # PartyVInfo + apv_info = u32be_len_input(headers.get('apv'), True) + + # SuppPubInfo + pub_info = struct.pack('>I', bit_size) + cctag + + return alg_id + apu_info + apv_info + pub_info + + def compute_derived_key(self, shared_key, fixed_info, bit_size): + ckdf = ConcatKDFHash( + algorithm=hashes.SHA256(), + length=bit_size // 8, + otherinfo=fixed_info, + backend=default_backend() + ) + return ckdf.derive(shared_key) + + def deliver_at_sender(self, sender_static_key, sender_ephemeral_key, recipient_pubkey, headers, bit_size, tag): + shared_key_s = sender_static_key.exchange_shared_key(recipient_pubkey) + shared_key_e = sender_ephemeral_key.exchange_shared_key(recipient_pubkey) + shared_key = self.compute_shared_key(shared_key_e, shared_key_s) + + fixed_info = self.compute_fixed_info(headers, bit_size, tag) + + return self.compute_derived_key(shared_key, fixed_info, bit_size) + + def deliver_at_recipient(self, recipient_key, sender_static_pubkey, sender_ephemeral_pubkey, headers, bit_size, tag): + shared_key_s = recipient_key.exchange_shared_key(sender_static_pubkey) + shared_key_e = recipient_key.exchange_shared_key(sender_ephemeral_pubkey) + shared_key = self.compute_shared_key(shared_key_e, shared_key_s) + + fixed_info = self.compute_fixed_info(headers, bit_size, tag) + + return self.compute_derived_key(shared_key, fixed_info, bit_size) + + def _generate_ephemeral_key(self, key): + return key.generate_key(key['crv'], is_private=True) + + def _prepare_headers(self, epk): + # REQUIRED_JSON_FIELDS contains only public fields + pub_epk = {k: epk[k] for k in epk.REQUIRED_JSON_FIELDS} + pub_epk['kty'] = epk.kty + return {'epk': pub_epk} + + def generate_keys_and_prepare_headers(self, enc_alg, key, sender_key, preset=None): + if not isinstance(enc_alg, CBCHS2EncAlgorithm): + raise InvalidEncryptionAlgorithmForECDH1PUWithKeyWrappingError() + + if preset and 'epk' in preset: + epk = preset['epk'] + h = {} + else: + epk = self._generate_ephemeral_key(key) + h = self._prepare_headers(epk) + + if preset and 'cek' in preset: + cek = preset['cek'] + else: + cek = enc_alg.generate_cek() + + return {'epk': epk, 'cek': cek, 'header': h} + + def _agree_upon_key_at_sender(self, enc_alg, headers, key, sender_key, epk, tag=None): + if self.key_size is None: + bit_size = enc_alg.CEK_SIZE + else: + bit_size = self.key_size + + public_key = key.get_op_key('wrapKey') + + return self.deliver_at_sender(sender_key, epk, public_key, headers, bit_size, tag) + + def _wrap_cek(self, cek, dk): + kek = self.aeskw.prepare_key(dk) + return self.aeskw.wrap_cek(cek, kek) + + def agree_upon_key_and_wrap_cek(self, enc_alg, headers, key, sender_key, epk, cek, tag): + dk = self._agree_upon_key_at_sender(enc_alg, headers, key, sender_key, epk, tag) + return self._wrap_cek(cek, dk) + + def wrap(self, enc_alg, headers, key, sender_key, preset=None): + # In this class this method is used in direct key agreement mode only + if self.key_size is not None: + raise RuntimeError('Invalid algorithm state detected') + + if preset and 'epk' in preset: + epk = preset['epk'] + h = {} + else: + epk = self._generate_ephemeral_key(key) + h = self._prepare_headers(epk) + + dk = self._agree_upon_key_at_sender(enc_alg, headers, key, sender_key, epk) + + return {'ek': b'', 'cek': dk, 'header': h} + + def unwrap(self, enc_alg, ek, headers, key, sender_key, tag=None): + if 'epk' not in headers: + raise ValueError('Missing "epk" in headers') + + if self.key_size is None: + bit_size = enc_alg.CEK_SIZE + else: + bit_size = self.key_size + + sender_pubkey = sender_key.get_op_key('wrapKey') + epk = key.import_key(headers['epk']) + epk_pubkey = epk.get_op_key('wrapKey') + dk = self.deliver_at_recipient(key, sender_pubkey, epk_pubkey, headers, bit_size, tag) + + if self.key_size is None: + return dk + + kek = self.aeskw.prepare_key(dk) + return self.aeskw.unwrap(enc_alg, ek, headers, kek) + + +JWE_DRAFT_ALG_ALGORITHMS = [ + ECDH1PUAlgorithm(None), # ECDH-1PU + ECDH1PUAlgorithm(128), # ECDH-1PU+A128KW + ECDH1PUAlgorithm(192), # ECDH-1PU+A192KW + ECDH1PUAlgorithm(256), # ECDH-1PU+A256KW +] + + +def register_jwe_alg_draft(cls): + for alg in JWE_DRAFT_ALG_ALGORITHMS: + cls.register_algorithm(alg) diff --git a/.venv/Lib/site-packages/authlib/jose/drafts/_jwe_enc_cryptodome.py b/.venv/Lib/site-packages/authlib/jose/drafts/_jwe_enc_cryptodome.py new file mode 100644 index 00000000..cb6fceaf --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/drafts/_jwe_enc_cryptodome.py @@ -0,0 +1,52 @@ +""" + authlib.jose.draft + ~~~~~~~~~~~~~~~~~~~~ + + Content Encryption per `Section 4`_. + + .. _`Section 4`: https://datatracker.ietf.org/doc/html/draft-amringer-jose-chacha-02#section-4 +""" +from authlib.jose.rfc7516 import JWEEncAlgorithm +from Cryptodome.Cipher import ChaCha20_Poly1305 as Cryptodome_ChaCha20_Poly1305 + + +class XC20PEncAlgorithm(JWEEncAlgorithm): + # Use of an IV of size 192 bits is REQUIRED with this algorithm. + # https://datatracker.ietf.org/doc/html/draft-amringer-jose-chacha-02#section-4.1 + IV_SIZE = 192 + + def __init__(self, key_size): + self.name = 'XC20P' + self.description = 'XChaCha20-Poly1305' + self.key_size = key_size + self.CEK_SIZE = key_size + + def encrypt(self, msg, aad, iv, key): + """Content Encryption with AEAD_XCHACHA20_POLY1305 + + :param msg: text to be encrypt in bytes + :param aad: additional authenticated data in bytes + :param iv: initialization vector in bytes + :param key: encrypted key in bytes + :return: (ciphertext, tag) + """ + self.check_iv(iv) + chacha = Cryptodome_ChaCha20_Poly1305.new(key=key, nonce=iv) + chacha.update(aad) + ciphertext, tag = chacha.encrypt_and_digest(msg) + return ciphertext, tag + + def decrypt(self, ciphertext, aad, iv, tag, key): + """Content Decryption with AEAD_XCHACHA20_POLY1305 + + :param ciphertext: ciphertext in bytes + :param aad: additional authenticated data in bytes + :param iv: initialization vector in bytes + :param tag: authentication tag in bytes + :param key: encrypted key in bytes + :return: message + """ + self.check_iv(iv) + chacha = Cryptodome_ChaCha20_Poly1305.new(key=key, nonce=iv) + chacha.update(aad) + return chacha.decrypt_and_verify(ciphertext, tag) diff --git a/.venv/Lib/site-packages/authlib/jose/drafts/_jwe_enc_cryptography.py b/.venv/Lib/site-packages/authlib/jose/drafts/_jwe_enc_cryptography.py new file mode 100644 index 00000000..1b0c852b --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/drafts/_jwe_enc_cryptography.py @@ -0,0 +1,50 @@ +""" + authlib.jose.draft + ~~~~~~~~~~~~~~~~~~~~ + + Content Encryption per `Section 4`_. + + .. _`Section 4`: https://datatracker.ietf.org/doc/html/draft-amringer-jose-chacha-02#section-4 +""" +from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 +from authlib.jose.rfc7516 import JWEEncAlgorithm + + +class C20PEncAlgorithm(JWEEncAlgorithm): + # Use of an IV of size 96 bits is REQUIRED with this algorithm. + # https://datatracker.ietf.org/doc/html/draft-amringer-jose-chacha-02#section-4.1 + IV_SIZE = 96 + + def __init__(self, key_size): + self.name = 'C20P' + self.description = 'ChaCha20-Poly1305' + self.key_size = key_size + self.CEK_SIZE = key_size + + def encrypt(self, msg, aad, iv, key): + """Content Encryption with AEAD_CHACHA20_POLY1305 + + :param msg: text to be encrypt in bytes + :param aad: additional authenticated data in bytes + :param iv: initialization vector in bytes + :param key: encrypted key in bytes + :return: (ciphertext, tag) + """ + self.check_iv(iv) + chacha = ChaCha20Poly1305(key) + ciphertext = chacha.encrypt(iv, msg, aad) + return ciphertext[:-16], ciphertext[-16:] + + def decrypt(self, ciphertext, aad, iv, tag, key): + """Content Decryption with AEAD_CHACHA20_POLY1305 + + :param ciphertext: ciphertext in bytes + :param aad: additional authenticated data in bytes + :param iv: initialization vector in bytes + :param tag: authentication tag in bytes + :param key: encrypted key in bytes + :return: message + """ + self.check_iv(iv) + chacha = ChaCha20Poly1305(key) + return chacha.decrypt(iv, ciphertext + tag, aad) diff --git a/.venv/Lib/site-packages/authlib/jose/errors.py b/.venv/Lib/site-packages/authlib/jose/errors.py new file mode 100644 index 00000000..fb02eb4e --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/errors.py @@ -0,0 +1,113 @@ +from authlib.common.errors import AuthlibBaseError + + +class JoseError(AuthlibBaseError): + pass + + +class DecodeError(JoseError): + error = 'decode_error' + + +class MissingAlgorithmError(JoseError): + error = 'missing_algorithm' + + +class UnsupportedAlgorithmError(JoseError): + error = 'unsupported_algorithm' + + +class BadSignatureError(JoseError): + error = 'bad_signature' + + def __init__(self, result): + super().__init__() + self.result = result + + +class InvalidHeaderParameterNameError(JoseError): + error = 'invalid_header_parameter_name' + + def __init__(self, name): + description = f'Invalid Header Parameter Name: {name}' + super().__init__( + description=description) + + +class InvalidEncryptionAlgorithmForECDH1PUWithKeyWrappingError(JoseError): + error = 'invalid_encryption_algorithm_for_ECDH_1PU_with_key_wrapping' + + def __init__(self): + description = 'In key agreement with key wrapping mode ECDH-1PU algorithm ' \ + 'only supports AES_CBC_HMAC_SHA2 family encryption algorithms' + super().__init__( + description=description) + + +class InvalidAlgorithmForMultipleRecipientsMode(JoseError): + error = 'invalid_algorithm_for_multiple_recipients_mode' + + def __init__(self, alg): + description = f'{alg} algorithm cannot be used in multiple recipients mode' + super().__init__( + description=description) + + +class KeyMismatchError(JoseError): + error = 'key_mismatch_error' + description = 'Key does not match to any recipient' + + +class MissingEncryptionAlgorithmError(JoseError): + error = 'missing_encryption_algorithm' + description = 'Missing "enc" in header' + + +class UnsupportedEncryptionAlgorithmError(JoseError): + error = 'unsupported_encryption_algorithm' + description = 'Unsupported "enc" value in header' + + +class UnsupportedCompressionAlgorithmError(JoseError): + error = 'unsupported_compression_algorithm' + description = 'Unsupported "zip" value in header' + + +class InvalidUseError(JoseError): + error = 'invalid_use' + description = 'Key "use" is not valid for your usage' + + +class InvalidClaimError(JoseError): + error = 'invalid_claim' + + def __init__(self, claim): + self.claim_name = claim + description = f'Invalid claim "{claim}"' + super().__init__(description=description) + + +class MissingClaimError(JoseError): + error = 'missing_claim' + + def __init__(self, claim): + description = f'Missing "{claim}" claim' + super().__init__(description=description) + + +class InsecureClaimError(JoseError): + error = 'insecure_claim' + + def __init__(self, claim): + description = f'Insecure claim "{claim}"' + super().__init__(description=description) + + +class ExpiredTokenError(JoseError): + error = 'expired_token' + description = 'The token is expired' + + +class InvalidTokenError(JoseError): + error = 'invalid_token' + description = 'The token is not valid yet' diff --git a/.venv/Lib/site-packages/authlib/jose/jwk.py b/.venv/Lib/site-packages/authlib/jose/jwk.py new file mode 100644 index 00000000..bc3b6eb5 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/jwk.py @@ -0,0 +1,19 @@ +from authlib.deprecate import deprecate +from .rfc7517 import JsonWebKey + + +def loads(obj, kid=None): + deprecate('Please use ``JsonWebKey`` directly.') + key_set = JsonWebKey.import_key_set(obj) + if key_set: + return key_set.find_by_kid(kid) + return JsonWebKey.import_key(obj) + + +def dumps(key, kty=None, **params): + deprecate('Please use ``JsonWebKey`` directly.') + if kty: + params['kty'] = kty + + key = JsonWebKey.import_key(key, params) + return dict(key) diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7515/__init__.py b/.venv/Lib/site-packages/authlib/jose/rfc7515/__init__.py new file mode 100644 index 00000000..5f8e0f5f --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc7515/__init__.py @@ -0,0 +1,18 @@ +""" + authlib.jose.rfc7515 + ~~~~~~~~~~~~~~~~~~~~~ + + This module represents a direct implementation of + JSON Web Signature (JWS). + + https://tools.ietf.org/html/rfc7515 +""" + +from .jws import JsonWebSignature +from .models import JWSAlgorithm, JWSHeader, JWSObject + + +__all__ = [ + 'JsonWebSignature', + 'JWSAlgorithm', 'JWSHeader', 'JWSObject' +] diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7515/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc7515/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8e9b69e3b31c529a53dd3f9cdf9a67019a9d20d7 GIT binary patch literal 629 zcmZ`#L5tKd6i(VsXB>CMgFhg8vIkofR$&oA5L^b?1!r}k6hfzY(`HPXl4N#S58}V@ z?nS%`{*OIMub#XW_O@P3yE`JHFX7|8y!XDm_kG&lo+4*IpMQl4BlNuwHs)P9=MS9o z0Wp*!hM6a@^imJ^zAtEf zk9O|w42gIDvgwdIthgakv9$oAq0wNVwua<{aSeqfTs8uvd&@0XHBrluRRPCsKGev&8 z<+z@TQfY20*oR+#mWO+J@y28?-S%<;PM8Af0f`JMUu1?` zxYxL%yabb7iJ$c1ZRZ#n8;bS1VZ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7515/__pycache__/jws.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc7515/__pycache__/jws.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..38d55ec3bc52648271d9b879d0f2be6170efdc39 GIT binary patch literal 14489 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7515/__pycache__/models.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc7515/__pycache__/models.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..54cd816e3fe7e2ebbd390d87da485d09febdaa8a GIT binary patch literal 4381 zcmb_f-ESMm5#ReDc@!zi7G-_3k#v&M$}C)}N$fhMVj)hPMs^aph?+KF)t--cOZjAy z$L^hEOJx9|5Ktv>P@`xeJ^IP5>!R&T{)IeCfq)VR^r`4O4Y_EMzI0~qgCDY;mo9O0 zw=;7)d%v0e?eh2i{e1-5f8YL$ewrlYAJ_?7EOWEkk!LyQZFf|NC!VyztViIdysQ`Ume`=~JOu)p~_iY0XvLo3#DD6AgJA zVu8(a)ROMdwm%;;&&OEuBna+F5Z#EtgRjJA1nhW%f3h1w0KErrJ%Y<`zZ7!9)^~ou zXkBMiy+t>9bjMn)S+!MFubJuwWmb6;d#Kgjbw=|K1uwf~yH~?6pypeQ*(@h|vO_Cn zPht9P&D34p!HKBqm&GfE6~i`Rl$8(c@(&kvYAqS~KWMeuLIFR^GKr zD~{#TZ`Z*|U!~59zV680xa>@}GE)@Wy*@*Nf| zNhbqhoBT5~b(ons%FG-nGsg&n5!DuS5GoGcDR|f;F37NPu>QOZFz}SQ^p2}momG`5 zN>}U5+R$A(hd3dW`97W_%yj|a)vM@SP^;8&;Jeh)rb`{wwbc^k&{DJ49mXhxqw?H< zGanoaCK#su4x^BpTEQPTQnLiiJ|{6)h{Tg%0-glJI{1Y!FP1{JjDv2S?t%_g2$zGv zZIgdx$iVc0GR69#YsetN_EmWO`$xQhIAS;`uOQVft0&-FFI6mK&ab!s3w{u;ph9`A zSKM~-28bJW6-)jZnDeQGkOwnD(4!BC@GV5J+jfQOwaDNDFLU780HEbb@HWG$au7d2 zKY%~(2iVGXCBRpXpnH&lQynSDr94H`YI>Dwn%AdkupHJa_?*_XpRencz>?53(>6dY zqryv>u-2GWM^f@K5oKxaW}SM2?S94fiHoHnJUfkI2*g9e)6a{BVFhu41>lrGY)8MA zD8`f)K@lhEQ`=XXgTveJG|zl(d#O1#aUc)3WHI(4Is`&V#HL#$5`zkMPYORgMmFGz zTF89IuY&4VJruu7%7Q8GC`Fk9&F}Q^UopN*?g+&Mki6_AApwh2H!0HxU`+o}wM%Q% za6?wkt5;nWil=1ND6i={vt6)LQ@zPw<)pb@i`2Xz0+Va6QYa&adqfaPwOpi36J3+n9R^2-;#JNr>oh3FUrN3UC! ziC%h-$J%X2i@c(#osA-#3&zNGjSGBNbI-QlZCiV$b58y0z`)hf=Ui%kTUWq#sC+ov zOTo;1stss18mbT>8mU5mTz-MOKUUkfBYBBPX8bX6;(I^cOdJ&JC1Qvj> zl#6-s^*U_a)QdUmb;^)rteWKlgCrvey||B9F6NWlix7}~1B55RTJe&aW>j>?(KH87 zdkFNlPZ=}N-5QMQD<6*i66l>Wi2rPpX6Dqc)JzSvh>)CarU!m~?UQTwHV@NNN9n19 z^i(r-8ZDEdW#ceCag?4oNKgD->Hj!!H}N-R^b2KlKYOT*A1UJp%6M~ZdRM-iX%4>t zx705D{5`A_wK&A)+57|^V9$@TL&bF= z9LR{Y#3FFvaMfoyR?TsBI4pS*FbSw6qvEh{Lfqh_;gXVv_Fd? ze7quxxB@RYZ-IbH=vwK`>{xT?>#Z0`jy)z)vhN8B$SnwkjEv)&Z;njBE!`X%gGtL}bp zKmJ8(;vhBA%#Q3Uzg+-=Y)K?N2^xQ03hZTYf8O#`fYyQN-A#svCzeMs2cmO5B0n<} zZ=m64AUf7#Q$BwnpKpnY*chJRo-PJSJcH{GPIVw~L1uP7Y%937E&K(E0he+zKVy0_ zk{Ra&J`pw!M&Awp!F;K_<{y9;7;+mX*7+1fOA-X3B~Azs_oR4?x+iVJ8^X8%jB!%j alOLn@N!#?gFo0v86zB@tCr>f)>HZHoMiQX_ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7515/jws.py b/.venv/Lib/site-packages/authlib/jose/rfc7515/jws.py new file mode 100644 index 00000000..cf19c4ba --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc7515/jws.py @@ -0,0 +1,304 @@ +from authlib.common.encoding import ( + to_bytes, + to_unicode, + urlsafe_b64encode, + json_b64encode, +) +from authlib.jose.util import ( + extract_header, + extract_segment, ensure_dict, +) +from authlib.jose.errors import ( + DecodeError, + MissingAlgorithmError, + UnsupportedAlgorithmError, + BadSignatureError, + InvalidHeaderParameterNameError, +) +from .models import JWSHeader, JWSObject + + +class JsonWebSignature: + + #: Registered Header Parameter Names defined by Section 4.1 + REGISTERED_HEADER_PARAMETER_NAMES = frozenset([ + 'alg', 'jku', 'jwk', 'kid', + 'x5u', 'x5c', 'x5t', 'x5t#S256', + 'typ', 'cty', 'crit' + ]) + + #: Defined available JWS algorithms in the registry + ALGORITHMS_REGISTRY = {} + + def __init__(self, algorithms=None, private_headers=None): + self._private_headers = private_headers + self._algorithms = algorithms + + @classmethod + def register_algorithm(cls, algorithm): + if not algorithm or algorithm.algorithm_type != 'JWS': + raise ValueError( + f'Invalid algorithm for JWS, {algorithm!r}') + cls.ALGORITHMS_REGISTRY[algorithm.name] = algorithm + + def serialize_compact(self, protected, payload, key): + """Generate a JWS Compact Serialization. The JWS Compact Serialization + represents digitally signed or MACed content as a compact, URL-safe + string, per `Section 7.1`_. + + .. code-block:: text + + BASE64URL(UTF8(JWS Protected Header)) || '.' || + BASE64URL(JWS Payload) || '.' || + BASE64URL(JWS Signature) + + :param protected: A dict of protected header + :param payload: A bytes/string of payload + :param key: Private key used to generate signature + :return: byte + """ + jws_header = JWSHeader(protected, None) + self._validate_private_headers(protected) + algorithm, key = self._prepare_algorithm_key(protected, payload, key) + + protected_segment = json_b64encode(jws_header.protected) + payload_segment = urlsafe_b64encode(to_bytes(payload)) + + # calculate signature + signing_input = b'.'.join([protected_segment, payload_segment]) + signature = urlsafe_b64encode(algorithm.sign(signing_input, key)) + return b'.'.join([protected_segment, payload_segment, signature]) + + def deserialize_compact(self, s, key, decode=None): + """Exact JWS Compact Serialization, and validate with the given key. + If key is not provided, the returned dict will contain the signature, + and signing input values. Via `Section 7.1`_. + + :param s: text of JWS Compact Serialization + :param key: key used to verify the signature + :param decode: a function to decode payload data + :return: JWSObject + :raise: BadSignatureError + + .. _`Section 7.1`: https://tools.ietf.org/html/rfc7515#section-7.1 + """ + try: + s = to_bytes(s) + signing_input, signature_segment = s.rsplit(b'.', 1) + protected_segment, payload_segment = signing_input.split(b'.', 1) + except ValueError: + raise DecodeError('Not enough segments') + + protected = _extract_header(protected_segment) + jws_header = JWSHeader(protected, None) + + payload = _extract_payload(payload_segment) + if decode: + payload = decode(payload) + + signature = _extract_signature(signature_segment) + rv = JWSObject(jws_header, payload, 'compact') + algorithm, key = self._prepare_algorithm_key(jws_header, payload, key) + if algorithm.verify(signing_input, signature, key): + return rv + raise BadSignatureError(rv) + + def serialize_json(self, header_obj, payload, key): + """Generate a JWS JSON Serialization. The JWS JSON Serialization + represents digitally signed or MACed content as a JSON object, + per `Section 7.2`_. + + :param header_obj: A dict/list of header + :param payload: A string/dict of payload + :param key: Private key used to generate signature + :return: JWSObject + + Example ``header_obj`` of JWS JSON Serialization:: + + { + "protected: {"alg": "HS256"}, + "header": {"kid": "jose"} + } + + Pass a dict to generate flattened JSON Serialization, pass a list of + header dict to generate standard JSON Serialization. + """ + payload_segment = json_b64encode(payload) + + def _sign(jws_header): + self._validate_private_headers(jws_header) + _alg, _key = self._prepare_algorithm_key(jws_header, payload, key) + + protected_segment = json_b64encode(jws_header.protected) + signing_input = b'.'.join([protected_segment, payload_segment]) + signature = urlsafe_b64encode(_alg.sign(signing_input, _key)) + + rv = { + 'protected': to_unicode(protected_segment), + 'signature': to_unicode(signature) + } + if jws_header.header is not None: + rv['header'] = jws_header.header + return rv + + if isinstance(header_obj, dict): + data = _sign(JWSHeader.from_dict(header_obj)) + data['payload'] = to_unicode(payload_segment) + return data + + signatures = [_sign(JWSHeader.from_dict(h)) for h in header_obj] + return { + 'payload': to_unicode(payload_segment), + 'signatures': signatures + } + + def deserialize_json(self, obj, key, decode=None): + """Exact JWS JSON Serialization, and validate with the given key. + If key is not provided, it will return a dict without signature + verification. Header will still be validated. Via `Section 7.2`_. + + :param obj: text of JWS JSON Serialization + :param key: key used to verify the signature + :param decode: a function to decode payload data + :return: JWSObject + :raise: BadSignatureError + + .. _`Section 7.2`: https://tools.ietf.org/html/rfc7515#section-7.2 + """ + obj = ensure_dict(obj, 'JWS') + + payload_segment = obj.get('payload') + if payload_segment is None: + raise DecodeError('Missing "payload" value') + + payload_segment = to_bytes(payload_segment) + payload = _extract_payload(payload_segment) + if decode: + payload = decode(payload) + + if 'signatures' not in obj: + # flattened JSON JWS + jws_header, valid = self._validate_json_jws( + payload_segment, payload, obj, key) + + rv = JWSObject(jws_header, payload, 'flat') + if valid: + return rv + raise BadSignatureError(rv) + + headers = [] + is_valid = True + for header_obj in obj['signatures']: + jws_header, valid = self._validate_json_jws( + payload_segment, payload, header_obj, key) + headers.append(jws_header) + if not valid: + is_valid = False + + rv = JWSObject(headers, payload, 'json') + if is_valid: + return rv + raise BadSignatureError(rv) + + def serialize(self, header, payload, key): + """Generate a JWS Serialization. It will automatically generate a + Compact or JSON Serialization depending on the given header. If a + header is in a JSON header format, it will call + :meth:`serialize_json`, otherwise it will call + :meth:`serialize_compact`. + + :param header: A dict/list of header + :param payload: A string/dict of payload + :param key: Private key used to generate signature + :return: byte/dict + """ + if isinstance(header, (list, tuple)): + return self.serialize_json(header, payload, key) + if 'protected' in header: + return self.serialize_json(header, payload, key) + return self.serialize_compact(header, payload, key) + + def deserialize(self, s, key, decode=None): + """Deserialize JWS Serialization, both compact and JSON format. + It will automatically deserialize depending on the given JWS. + + :param s: text of JWS Compact/JSON Serialization + :param key: key used to verify the signature + :param decode: a function to decode payload data + :return: dict + :raise: BadSignatureError + + If key is not provided, it will still deserialize the serialization + without verification. + """ + if isinstance(s, dict): + return self.deserialize_json(s, key, decode) + + s = to_bytes(s) + if s.startswith(b'{') and s.endswith(b'}'): + return self.deserialize_json(s, key, decode) + return self.deserialize_compact(s, key, decode) + + def _prepare_algorithm_key(self, header, payload, key): + if 'alg' not in header: + raise MissingAlgorithmError() + + alg = header['alg'] + if self._algorithms is not None and alg not in self._algorithms: + raise UnsupportedAlgorithmError() + if alg not in self.ALGORITHMS_REGISTRY: + raise UnsupportedAlgorithmError() + + algorithm = self.ALGORITHMS_REGISTRY[alg] + if callable(key): + key = key(header, payload) + elif key is None and 'jwk' in header: + key = header['jwk'] + key = algorithm.prepare_key(key) + return algorithm, key + + def _validate_private_headers(self, header): + # only validate private headers when developers set + # private headers explicitly + if self._private_headers is not None: + names = self.REGISTERED_HEADER_PARAMETER_NAMES.copy() + names = names.union(self._private_headers) + + for k in header: + if k not in names: + raise InvalidHeaderParameterNameError(k) + + def _validate_json_jws(self, payload_segment, payload, header_obj, key): + protected_segment = header_obj.get('protected') + if not protected_segment: + raise DecodeError('Missing "protected" value') + + signature_segment = header_obj.get('signature') + if not signature_segment: + raise DecodeError('Missing "signature" value') + + protected_segment = to_bytes(protected_segment) + protected = _extract_header(protected_segment) + header = header_obj.get('header') + if header and not isinstance(header, dict): + raise DecodeError('Invalid "header" value') + + jws_header = JWSHeader(protected, header) + algorithm, key = self._prepare_algorithm_key(jws_header, payload, key) + signing_input = b'.'.join([protected_segment, payload_segment]) + signature = _extract_signature(to_bytes(signature_segment)) + if algorithm.verify(signing_input, signature, key): + return jws_header, True + return jws_header, False + + +def _extract_header(header_segment): + return extract_header(header_segment, DecodeError) + + +def _extract_signature(signature_segment): + return extract_segment(signature_segment, DecodeError, 'signature') + + +def _extract_payload(payload_segment): + return extract_segment(payload_segment, DecodeError, 'payload') diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7515/models.py b/.venv/Lib/site-packages/authlib/jose/rfc7515/models.py new file mode 100644 index 00000000..5da3c7e0 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc7515/models.py @@ -0,0 +1,81 @@ +class JWSAlgorithm: + """Interface for JWS algorithm. JWA specification (RFC7518) SHOULD + implement the algorithms for JWS with this base implementation. + """ + name = None + description = None + algorithm_type = 'JWS' + algorithm_location = 'alg' + + def prepare_key(self, raw_data): + """Prepare key for signing and verifying signature.""" + raise NotImplementedError() + + def sign(self, msg, key): + """Sign the text msg with a private/sign key. + + :param msg: message bytes to be signed + :param key: private key to sign the message + :return: bytes + """ + raise NotImplementedError + + def verify(self, msg, sig, key): + """Verify the signature of text msg with a public/verify key. + + :param msg: message bytes to be signed + :param sig: result signature to be compared + :param key: public key to verify the signature + :return: boolean + """ + raise NotImplementedError + + +class JWSHeader(dict): + """Header object for JWS. It combine the protected header and unprotected + header together. JWSHeader itself is a dict of the combined dict. e.g. + + >>> protected = {'alg': 'HS256'} + >>> header = {'kid': 'a'} + >>> jws_header = JWSHeader(protected, header) + >>> print(jws_header) + {'alg': 'HS256', 'kid': 'a'} + >>> jws_header.protected == protected + >>> jws_header.header == header + + :param protected: dict of protected header + :param header: dict of unprotected header + """ + def __init__(self, protected, header): + obj = {} + if protected: + obj.update(protected) + if header: + obj.update(header) + super().__init__(obj) + self.protected = protected + self.header = header + + @classmethod + def from_dict(cls, obj): + if isinstance(obj, cls): + return obj + return cls(obj.get('protected'), obj.get('header')) + + +class JWSObject(dict): + """A dict instance to represent a JWS object.""" + def __init__(self, header, payload, type='compact'): + super().__init__( + header=header, + payload=payload, + ) + self.header = header + self.payload = payload + self.type = type + + @property + def headers(self): + """Alias of ``header`` for JSON typed JWS.""" + if self.type == 'json': + return self['header'] diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7516/__init__.py b/.venv/Lib/site-packages/authlib/jose/rfc7516/__init__.py new file mode 100644 index 00000000..4a024335 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc7516/__init__.py @@ -0,0 +1,18 @@ +""" + authlib.jose.rfc7516 + ~~~~~~~~~~~~~~~~~~~~~ + + This module represents a direct implementation of + JSON Web Encryption (JWE). + + https://tools.ietf.org/html/rfc7516 +""" + +from .jwe import JsonWebEncryption +from .models import JWEAlgorithm, JWEAlgorithmWithTagAwareKeyAgreement, JWEEncAlgorithm, JWEZipAlgorithm + + +__all__ = [ + 'JsonWebEncryption', + 'JWEAlgorithm', 'JWEAlgorithmWithTagAwareKeyAgreement', 'JWEEncAlgorithm', 'JWEZipAlgorithm' +] diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7516/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc7516/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4bbdf9f42257a94f8fccadc3614a6115102f7f26 GIT binary patch literal 701 zcmah`Pixdb6rai8b#*C%A0Vg)b1=b!6-p5nER|I%*p-D42-)OqGIb^sW~MFMgZM4H zdlAp#_oz3?)swe{-s;7fv}=1P_-6R={{G(My)UED5NY|d`yGB@gnk)gE!L%SwyBj* zs6+`WacNP^ti-}bx2esX#9?mYGB5F%pZFM6sB}K#WKg>MDD+Og4FfItp{gmFM+aO& zBo@W9r%yKfz=xY;*oUSykpbi7A%#FdD?mb{WRM3X5m2aru$BVTzFZOB1bop~P4?gH z1v8ijJ53>$Z6A6xneBwp1#7KTE4SiUaZY7KKrJFJs<>8+#_Pd;>s6o-cXua}H=65; zDs;L#nruufE{LjG_wc$k)2?Y=jgNByuV6W@1oQ)T8#+sqT$LF|LfU_h&=t1sDI5c? z0ndQ1VK2PZ`B_%-BFj4a;28SM&eNL#DsQSV={coY_7$CJ0(73f*h&jtlBP=E@x}CI zUc8s-TRj?^gI;R^O#x|i1kF+Un#@y46g+NqQeJ^fFHaYn)2%lYXBlaT%Ce|ko)5M! zj`Un?=w@bhGS#rMF~%!vfSnaGa1Y@Jr|ACm{}a`x|NAS?zHP108b12wiIHyb7s^S| AdH?_b literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7516/__pycache__/jwe.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc7516/__pycache__/jwe.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8538f6b1f131bdffd85571fe92d8e78d0332a26d GIT binary patch literal 31457 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 O>osbjwy6wQkNjWlHIl6W literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7516/__pycache__/models.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc7516/__pycache__/models.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..07ad29aa6b690cedafffaab12902b983e2928694 GIT binary patch literal 8497 zcmcgx+iw)t8K2qN%XoM3f(znai9%DUd8yRL{t4^IYE~mfiq!TYZ$>6kmA>@%ow@AQu1VUS z-T7wbeCPVzzcatvwk;~4{OjDGjIXx~!r$n{D`EFx{qK0VBj|!IW`q>o0~s+JNCiY8 zAe<9)>879ujlds5_as611ea4%632#tjTjQg2Z6`s;)5J71K-vXAL95Z@UeRV^u*=% z40B8zm~9Q12*FP>CRajS}>CDq{QO5*%2%}4eHqvCbwuHP?fb4Dlui`45k*1G*)04 z#S(F#j#YyVEjrMR5yjaKfMm>;)9IX=HPUH2noeWGGZ}i0r_=Aws2LX%NvHL^hU#r2 z?_9YwoE{w+K09*hvK=J69n(QvW)_NOK4-W4>`xcx3WnWLeb3}ImD(^O5!(guz*z;~ z3ky*#0lKWK01N(aEg**EH38tuox2xa`!beTI9uuHTDVx*wRd5xvS(j8*tHfELw(f7 z1!4cGT1QWO<9s4$Ok0-JC8Jtaoz8f2x~^au4LTEo=@6keL1+jx2O1K#iufO%`S;h3U zK`Blf)ln_3fi%$#=qPZerA%-Y_1bgFy9%ihg}t&>VGMC$WS!_|N2U!`H<-nC(p%V( zJ&Q(#WO}k0yus8$X-6$(2B~T?c5qLR&`bBq%m6y&mWT{gF zD)m!fixk!CsT?tL4K=(uH6jKSNZiSqCLIwRIdgV&;P@MFDUee&rx@?4B&SM#Qn6;V zX{z$g#(zm>9Z`*1Mh=2YR-Ap0c-A1Zy}q?X3oEVWbTX{m@Vg>kdSxq=tXkcT#-Z73 zw16CjSGKB=a#bU%8o&lHj4c_3>$apB07Z4mqS3i#`pWqPXI*-xkk1h@_)dvYY4j(-MRFQPFl-$z7X`e^Yyk>;%X=lGFS+XpE7xKq+#X=FLZQ260h1wLS!Z2($)w&3~R3u6fY_Qi&3t z?*aFTkH0KD2#kG28kUsoK;E(=GYobkpS9&PBNx+`&!f;7(ao^C8!cjn3 zyWpz%0QMw$S>%ThP$qWVE-fGY^}zk(D|`D_5(BG=fwDZnN&COp86(0V41EDN_9B2C zIe(RJiM@=s+6~404Vkm0CpO%VIr|cItlv)m{oa+mM^_U4tBL-y-0y71Cpy{_lQ^SN zc&KO8yjaf;un0CCO!FCZoq7r^Q6yXM7Clhk>qDeO@RQOQBWjm+oX^dw8BYb=@!Fy(Gm0}TH>4cV%)+$6Xq){CoMF;mx|3u%ajh+3$H-Atot*Drd>JEpL>T?U4 zIK2J8@(L7(U{s|6;z3;4aB+{t+pJ+($le<`>VytGa3J&yr6w+r+bC!DL06Ps zn*o<)z90>2@e2twmG!3pHu2y=cxXya1bA^ewhD7UoiYnee!659wtiAnJui6>aBQ(? zHJIXjmNHa}o8sE}1~nH$`>DoQ-)3%h1w+(L8->((6Yqt=sGGQoo2;8U*|rr?qO%e9 z4uJ-Vd6Vi0{0NsthU`B`%;TMz(8zVH_k8p^$@R|~n7=4YihAItj35qYt*MX^rr_-! zT7H7dDXGY!@E*cCh(m~r!{uq@mij0^UMQK)o8qKiN`B%R{DODV;rgsI`Rs(5Gc2XR z@bPud?1s|d^o+}fZw z1VuVd8WFO?GX?l&!wy+91%uI9AbDaO^tJf}vtu>XOS-2(X$;1G0$@wvirtn@^E0$` z+E1t#oV4u6Xv6icma&80GyET&@WI%>8}vV1nJn_9872WGmC zj6UiE>U9QSLHI{(*OIpU>`H9^YHUA=WOt>rYw%$nW%(2*X|ti{Cyk^o%mA=sT%m9}J)PItHLBU>Dw$?v zGU+sO$_do+6zr6vYm^)@0@U2H0H9XhZ!I9vaU=m*4!yJ{v;aE;p(7L)xIh-dJE+^R zNd1PzhY~7o{;;;nLDWJgNT5|{xcuVTvGqPwZR{zyHwY0o?KUvO^#eb5?vLpJ`Zuxu z+&8! zeDvgB&;!_}IgZdA&EO%`J*pzEicxCV3?5S5qbg!=w@9Y7HC)mka?GPz{P(wu;AS&e O3O=OTM=emCss9GoJ#VuB literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7516/jwe.py b/.venv/Lib/site-packages/authlib/jose/rfc7516/jwe.py new file mode 100644 index 00000000..084bccad --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc7516/jwe.py @@ -0,0 +1,722 @@ +from collections import OrderedDict +from copy import deepcopy + +from authlib.common.encoding import ( + to_bytes, urlsafe_b64encode, json_b64encode, to_unicode +) +from authlib.jose.rfc7516.models import JWEAlgorithmWithTagAwareKeyAgreement, JWESharedHeader, JWEHeader +from authlib.jose.util import ( + extract_header, + extract_segment, ensure_dict, +) +from authlib.jose.errors import ( + DecodeError, + MissingAlgorithmError, + UnsupportedAlgorithmError, + MissingEncryptionAlgorithmError, + UnsupportedEncryptionAlgorithmError, + UnsupportedCompressionAlgorithmError, + InvalidHeaderParameterNameError, InvalidAlgorithmForMultipleRecipientsMode, KeyMismatchError, +) + + +class JsonWebEncryption: + #: Registered Header Parameter Names defined by Section 4.1 + REGISTERED_HEADER_PARAMETER_NAMES = frozenset([ + 'alg', 'enc', 'zip', + 'jku', 'jwk', 'kid', + 'x5u', 'x5c', 'x5t', 'x5t#S256', + 'typ', 'cty', 'crit' + ]) + + ALG_REGISTRY = {} + ENC_REGISTRY = {} + ZIP_REGISTRY = {} + + def __init__(self, algorithms=None, private_headers=None): + self._algorithms = algorithms + self._private_headers = private_headers + + @classmethod + def register_algorithm(cls, algorithm): + """Register an algorithm for ``alg`` or ``enc`` or ``zip`` of JWE.""" + if not algorithm or algorithm.algorithm_type != 'JWE': + raise ValueError( + f'Invalid algorithm for JWE, {algorithm!r}') + + if algorithm.algorithm_location == 'alg': + cls.ALG_REGISTRY[algorithm.name] = algorithm + elif algorithm.algorithm_location == 'enc': + cls.ENC_REGISTRY[algorithm.name] = algorithm + elif algorithm.algorithm_location == 'zip': + cls.ZIP_REGISTRY[algorithm.name] = algorithm + + def serialize_compact(self, protected, payload, key, sender_key=None): + """Generate a JWE Compact Serialization. + + The JWE Compact Serialization represents encrypted content as a compact, + URL-safe string. This string is:: + + BASE64URL(UTF8(JWE Protected Header)) || '.' || + BASE64URL(JWE Encrypted Key) || '.' || + BASE64URL(JWE Initialization Vector) || '.' || + BASE64URL(JWE Ciphertext) || '.' || + BASE64URL(JWE Authentication Tag) + + Only one recipient is supported by the JWE Compact Serialization and + it provides no syntax to represent JWE Shared Unprotected Header, JWE + Per-Recipient Unprotected Header, or JWE AAD values. + + :param protected: A dict of protected header + :param payload: Payload (bytes or a value convertible to bytes) + :param key: Public key used to encrypt payload + :param sender_key: Sender's private key in case + JWEAlgorithmWithTagAwareKeyAgreement is used + :return: JWE compact serialization as bytes + """ + + # step 1: Prepare algorithms & key + alg = self.get_header_alg(protected) + enc = self.get_header_enc(protected) + zip_alg = self.get_header_zip(protected) + + self._validate_sender_key(sender_key, alg) + self._validate_private_headers(protected, alg) + + key = prepare_key(alg, protected, key) + if sender_key is not None: + sender_key = alg.prepare_key(sender_key) + + # self._post_validate_header(protected, algorithm) + + # step 2: Generate a random Content Encryption Key (CEK) + # use enc_alg.generate_cek() in scope of upcoming .wrap or .generate_keys_and_prepare_headers call + + # step 3: Encrypt the CEK with the recipient's public key + if isinstance(alg, JWEAlgorithmWithTagAwareKeyAgreement) and alg.key_size is not None: + # For a JWE algorithm with tag-aware key agreement in case key agreement with key wrapping mode is used: + # Defer key agreement with key wrapping until authentication tag is computed + prep = alg.generate_keys_and_prepare_headers(enc, key, sender_key) + epk = prep['epk'] + cek = prep['cek'] + protected.update(prep['header']) + else: + # In any other case: + # Keep the normal steps order defined by RFC 7516 + if isinstance(alg, JWEAlgorithmWithTagAwareKeyAgreement): + wrapped = alg.wrap(enc, protected, key, sender_key) + else: + wrapped = alg.wrap(enc, protected, key) + cek = wrapped['cek'] + ek = wrapped['ek'] + if 'header' in wrapped: + protected.update(wrapped['header']) + + # step 4: Generate a random JWE Initialization Vector + iv = enc.generate_iv() + + # step 5: Let the Additional Authenticated Data encryption parameter + # be ASCII(BASE64URL(UTF8(JWE Protected Header))) + protected_segment = json_b64encode(protected) + aad = to_bytes(protected_segment, 'ascii') + + # step 6: compress message if required + if zip_alg: + msg = zip_alg.compress(to_bytes(payload)) + else: + msg = to_bytes(payload) + + # step 7: perform encryption + ciphertext, tag = enc.encrypt(msg, aad, iv, cek) + + if isinstance(alg, JWEAlgorithmWithTagAwareKeyAgreement) and alg.key_size is not None: + # For a JWE algorithm with tag-aware key agreement in case key agreement with key wrapping mode is used: + # Perform key agreement with key wrapping deferred at step 3 + wrapped = alg.agree_upon_key_and_wrap_cek(enc, protected, key, sender_key, epk, cek, tag) + ek = wrapped['ek'] + + # step 8: build resulting message + return b'.'.join([ + protected_segment, + urlsafe_b64encode(ek), + urlsafe_b64encode(iv), + urlsafe_b64encode(ciphertext), + urlsafe_b64encode(tag) + ]) + + def serialize_json(self, header_obj, payload, keys, sender_key=None): + """Generate a JWE JSON Serialization (in fully general syntax). + + The JWE JSON Serialization represents encrypted content as a JSON + object. This representation is neither optimized for compactness nor + URL safe. + + The following members are defined for use in top-level JSON objects + used for the fully general JWE JSON Serialization syntax: + + protected + The "protected" member MUST be present and contain the value + BASE64URL(UTF8(JWE Protected Header)) when the JWE Protected + Header value is non-empty; otherwise, it MUST be absent. These + Header Parameter values are integrity protected. + + unprotected + The "unprotected" member MUST be present and contain the value JWE + Shared Unprotected Header when the JWE Shared Unprotected Header + value is non-empty; otherwise, it MUST be absent. This value is + represented as an unencoded JSON object, rather than as a string. + These Header Parameter values are not integrity protected. + + iv + The "iv" member MUST be present and contain the value + BASE64URL(JWE Initialization Vector) when the JWE Initialization + Vector value is non-empty; otherwise, it MUST be absent. + + aad + The "aad" member MUST be present and contain the value + BASE64URL(JWE AAD)) when the JWE AAD value is non-empty; + otherwise, it MUST be absent. A JWE AAD value can be included to + supply a base64url-encoded value to be integrity protected but not + encrypted. + + ciphertext + The "ciphertext" member MUST be present and contain the value + BASE64URL(JWE Ciphertext). + + tag + The "tag" member MUST be present and contain the value + BASE64URL(JWE Authentication Tag) when the JWE Authentication Tag + value is non-empty; otherwise, it MUST be absent. + + recipients + The "recipients" member value MUST be an array of JSON objects. + Each object contains information specific to a single recipient. + This member MUST be present with exactly one array element per + recipient, even if some or all of the array element values are the + empty JSON object "{}" (which can happen when all Header Parameter + values are shared between all recipients and when no encrypted key + is used, such as when doing Direct Encryption). + + The following members are defined for use in the JSON objects that + are elements of the "recipients" array: + + header + The "header" member MUST be present and contain the value JWE Per- + Recipient Unprotected Header when the JWE Per-Recipient + Unprotected Header value is non-empty; otherwise, it MUST be + absent. This value is represented as an unencoded JSON object, + rather than as a string. These Header Parameter values are not + integrity protected. + + encrypted_key + The "encrypted_key" member MUST be present and contain the value + BASE64URL(JWE Encrypted Key) when the JWE Encrypted Key value is + non-empty; otherwise, it MUST be absent. + + This implementation assumes that "alg" and "enc" header fields are + contained in the protected or shared unprotected header. + + :param header_obj: A dict of headers (in addition optionally contains JWE AAD) + :param payload: Payload (bytes or a value convertible to bytes) + :param keys: Public keys (or a single public key) used to encrypt payload + :param sender_key: Sender's private key in case + JWEAlgorithmWithTagAwareKeyAgreement is used + :return: JWE JSON serialization (in fully general syntax) as dict + + Example of `header_obj`:: + + { + "protected": { + "alg": "ECDH-1PU+A128KW", + "enc": "A256CBC-HS512", + "apu": "QWxpY2U", + "apv": "Qm9iIGFuZCBDaGFybGll" + }, + "unprotected": { + "jku": "https://alice.example.com/keys.jwks" + }, + "recipients": [ + { + "header": { + "kid": "bob-key-2" + } + }, + { + "header": { + "kid": "2021-05-06" + } + } + ], + "aad": b'Authenticate me too.' + } + """ + if not isinstance(keys, list): # single key + keys = [keys] + + if not keys: + raise ValueError("No keys have been provided") + + header_obj = deepcopy(header_obj) + + shared_header = JWESharedHeader.from_dict(header_obj) + + recipients = header_obj.get('recipients') + if recipients is None: + recipients = [{} for _ in keys] + for i in range(len(recipients)): + if recipients[i] is None: + recipients[i] = {} + if 'header' not in recipients[i]: + recipients[i]['header'] = {} + + jwe_aad = header_obj.get('aad') + + if len(keys) != len(recipients): + raise ValueError("Count of recipient keys {} does not equal to count of recipients {}" + .format(len(keys), len(recipients))) + + # step 1: Prepare algorithms & key + alg = self.get_header_alg(shared_header) + enc = self.get_header_enc(shared_header) + zip_alg = self.get_header_zip(shared_header) + + self._validate_sender_key(sender_key, alg) + self._validate_private_headers(shared_header, alg) + for recipient in recipients: + self._validate_private_headers(recipient['header'], alg) + + for i in range(len(keys)): + keys[i] = prepare_key(alg, recipients[i]['header'], keys[i]) + if sender_key is not None: + sender_key = alg.prepare_key(sender_key) + + # self._post_validate_header(protected, algorithm) + + # step 2: Generate a random Content Encryption Key (CEK) + # use enc_alg.generate_cek() in scope of upcoming .wrap or .generate_keys_and_prepare_headers call + + # step 3: Encrypt the CEK with the recipient's public key + preset = alg.generate_preset(enc, keys[0]) + if 'cek' in preset: + cek = preset['cek'] + else: + cek = None + if len(keys) > 1 and cek is None: + raise InvalidAlgorithmForMultipleRecipientsMode(alg.name) + if 'header' in preset: + shared_header.update_protected(preset['header']) + + if isinstance(alg, JWEAlgorithmWithTagAwareKeyAgreement) and alg.key_size is not None: + # For a JWE algorithm with tag-aware key agreement in case key agreement with key wrapping mode is used: + # Defer key agreement with key wrapping until authentication tag is computed + epks = [] + for i in range(len(keys)): + prep = alg.generate_keys_and_prepare_headers(enc, keys[i], sender_key, preset) + if cek is None: + cek = prep['cek'] + epks.append(prep['epk']) + recipients[i]['header'].update(prep['header']) + else: + # In any other case: + # Keep the normal steps order defined by RFC 7516 + for i in range(len(keys)): + if isinstance(alg, JWEAlgorithmWithTagAwareKeyAgreement): + wrapped = alg.wrap(enc, shared_header, keys[i], sender_key, preset) + else: + wrapped = alg.wrap(enc, shared_header, keys[i], preset) + if cek is None: + cek = wrapped['cek'] + recipients[i]['encrypted_key'] = wrapped['ek'] + if 'header' in wrapped: + recipients[i]['header'].update(wrapped['header']) + + # step 4: Generate a random JWE Initialization Vector + iv = enc.generate_iv() + + # step 5: Compute the Encoded Protected Header value + # BASE64URL(UTF8(JWE Protected Header)). If the JWE Protected Header + # is not present, let this value be the empty string. + # Let the Additional Authenticated Data encryption parameter be + # ASCII(Encoded Protected Header). However, if a JWE AAD value is + # present, instead let the Additional Authenticated Data encryption + # parameter be ASCII(Encoded Protected Header || '.' || BASE64URL(JWE AAD)). + aad = json_b64encode(shared_header.protected) if shared_header.protected else b'' + if jwe_aad is not None: + aad += b'.' + urlsafe_b64encode(jwe_aad) + aad = to_bytes(aad, 'ascii') + + # step 6: compress message if required + if zip_alg: + msg = zip_alg.compress(to_bytes(payload)) + else: + msg = to_bytes(payload) + + # step 7: perform encryption + ciphertext, tag = enc.encrypt(msg, aad, iv, cek) + + if isinstance(alg, JWEAlgorithmWithTagAwareKeyAgreement) and alg.key_size is not None: + # For a JWE algorithm with tag-aware key agreement in case key agreement with key wrapping mode is used: + # Perform key agreement with key wrapping deferred at step 3 + for i in range(len(keys)): + wrapped = alg.agree_upon_key_and_wrap_cek(enc, shared_header, keys[i], sender_key, epks[i], cek, tag) + recipients[i]['encrypted_key'] = wrapped['ek'] + + # step 8: build resulting message + obj = OrderedDict() + + if shared_header.protected: + obj['protected'] = to_unicode(json_b64encode(shared_header.protected)) + + if shared_header.unprotected: + obj['unprotected'] = shared_header.unprotected + + for recipient in recipients: + if not recipient['header']: + del recipient['header'] + recipient['encrypted_key'] = to_unicode(urlsafe_b64encode(recipient['encrypted_key'])) + for member in set(recipient.keys()): + if member not in {'header', 'encrypted_key'}: + del recipient[member] + obj['recipients'] = recipients + + if jwe_aad is not None: + obj['aad'] = to_unicode(urlsafe_b64encode(jwe_aad)) + + obj['iv'] = to_unicode(urlsafe_b64encode(iv)) + + obj['ciphertext'] = to_unicode(urlsafe_b64encode(ciphertext)) + + obj['tag'] = to_unicode(urlsafe_b64encode(tag)) + + return obj + + def serialize(self, header, payload, key, sender_key=None): + """Generate a JWE Serialization. + + It will automatically generate a compact or JSON serialization depending + on `header` argument. If `header` is a dict with "protected", + "unprotected" and/or "recipients" keys, it will call `serialize_json`, + otherwise it will call `serialize_compact`. + + :param header: A dict of header(s) + :param payload: Payload (bytes or a value convertible to bytes) + :param key: Public key(s) used to encrypt payload + :param sender_key: Sender's private key in case + JWEAlgorithmWithTagAwareKeyAgreement is used + :return: JWE compact serialization as bytes or + JWE JSON serialization as dict + """ + if 'protected' in header or 'unprotected' in header or 'recipients' in header: + return self.serialize_json(header, payload, key, sender_key) + + return self.serialize_compact(header, payload, key, sender_key) + + def deserialize_compact(self, s, key, decode=None, sender_key=None): + """Extract JWE Compact Serialization. + + :param s: JWE Compact Serialization as bytes + :param key: Private key used to decrypt payload + (optionally can be a tuple of kid and essentially key) + :param decode: Function to decode payload data + :param sender_key: Sender's public key in case + JWEAlgorithmWithTagAwareKeyAgreement is used + :return: dict with `header` and `payload` keys where `header` value is + a dict containing protected header fields + """ + try: + s = to_bytes(s) + protected_s, ek_s, iv_s, ciphertext_s, tag_s = s.rsplit(b'.') + except ValueError: + raise DecodeError('Not enough segments') + + protected = extract_header(protected_s, DecodeError) + ek = extract_segment(ek_s, DecodeError, 'encryption key') + iv = extract_segment(iv_s, DecodeError, 'initialization vector') + ciphertext = extract_segment(ciphertext_s, DecodeError, 'ciphertext') + tag = extract_segment(tag_s, DecodeError, 'authentication tag') + + alg = self.get_header_alg(protected) + enc = self.get_header_enc(protected) + zip_alg = self.get_header_zip(protected) + + self._validate_sender_key(sender_key, alg) + self._validate_private_headers(protected, alg) + + if isinstance(key, tuple) and len(key) == 2: + # Ignore separately provided kid, extract essentially key only + key = key[1] + + key = prepare_key(alg, protected, key) + + if sender_key is not None: + sender_key = alg.prepare_key(sender_key) + + if isinstance(alg, JWEAlgorithmWithTagAwareKeyAgreement): + # For a JWE algorithm with tag-aware key agreement: + if alg.key_size is not None: + # In case key agreement with key wrapping mode is used: + # Provide authentication tag to .unwrap method + cek = alg.unwrap(enc, ek, protected, key, sender_key, tag) + else: + # Otherwise, don't provide authentication tag to .unwrap method + cek = alg.unwrap(enc, ek, protected, key, sender_key) + else: + # For any other JWE algorithm: + # Don't provide authentication tag to .unwrap method + cek = alg.unwrap(enc, ek, protected, key) + + aad = to_bytes(protected_s, 'ascii') + msg = enc.decrypt(ciphertext, aad, iv, tag, cek) + + if zip_alg: + payload = zip_alg.decompress(to_bytes(msg)) + else: + payload = msg + + if decode: + payload = decode(payload) + return {'header': protected, 'payload': payload} + + def deserialize_json(self, obj, key, decode=None, sender_key=None): + """Extract JWE JSON Serialization. + + :param obj: JWE JSON Serialization as dict or str + :param key: Private key used to decrypt payload + (optionally can be a tuple of kid and essentially key) + :param decode: Function to decode payload data + :param sender_key: Sender's public key in case + JWEAlgorithmWithTagAwareKeyAgreement is used + :return: dict with `header` and `payload` keys where `header` value is + a dict containing `protected`, `unprotected`, `recipients` and/or + `aad` keys + """ + obj = ensure_dict(obj, 'JWE') + obj = deepcopy(obj) + + if 'protected' in obj: + protected = extract_header(to_bytes(obj['protected']), DecodeError) + else: + protected = None + + unprotected = obj.get('unprotected') + + recipients = obj['recipients'] + for recipient in recipients: + if 'header' not in recipient: + recipient['header'] = {} + recipient['encrypted_key'] = extract_segment( + to_bytes(recipient['encrypted_key']), DecodeError, 'encrypted key') + + if 'aad' in obj: + jwe_aad = extract_segment(to_bytes(obj['aad']), DecodeError, 'JWE AAD') + else: + jwe_aad = None + + iv = extract_segment(to_bytes(obj['iv']), DecodeError, 'initialization vector') + + ciphertext = extract_segment(to_bytes(obj['ciphertext']), DecodeError, 'ciphertext') + + tag = extract_segment(to_bytes(obj['tag']), DecodeError, 'authentication tag') + + shared_header = JWESharedHeader(protected, unprotected) + + alg = self.get_header_alg(shared_header) + enc = self.get_header_enc(shared_header) + zip_alg = self.get_header_zip(shared_header) + + self._validate_sender_key(sender_key, alg) + self._validate_private_headers(shared_header, alg) + for recipient in recipients: + self._validate_private_headers(recipient['header'], alg) + + kid = None + if isinstance(key, tuple) and len(key) == 2: + # Extract separately provided kid and essentially key + kid = key[0] + key = key[1] + + key = alg.prepare_key(key) + + if kid is None: + # If kid has not been provided separately, try to get it from key itself + kid = key.kid + + if sender_key is not None: + sender_key = alg.prepare_key(sender_key) + + def _unwrap_with_sender_key_and_tag(ek, header): + return alg.unwrap(enc, ek, header, key, sender_key, tag) + + def _unwrap_with_sender_key_and_without_tag(ek, header): + return alg.unwrap(enc, ek, header, key, sender_key) + + def _unwrap_without_sender_key_and_tag(ek, header): + return alg.unwrap(enc, ek, header, key) + + def _unwrap_for_matching_recipient(unwrap_func): + if kid is not None: + for recipient in recipients: + if recipient['header'].get('kid') == kid: + header = JWEHeader(protected, unprotected, recipient['header']) + return unwrap_func(recipient['encrypted_key'], header) + + # Since no explicit match has been found, iterate over all the recipients + error = None + for recipient in recipients: + header = JWEHeader(protected, unprotected, recipient['header']) + try: + return unwrap_func(recipient['encrypted_key'], header) + except Exception as e: + error = e + else: + if error is None: + raise KeyMismatchError() + else: + raise error + + if isinstance(alg, JWEAlgorithmWithTagAwareKeyAgreement): + # For a JWE algorithm with tag-aware key agreement: + if alg.key_size is not None: + # In case key agreement with key wrapping mode is used: + # Provide authentication tag to .unwrap method + cek = _unwrap_for_matching_recipient(_unwrap_with_sender_key_and_tag) + else: + # Otherwise, don't provide authentication tag to .unwrap method + cek = _unwrap_for_matching_recipient(_unwrap_with_sender_key_and_without_tag) + else: + # For any other JWE algorithm: + # Don't provide authentication tag to .unwrap method + cek = _unwrap_for_matching_recipient(_unwrap_without_sender_key_and_tag) + + aad = to_bytes(obj.get('protected', '')) + if 'aad' in obj: + aad += b'.' + to_bytes(obj['aad']) + aad = to_bytes(aad, 'ascii') + + msg = enc.decrypt(ciphertext, aad, iv, tag, cek) + + if zip_alg: + payload = zip_alg.decompress(to_bytes(msg)) + else: + payload = msg + + if decode: + payload = decode(payload) + + for recipient in recipients: + if not recipient['header']: + del recipient['header'] + for member in set(recipient.keys()): + if member != 'header': + del recipient[member] + + header = {} + if protected: + header['protected'] = protected + if unprotected: + header['unprotected'] = unprotected + header['recipients'] = recipients + if jwe_aad is not None: + header['aad'] = jwe_aad + + return { + 'header': header, + 'payload': payload + } + + def deserialize(self, obj, key, decode=None, sender_key=None): + """Extract a JWE Serialization. + + It supports both compact and JSON serialization. + + :param obj: JWE compact serialization as bytes or + JWE JSON serialization as dict or str + :param key: Private key used to decrypt payload + (optionally can be a tuple of kid and essentially key) + :param decode: Function to decode payload data + :param sender_key: Sender's public key in case + JWEAlgorithmWithTagAwareKeyAgreement is used + :return: dict with `header` and `payload` keys + """ + if isinstance(obj, dict): + return self.deserialize_json(obj, key, decode, sender_key) + + obj = to_bytes(obj) + if obj.startswith(b'{') and obj.endswith(b'}'): + return self.deserialize_json(obj, key, decode, sender_key) + + return self.deserialize_compact(obj, key, decode, sender_key) + + @staticmethod + def parse_json(obj): + """Parse JWE JSON Serialization. + + :param obj: JWE JSON Serialization as str or dict + :return: Parsed JWE JSON Serialization as dict if `obj` is an str, + or `obj` as is if `obj` is already a dict + """ + return ensure_dict(obj, 'JWE') + + def get_header_alg(self, header): + if 'alg' not in header: + raise MissingAlgorithmError() + + alg = header['alg'] + if self._algorithms is not None and alg not in self._algorithms: + raise UnsupportedAlgorithmError() + if alg not in self.ALG_REGISTRY: + raise UnsupportedAlgorithmError() + return self.ALG_REGISTRY[alg] + + def get_header_enc(self, header): + if 'enc' not in header: + raise MissingEncryptionAlgorithmError() + enc = header['enc'] + if self._algorithms is not None and enc not in self._algorithms: + raise UnsupportedEncryptionAlgorithmError() + if enc not in self.ENC_REGISTRY: + raise UnsupportedEncryptionAlgorithmError() + return self.ENC_REGISTRY[enc] + + def get_header_zip(self, header): + if 'zip' in header: + z = header['zip'] + if self._algorithms is not None and z not in self._algorithms: + raise UnsupportedCompressionAlgorithmError() + if z not in self.ZIP_REGISTRY: + raise UnsupportedCompressionAlgorithmError() + return self.ZIP_REGISTRY[z] + + def _validate_sender_key(self, sender_key, alg): + if isinstance(alg, JWEAlgorithmWithTagAwareKeyAgreement): + if sender_key is None: + raise ValueError("{} algorithm requires sender_key but passed sender_key value is None" + .format(alg.name)) + else: + if sender_key is not None: + raise ValueError("{} algorithm does not use sender_key but passed sender_key value is not None" + .format(alg.name)) + + def _validate_private_headers(self, header, alg): + # only validate private headers when developers set + # private headers explicitly + if self._private_headers is None: + return + + names = self.REGISTERED_HEADER_PARAMETER_NAMES.copy() + names = names.union(self._private_headers) + + if alg.EXTRA_HEADERS: + names = names.union(alg.EXTRA_HEADERS) + + for k in header: + if k not in names: + raise InvalidHeaderParameterNameError(k) + + +def prepare_key(alg, header, key): + if callable(key): + key = key(header, None) + elif key is None and 'jwk' in header: + key = header['jwk'] + return alg.prepare_key(key) diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7516/models.py b/.venv/Lib/site-packages/authlib/jose/rfc7516/models.py new file mode 100644 index 00000000..279563cf --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc7516/models.py @@ -0,0 +1,148 @@ +import os +from abc import ABCMeta + + +class JWEAlgorithmBase(metaclass=ABCMeta): + """Base interface for all JWE algorithms. + """ + EXTRA_HEADERS = None + + name = None + description = None + algorithm_type = 'JWE' + algorithm_location = 'alg' + + def prepare_key(self, raw_data): + raise NotImplementedError + + def generate_preset(self, enc_alg, key): + raise NotImplementedError + + +class JWEAlgorithm(JWEAlgorithmBase, metaclass=ABCMeta): + """Interface for JWE algorithm conforming to RFC7518. + JWA specification (RFC7518) SHOULD implement the algorithms for JWE with this base implementation. + """ + def wrap(self, enc_alg, headers, key, preset=None): + raise NotImplementedError + + def unwrap(self, enc_alg, ek, headers, key): + raise NotImplementedError + + +class JWEAlgorithmWithTagAwareKeyAgreement(JWEAlgorithmBase, metaclass=ABCMeta): + """Interface for JWE algorithm with tag-aware key agreement (in key agreement with key wrapping mode). + ECDH-1PU is an example of such an algorithm. + """ + def generate_keys_and_prepare_headers(self, enc_alg, key, sender_key, preset=None): + raise NotImplementedError + + def agree_upon_key_and_wrap_cek(self, enc_alg, headers, key, sender_key, epk, cek, tag): + raise NotImplementedError + + def wrap(self, enc_alg, headers, key, sender_key, preset=None): + raise NotImplementedError + + def unwrap(self, enc_alg, ek, headers, key, sender_key, tag=None): + raise NotImplementedError + + +class JWEEncAlgorithm: + name = None + description = None + algorithm_type = 'JWE' + algorithm_location = 'enc' + + IV_SIZE = None + CEK_SIZE = None + + def generate_cek(self): + return os.urandom(self.CEK_SIZE // 8) + + def generate_iv(self): + return os.urandom(self.IV_SIZE // 8) + + def check_iv(self, iv): + if len(iv) * 8 != self.IV_SIZE: + raise ValueError('Invalid "iv" size') + + def encrypt(self, msg, aad, iv, key): + """Encrypt the given "msg" text. + + :param msg: text to be encrypt in bytes + :param aad: additional authenticated data in bytes + :param iv: initialization vector in bytes + :param key: encrypted key in bytes + :return: (ciphertext, tag) + """ + raise NotImplementedError + + def decrypt(self, ciphertext, aad, iv, tag, key): + """Decrypt the given cipher text. + + :param ciphertext: ciphertext in bytes + :param aad: additional authenticated data in bytes + :param iv: initialization vector in bytes + :param tag: authentication tag in bytes + :param key: encrypted key in bytes + :return: message + """ + raise NotImplementedError + + +class JWEZipAlgorithm: + name = None + description = None + algorithm_type = 'JWE' + algorithm_location = 'zip' + + def compress(self, s): + raise NotImplementedError + + def decompress(self, s): + raise NotImplementedError + + +class JWESharedHeader(dict): + """Shared header object for JWE. + + Combines protected header and shared unprotected header together. + """ + def __init__(self, protected, unprotected): + obj = {} + if protected: + obj.update(protected) + if unprotected: + obj.update(unprotected) + super().__init__(obj) + self.protected = protected if protected else {} + self.unprotected = unprotected if unprotected else {} + + def update_protected(self, addition): + self.update(addition) + self.protected.update(addition) + + @classmethod + def from_dict(cls, obj): + if isinstance(obj, cls): + return obj + return cls(obj.get('protected'), obj.get('unprotected')) + + +class JWEHeader(dict): + """Header object for JWE. + + Combines protected header, shared unprotected header and specific recipient's unprotected header together. + """ + def __init__(self, protected, unprotected, header): + obj = {} + if protected: + obj.update(protected) + if unprotected: + obj.update(unprotected) + if header: + obj.update(header) + super().__init__(obj) + self.protected = protected if protected else {} + self.unprotected = unprotected if unprotected else {} + self.header = header if header else {} diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7517/__init__.py b/.venv/Lib/site-packages/authlib/jose/rfc7517/__init__.py new file mode 100644 index 00000000..d3fbbb2d --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc7517/__init__.py @@ -0,0 +1,17 @@ +""" + authlib.jose.rfc7517 + ~~~~~~~~~~~~~~~~~~~~~ + + This module represents a direct implementation of + JSON Web Key (JWK). + + https://tools.ietf.org/html/rfc7517 +""" +from ._cryptography_key import load_pem_key +from .base_key import Key +from .asymmetric_key import AsymmetricKey +from .key_set import KeySet +from .jwk import JsonWebKey + + +__all__ = ['Key', 'AsymmetricKey', 'KeySet', 'JsonWebKey', 'load_pem_key'] diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7517/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc7517/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9221268d64fa48d5fb404be345e4c43ba1989b4d GIT binary patch literal 752 zcmZuu&x_MQ6rO3?B%9re?oGVpXi-x<$ilJ+f}pfg!LBTXz>p@>c6MhnVPr0mMq1a#o|`#mlju}x8mVb^@aW+|lX(9>37XXLoas=={G8KJ(Na-O3!}p{%$cH@37IH4 z6%b1elSL?}&0mA@%TahjC*hD*;oZT>uotcA=Ejuzu-`XQavd>hrjb;${@e)O-%Ruq zc7uAj-s3XONl67cqZRlLkipY^qAMY&Q7l^rTzJORKq?q$SwLGG@2ED=sE!5Kf@i@2 z81?pQkC0qugw(f4rmE7&nM%ufWji%BwLeKUZCp!J-$?&7ZGx7z_Mn<*n8fne&gq-8 zrimp_IVa>Rx`YI}N}e7jnao)+OJ2+A@$)o0)5$B?nwU^nXhw^SCeZ~gE|M2)l4xe= zgA$6;8P&=4(famin-%p5VFfdUL}hj5AFa>xSnWeIyF2|3VC7(pS1lj6SIELX!uJ>G n-ru@Jw-?*GM7_nfF43LEw*DJgxoCHY7r_AZgJ(Z=6DIf#J*(T2 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7517/__pycache__/_cryptography_key.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc7517/__pycache__/_cryptography_key.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d9c4f90238954e59d134ff133d49d17f37973de5 GIT binary patch literal 2014 zcmbtV&ube;6rSCcv}-wLlh|$=Vi!>t8i6glO@r-Hnpm>a8iE=uTM!`-tKG4+^{!UT zjO-{VB!wQ@QmAMT?olVV#Vz!b{~)=qf(~ZE5a=m4fiEV#^v%lF4`>CchqsUS-pqXa z=FRtZe;FAGBN%^w_7uMgAoLe^&W3nu9Nz(B4;jc1EMyBALEyG%iMEuH>_8@92QxuG zCRrg{&d9zUuoQbJGX%D5guWIsVI!DAQRNi}jSAjX%h8Nn3EQ~`H|G{}Iws8AG_~w4Aq0y(dU%Ay?`I0bVumrdGCCF0bj^xM)B~VNNbzVVEX$ zIB92uz>?rOuETlv5ED8xsEYQ%JLp6np{hVWtfG1+(p`&Su75R|WWnxy6*0N%?SpyH zaeo)~;oS#k^+qXF6%BFQ_W@<7vk)?RLlmivLdB}|)jMps7pW=@zzXa`O%8Zn{EhL?>noHKA+fTyzItah0e*CdC=l_&lxc*~U6U0E-%0o$!dXms%Mi{7FWhZ3 zFPzq_GF~CXA<>{G5pCB~crUU_3401Ot#1*2TV8WUlr=t!NaC;q(t{ENo&Mssdi~eYKb%JFRx@_1q26w)x4#J-s-r(V{_b%@jWpGWt3+A>3C=zM@Z@NC zyj_f5{hwJvZ9rNQujt9i3B3$Oe-@lvoGjw1>9FVnBA=WabX0F^Y+)S>{8HnNG3IQJ<}xyxzpWZ9Z)s>Qmdha>}Ea?%1|d zi~;9-M*8jGljS#b3|NSagL~!aQR<={san6DF}yX-tCu`C<f`A-F|6>t_lgEg$8Ld0eSrcHPPWi literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7517/__pycache__/asymmetric_key.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc7517/__pycache__/asymmetric_key.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..980712787ba375d2af717ff54fb2239bf4bca82d GIT binary patch literal 9847 zcmcIKTWlLwb~BtIHR4m^OK*`Pk?0^7fQ&Ip5w7(jr4)*lP>L#gu-q(4394mo_< zak1#t@XXA;=bn4-x#xLD|LAa7DJcJQ;Sa*wy%hBy_);zA%EQxHcz8td6i=t9G##aB zd^V*_X(q~~*(jSfN6l$V)ROLqc0e1$vnej!8SNy`=9D#Ui`r<)L|veG%Uz1^5Nw|@ z6!iuC^b)o6+zb`z{4>5rXpPHfW3!8SL5i3)?tCVZ<&&9t&2d>w-j3&m$*h=;=QaD~ zh1paxQF-e*BS`tvx8uoFd^ROOA8|34Pi8ZkeJWdf`!lT%U{7V^d@LuVW4DAw7?62G zSWM`1(P4FJPp#176Ii@JMQNUjns_?O%u`VoerCZE?SLQ0o1&e3Uy+)ldG>B+)GF9` z^IhsQp!9`76P5@|k2?4cfKHwR=;Av8cJWq#-MkH;o3{h>@D6}p-U-mh_w!wM>8Ky> z-Ei;W2Y5H!d-*}$1NT0-d*R+M4Dds|?=Iam>L982x6}_oeNW3AhoN?u?`^>j6seEs zXb`q2pgB%Ui|MqG7n2EK+R~n@H@cz9Y;A z0d@Q-GGi*i8a$yWWHbJr&H?x({fNrr231PqQc86#RSb$MFrPvF7e*UR73cyLGgUDP zCU~oECP?iJ^*KEiVKuX~kP}3Wi^Y2g|m_2vwx-PKS-_FimeJ!52C0(Bu(n5Mx5CthAWD>&l z@!LY?_VqWDv)83$UU(@7Nbz|=x*lK1-$*5A_ub4&!ai{>arodXhxf$|hU0|BbBm%I zMqBbXY{YnVCDb{1Kc>n-<>7TE`` zBK(O?=#nt_2rtM(vNuTV5mlgW!d)*SsKE?a0H`y1+@>nE42TIkHL213)rg6(O|#^) zw}g!JIW78tfP{U5B3K&=*sgOrn@KG$^);@juBivRMF6Z&TQ-+!8`!4k&c3pzclBV| z=3E_pI40YM;L>Yco?>2Kk0A%p)sVHnffrm)3GS_>K(~{qhIM+OZ#`v$NTbBg;24JN z8A$NZj2EGo{_}#6Cpsj??*w6+i2|Wc%_l)tuqKwxjR%Rgf%e_V^1(aFR4N!xNm(mO z9+t!nA#p31oFjzlJEDSu#OJbNUf_eXi+}(%C{0$Q^RZl9jHiQH(2F=)&SPX6#%u6) zJhdR~1u}^n!MGF*Ny+(4Xm2nC0*$sdG+v`53i$;Q2vpW$G=SpS$sAFTVLh7j^4n+L zym&VD#`*VRmoCp}&Uqmpt0|x6BJVZL1c5>c(mIW4Nw^WgiZodfJ)1-7OTCT4RBH)9 z2kCVHE7Z1=>U3;yed}D`T14SSRc=(~M$0zu8msn#Na0oX^lW%`u6uSWp53Zvw`|{C zc6l~j;dNJ7aqUoDJ7jLhbChQV25M5Cj(SxhLSiTpARDDoNS5gWEqV)d$!M>CXv9UD zHD#Tl#4f-E)}i$hL;5qaktk<91H}=jT^elVTy0Cn07JR}V1+8%Tn|p6B8GuS4^PSV z(3Zb{!@p*?I z$5>a>OJL3mX(f1wHq2pk`#u0eYI<-0vWs#g4&s7q7K`w2X{Zg0YEpU-yBr5VcvP`g zqrfE96PE2^uwW04BU^%Hd)J12Xx%=f*aNCPAlm~VTdFG{bAjjZWd$fhGzNaIw#i_9 z2Vng#AV~Gz5&hwd*(m76!my-ZuZU?%?1#6AStLB`(gUg*4|K!t(yI+`s*7MVOLqaG zrT#{il8%)nrGCZLU zPZZBRxKxC{R;J>jh?DyU9-4%092jgcw7tQ9G3GTp6rJraK-*wBOwK5cy55equJ2}j z3#>6dnaIcZcs{OK7IJVGv~GSOos(kqAx~GOs zg%<(oDMnEccR5ECXIOQHWiI@e&r;kEL|f*x59c)8c233~zKI zkgRzU&6eQO|Mw*J;3S$Xa+BSeZkWSl0tKa7P+)BEd+G&c|AhL4eMH@>v#j@7aJ(L# zzQ^9CMOPlND}^^TD&NO|)80(*On%&KOba@XhGLkNs1HRe{5ZxBYD4CYr)QC5FxdPF6`E&bGs zG0#0yy_5SV8`Llbx{pj3!QYu4_#mmnQ-kihU~=-}`8UtaK)h)he_5k%k*JY)Dhb&H zdD;reKYp;Dz!fC2>Dk0Mv75NZetMN5|iT-t;{sxffAgn#V7_sP1(|QdZr_q$=7yKZv(dUF95!W6>N3; z9u5>OWt$I!l7nmE(lxn%46aT0pgeRyaZjl33E4ie<@A1f^Zv~>pW+Ot&OnhtXS}oc zYVp-lfAQ6=Dj#%iJf4KR;+s}|)5Xd1VDQ(k6(?5@-g~R;a>FQ&(Q+`nYFSffP}$`xI&@=Jufm4izXnSJFOHG& zGt#?8@A;z9Hz)zUG~8YZDoM^b1lS=Mp2X0VJViW@e8$;TGZYK#3wlp)%eFvm60y z7U7xb$U{@L)S{4OIcfO#X z2IbENFQ0#F-?{VCcoYB!o{+Y~iD+xW4*54ZA3YWfL5ENf4&Fl0D`aHdmBhYgK8^(i zeWXeNs3-bjor!Mln}Z|0J6Vy3o_e+)tnYd!nZFUNqSU%pPXWlhjp`|lfoWtO%o~LDAlV4&oH{a*C(~;u{D^ z=yL|2FfJ2uheZ@y5%ofIR6}1fHxczkGhcq=?936(UdeU!77Mm`XBK8}3W@w>5?H+< zEMCmaWxZ32A_3hN9bM4r~CS-h6~ttWX^min423-8Buh(0{|Td)>3U+&8k>GphFNDepMC-9dRH z-%_mC`5l67igh@*tyEW!eri(o4Q+Y?s%K)`Om&TZOEF#6?+|QLOs7@1Wk$dQJisj_ zw(MnizznSf_tpZ(zNRnf7OgT(frQ}hh*tr?0VH~e&l!E|jCu(NF!l#+G<+IpW22$= z7l0|DPD5(r@_f2{fBCWX>vxOGifdAJP0HM4>k7<(O;&(${Igd82|cdC)NETK%oLI4 z2&0R-F>CQ%peMcupmqMdAhwx5)ILOX%-oInmxQma-;fntQ(f0&?po^#aQ0*c75_?= zprW<39-W$CzsSCTANm4*dRc}DuE4~M_W~Xn!%oqn9}prY&8Hs{io%BrNm1Zqb4ek^ zOCm;G5YjP;l%z4BVgwx`Dq*n_)m1gjl}w{0)iYmow@ukWQ}ZLBD@_0ZzsuP+xRG^k zq!d=Tohr9e=605y-NnS(F4-AUoFUa2g21P5u*f`cLM&5kBeBMQUj_T#n1$lUiAEU} zhYO~k_ZR4zA8wyQH2Y2b&@t2Sxdds~QiY~boMb23=*TjY`S<#dE`$o|94XJFVrpyw zD*xO_C2#mkIPPxnbz%?bFxteH0%Nz*{RH^aQ!th4Vvbrz_|(`$eVNUecxsu=ch|7U znmViR1@=p}QOB0e4RbgDC?CzOwgxz`zlF;4`G{0n*XzooTd5SjO&o*?8Co?j;8YYw zKfFZcA!ZH~39a4IaMiuy;Sc$spbI{HOhuO;v1yP~Br{Sz4&S5*DUxtBoXVelb4GJr zp1yeP^wsm^m>w%wOq#@57(-)n*_?=bt#!}LycVmZV3()QPhNaiME?tZG6pyC0|aD> zaeTrFiX;tbc8}JIcB0-k9pcwoehb~DC|Hmc>WR&_npiua*aE68fKH^R?DEU5P`S(V z(6-SPTJH*#4l7+_YS)cC5iZCtgDZ&Tf!XX&!rw;C>a9?#3}LyG&5 z>ONFFTRgkz=viadX4IjV6~`;8cEjzZk5{_2&{6O{!r<_V@BQm z>NlM1zoPiBsQxR(3!ARKwOyqHYWSeyI;6S|ZBu3kOx)kMnkc>V)x7LKsrXN-{*$ZB zDzn)=uy&y|qwYAObRSi_j{<89-1)EW$o^A`|CH)Kg}6`9|DRU;XH@?gx$8`wVFT4Q z3W{@`8)y)BG(LtwZ&di4w*}Ln+K5^GRKbWm3?&K(<^X`S6B$CuX-KEKNcadxnz2g6 z)qEJ$-2Sgf0neL3Zh)8JHAxM;qPX^}uKltr`iGl;^86{GPQIrcimHdAG8b*lt#Imu z3ICUavj|HTpxF}Q?O0ZfNy(*(!l5^B@?Q3NA%oxG1d=H>or~AE{So`>Cyq~=PaGj? zm;#SF3HM2`7L!x@p|ELcGBSdny)*H&0H3|Bu~<6GFQo9<9*cdr5KmQFI$|+Cn~23k zJbl;P^(H_+T+z&Wh>RPgZx!aRXHp`fIfEqmm zSSgEh+hjI-K`YJPZy9*K`>tN$w3>HrQwHee%wVYu;I){8+mr#iSo1*$nybLhnorfWlkU6k>$P^$-iu9DV6n|gw{mweOC&WrKfjm7aB@g+#W$02DYzLLZLlp(KpY@o~K34B6r)=wt66S`ua6qlh6 zg;@GG0NV^r(`9O}+<0x97}^A)`4<9?qJi>Q{Z*#=6e9ch6`i GOZ;C}EtXyY literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7517/__pycache__/base_key.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc7517/__pycache__/base_key.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5c7aa0d7d546e9dd7efc5dc5bd803ca3c8318899 GIT binary patch literal 5893 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7517/__pycache__/key_set.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc7517/__pycache__/key_set.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d72a437418dc52c8b69c8fe094f3f2f73f045cc4 GIT binary patch literal 2009 zcmZuy&ub%99Di?SlBU^h`opE0EQ=1SpaX8Y+Lo123kz%4)!mBist~ixPG(-(X_HKR zZ&GNOvOyL$l^`o9?ZJZwsV=>E5j=YE56HqE%77q<2XB#hSn9>^cP2@jc3);b^L;Nr51tBG%Mq=S;dN3$^)8>z&8Tl zs1=3LA!`T@ANHf~v(07Z*0ejTwouKYA%x0Vg)_m*u22p2z2y%U)lXPng@r1tOq)H0 zs2yeSm2}Pl>=2K7L@iFz4b+#!q$yWp`7I+M%1@2VU!%wega;9V1<(1q= zPT|hGhPf_sORU67c?L$9tZcGedV`fWa<}Y!PS`HHT!BT#3KKb_>aG^;{M4Ew*c30A zS7+b2It8k90d`h4{g|%XW!u&D+Gyxzx;HR{CX4{o$-%i~Lun2-;MaixvM}HvI(G)% z&YJ)a=|c&UM;o*u6(opm%p+?s9=7Xb4}|?*m)I2Cmus_2y>O~7#u)5V4UDX1o382< zV3eJXau6hw_75WjO@0C1fI{DZ9V^5mcgMD<1Ytk2Vp}Run{3P9(=X{)QgeKnJVy2m z8A3;en&M08D?VNKHw~mG$y-msp3&Q_*zG{w zK!zi*J;?AJ2s^;&<2m&xM$?lpnp?7q26dY!??HC<`x!#2*Is*0u7QhTzJr@2Tn=1M zYf|73#{)Ixgx|jGfjJ`X*C3(_X-%F3K2iKn~o@7cCE_ido#Rztr zMF*quIn|`vqXoNc1vE$QmkifjWg_UW*l@Geb=y)mjAE6g<8igyG65rTDx+Rg!>Hk9 zfq|nnoVitA&IF~&E(_OyVsUKNum#JgALGgIaPIK_R4sY43<^Q*$?66i#OmbBpvR9N zZS8UM0!;D=fRLNL?3^iphkAZfhi$cqE=P}zA*IFJ0Cmz%kcr8!Q*9y*htRloFgn(( z?#f?y4e#K5@=*+bZJCT+{40@crKX=GW}YTyTCtfRcZ(Wb&|+BH%0`Llx*yl|l4Dhi zD4*5!&#FeTJ2Rx~mSgHVM|y{ROQLiUVH6>_dw7XB<}d&(0m1^P_kRbMQY z_aQ1p7Ad%K5@T}Yr8XIacsw%OCZ{1Z0Cg{FvVXo?&(lzHN=`WqwLkc02yRJe;h@!r pvANLod437bK$eP|0BxC4dO*^x!KWQfQ842){DWivK4&7Z?|;?<YV(2>q zNr;T)n^(;HxK7zZHqmC@bh1r)XO^;ZVs?6d;of5AL006f$jnljT25H4P$Hd8Xr&5K z%@y4Wr<18nm!Wn&Ucj=3%d%Ro)=ZIYM@i2mPezF(? zgy52Dn3%|U=XpD<(zMhHBz#RdC9eu#wBx%oR;7jIUMQwJjmuCk)s*G2YTb&u zsjNORq~D(L5dcP#VVWq`=$6wg7aFKbn&@()Tbk%m<8RVLQ;pN4iNr>?w0tZBACwCL Vo{6`R3(-K3Z6OCXdHS>8`x77(Yb^i( literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7518/__pycache__/ec_key.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc7518/__pycache__/ec_key.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..88feed75be375f4599b0c79ab0b7520c32029dbb GIT binary patch literal 5595 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 H(Tn~sD0i`b$y{u&y$MC{R8e=Ut$BaUdD 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 R?d6F=7wCcQc|&b2}3cD>#m+Z#(- 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 S@BS;ze(m)B^M44j4gD9@XaYw7 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7518/__pycache__/rsa_key.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc7518/__pycache__/rsa_key.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9cdbf6ca495523066a07c220f862f3000ac97bb9 GIT binary patch literal 6690 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 X!lzFu=6OB-9nQyuz#DD>)Gq!De6PGX literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7518/__pycache__/util.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc7518/__pycache__/util.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5376d4e39938e7d06893d444caca9f95aa9cd601 GIT binary patch literal 841 zcmZWn&1(}u6rb7Me3+2NRq7XrbwOeZZM4BEk_w8nQX~gIpp=EMyE92PCY!LkDKTte z4_1P&F)Vi7C1$5PFQ3X#uNyV_eY^VZm7;yH2Q(0P4qrtO(EB7GcmQ3ZkzVecr~2SvE@E;>mseD3+#J02coB|j^9 zFGlH{pUxc%Ir9oI@_g7kd?=IEena7U*!VPAYPCtXNuQbQ*Jcx~b$}_4F&?9=8-CNc SfUiwa1Pd77pQ8UE?E4q6V!Xcq literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7518/ec_key.py b/.venv/Lib/site-packages/authlib/jose/rfc7518/ec_key.py new file mode 100644 index 00000000..05f0c044 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc7518/ec_key.py @@ -0,0 +1,101 @@ +from cryptography.hazmat.primitives.asymmetric import ec +from cryptography.hazmat.primitives.asymmetric.ec import ( + EllipticCurvePublicKey, EllipticCurvePrivateKeyWithSerialization, + EllipticCurvePrivateNumbers, EllipticCurvePublicNumbers, + SECP256R1, SECP384R1, SECP521R1, SECP256K1, +) +from cryptography.hazmat.backends import default_backend +from authlib.common.encoding import base64_to_int, int_to_base64 +from ..rfc7517 import AsymmetricKey + + +class ECKey(AsymmetricKey): + """Key class of the ``EC`` key type.""" + + kty = 'EC' + DSS_CURVES = { + 'P-256': SECP256R1, + 'P-384': SECP384R1, + 'P-521': SECP521R1, + # https://tools.ietf.org/html/rfc8812#section-3.1 + 'secp256k1': SECP256K1, + } + CURVES_DSS = { + SECP256R1.name: 'P-256', + SECP384R1.name: 'P-384', + SECP521R1.name: 'P-521', + SECP256K1.name: 'secp256k1', + } + REQUIRED_JSON_FIELDS = ['crv', 'x', 'y'] + + PUBLIC_KEY_FIELDS = REQUIRED_JSON_FIELDS + PRIVATE_KEY_FIELDS = ['crv', 'd', 'x', 'y'] + + PUBLIC_KEY_CLS = EllipticCurvePublicKey + PRIVATE_KEY_CLS = EllipticCurvePrivateKeyWithSerialization + SSH_PUBLIC_PREFIX = b'ecdsa-sha2-' + + def exchange_shared_key(self, pubkey): + # # used in ECDHESAlgorithm + private_key = self.get_private_key() + if private_key: + return private_key.exchange(ec.ECDH(), pubkey) + raise ValueError('Invalid key for exchanging shared key') + + @property + def curve_key_size(self): + raw_key = self.get_private_key() + if not raw_key: + raw_key = self.public_key + return raw_key.curve.key_size + + def load_private_key(self): + curve = self.DSS_CURVES[self._dict_data['crv']]() + public_numbers = EllipticCurvePublicNumbers( + base64_to_int(self._dict_data['x']), + base64_to_int(self._dict_data['y']), + curve, + ) + private_numbers = EllipticCurvePrivateNumbers( + base64_to_int(self.tokens['d']), + public_numbers + ) + return private_numbers.private_key(default_backend()) + + def load_public_key(self): + curve = self.DSS_CURVES[self._dict_data['crv']]() + public_numbers = EllipticCurvePublicNumbers( + base64_to_int(self._dict_data['x']), + base64_to_int(self._dict_data['y']), + curve, + ) + return public_numbers.public_key(default_backend()) + + def dumps_private_key(self): + numbers = self.private_key.private_numbers() + return { + 'crv': self.CURVES_DSS[self.private_key.curve.name], + 'x': int_to_base64(numbers.public_numbers.x), + 'y': int_to_base64(numbers.public_numbers.y), + 'd': int_to_base64(numbers.private_value), + } + + def dumps_public_key(self): + numbers = self.public_key.public_numbers() + return { + 'crv': self.CURVES_DSS[numbers.curve.name], + 'x': int_to_base64(numbers.x), + 'y': int_to_base64(numbers.y) + } + + @classmethod + def generate_key(cls, crv='P-256', options=None, is_private=False) -> 'ECKey': + if crv not in cls.DSS_CURVES: + raise ValueError(f'Invalid crv value: "{crv}"') + raw_key = ec.generate_private_key( + curve=cls.DSS_CURVES[crv](), + backend=default_backend(), + ) + if not is_private: + raw_key = raw_key.public_key() + return cls.import_key(raw_key, options=options) diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7518/jwe_algs.py b/.venv/Lib/site-packages/authlib/jose/rfc7518/jwe_algs.py new file mode 100644 index 00000000..b57654a9 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc7518/jwe_algs.py @@ -0,0 +1,349 @@ +import os +import struct +from cryptography.hazmat.primitives.asymmetric import padding +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives.keywrap import ( + aes_key_wrap, + aes_key_unwrap +) +from cryptography.hazmat.primitives.ciphers import Cipher +from cryptography.hazmat.primitives.ciphers.algorithms import AES +from cryptography.hazmat.primitives.ciphers.modes import GCM +from cryptography.hazmat.primitives.kdf.concatkdf import ConcatKDFHash +from authlib.common.encoding import ( + to_bytes, to_native, + urlsafe_b64decode, + urlsafe_b64encode +) +from authlib.jose.rfc7516 import JWEAlgorithm +from .rsa_key import RSAKey +from .ec_key import ECKey +from .oct_key import OctKey + + +class DirectAlgorithm(JWEAlgorithm): + name = 'dir' + description = 'Direct use of a shared symmetric key' + + def prepare_key(self, raw_data): + return OctKey.import_key(raw_data) + + def generate_preset(self, enc_alg, key): + return {} + + def wrap(self, enc_alg, headers, key, preset=None): + cek = key.get_op_key('encrypt') + if len(cek) * 8 != enc_alg.CEK_SIZE: + raise ValueError('Invalid "cek" length') + return {'ek': b'', 'cek': cek} + + def unwrap(self, enc_alg, ek, headers, key): + cek = key.get_op_key('decrypt') + if len(cek) * 8 != enc_alg.CEK_SIZE: + raise ValueError('Invalid "cek" length') + return cek + + +class RSAAlgorithm(JWEAlgorithm): + #: A key of size 2048 bits or larger MUST be used with these algorithms + #: RSA1_5, RSA-OAEP, RSA-OAEP-256 + key_size = 2048 + + def __init__(self, name, description, pad_fn): + self.name = name + self.description = description + self.padding = pad_fn + + def prepare_key(self, raw_data): + return RSAKey.import_key(raw_data) + + def generate_preset(self, enc_alg, key): + cek = enc_alg.generate_cek() + return {'cek': cek} + + def wrap(self, enc_alg, headers, key, preset=None): + if preset and 'cek' in preset: + cek = preset['cek'] + else: + cek = enc_alg.generate_cek() + + op_key = key.get_op_key('wrapKey') + if op_key.key_size < self.key_size: + raise ValueError('A key of size 2048 bits or larger MUST be used') + ek = op_key.encrypt(cek, self.padding) + return {'ek': ek, 'cek': cek} + + def unwrap(self, enc_alg, ek, headers, key): + # it will raise ValueError if failed + op_key = key.get_op_key('unwrapKey') + cek = op_key.decrypt(ek, self.padding) + if len(cek) * 8 != enc_alg.CEK_SIZE: + raise ValueError('Invalid "cek" length') + return cek + + +class AESAlgorithm(JWEAlgorithm): + def __init__(self, key_size): + self.name = f'A{key_size}KW' + self.description = f'AES Key Wrap using {key_size}-bit key' + self.key_size = key_size + + def prepare_key(self, raw_data): + return OctKey.import_key(raw_data) + + def generate_preset(self, enc_alg, key): + cek = enc_alg.generate_cek() + return {'cek': cek} + + def _check_key(self, key): + if len(key) * 8 != self.key_size: + raise ValueError( + f'A key of size {self.key_size} bits is required.') + + def wrap_cek(self, cek, key): + op_key = key.get_op_key('wrapKey') + self._check_key(op_key) + ek = aes_key_wrap(op_key, cek, default_backend()) + return {'ek': ek, 'cek': cek} + + def wrap(self, enc_alg, headers, key, preset=None): + if preset and 'cek' in preset: + cek = preset['cek'] + else: + cek = enc_alg.generate_cek() + return self.wrap_cek(cek, key) + + def unwrap(self, enc_alg, ek, headers, key): + op_key = key.get_op_key('unwrapKey') + self._check_key(op_key) + cek = aes_key_unwrap(op_key, ek, default_backend()) + if len(cek) * 8 != enc_alg.CEK_SIZE: + raise ValueError('Invalid "cek" length') + return cek + + +class AESGCMAlgorithm(JWEAlgorithm): + EXTRA_HEADERS = frozenset(['iv', 'tag']) + + def __init__(self, key_size): + self.name = f'A{key_size}GCMKW' + self.description = f'Key wrapping with AES GCM using {key_size}-bit key' + self.key_size = key_size + + def prepare_key(self, raw_data): + return OctKey.import_key(raw_data) + + def generate_preset(self, enc_alg, key): + cek = enc_alg.generate_cek() + return {'cek': cek} + + def _check_key(self, key): + if len(key) * 8 != self.key_size: + raise ValueError( + f'A key of size {self.key_size} bits is required.') + + def wrap(self, enc_alg, headers, key, preset=None): + if preset and 'cek' in preset: + cek = preset['cek'] + else: + cek = enc_alg.generate_cek() + + op_key = key.get_op_key('wrapKey') + self._check_key(op_key) + + #: https://tools.ietf.org/html/rfc7518#section-4.7.1.1 + #: The "iv" (initialization vector) Header Parameter value is the + #: base64url-encoded representation of the 96-bit IV value + iv_size = 96 + iv = os.urandom(iv_size // 8) + + cipher = Cipher(AES(op_key), GCM(iv), backend=default_backend()) + enc = cipher.encryptor() + ek = enc.update(cek) + enc.finalize() + + h = { + 'iv': to_native(urlsafe_b64encode(iv)), + 'tag': to_native(urlsafe_b64encode(enc.tag)) + } + return {'ek': ek, 'cek': cek, 'header': h} + + def unwrap(self, enc_alg, ek, headers, key): + op_key = key.get_op_key('unwrapKey') + self._check_key(op_key) + + iv = headers.get('iv') + if not iv: + raise ValueError('Missing "iv" in headers') + + tag = headers.get('tag') + if not tag: + raise ValueError('Missing "tag" in headers') + + iv = urlsafe_b64decode(to_bytes(iv)) + tag = urlsafe_b64decode(to_bytes(tag)) + + cipher = Cipher(AES(op_key), GCM(iv, tag), backend=default_backend()) + d = cipher.decryptor() + cek = d.update(ek) + d.finalize() + if len(cek) * 8 != enc_alg.CEK_SIZE: + raise ValueError('Invalid "cek" length') + return cek + + +class ECDHESAlgorithm(JWEAlgorithm): + EXTRA_HEADERS = ['epk', 'apu', 'apv'] + ALLOWED_KEY_CLS = ECKey + + # https://tools.ietf.org/html/rfc7518#section-4.6 + def __init__(self, key_size=None): + if key_size is None: + self.name = 'ECDH-ES' + self.description = 'ECDH-ES in the Direct Key Agreement mode' + else: + self.name = f'ECDH-ES+A{key_size}KW' + self.description = ( + 'ECDH-ES using Concat KDF and CEK wrapped ' + 'with A{}KW').format(key_size) + self.key_size = key_size + self.aeskw = AESAlgorithm(key_size) + + def prepare_key(self, raw_data): + if isinstance(raw_data, self.ALLOWED_KEY_CLS): + return raw_data + return ECKey.import_key(raw_data) + + def generate_preset(self, enc_alg, key): + epk = self._generate_ephemeral_key(key) + h = self._prepare_headers(epk) + preset = {'epk': epk, 'header': h} + if self.key_size is not None: + cek = enc_alg.generate_cek() + preset['cek'] = cek + return preset + + def compute_fixed_info(self, headers, bit_size): + # AlgorithmID + if self.key_size is None: + alg_id = u32be_len_input(headers['enc']) + else: + alg_id = u32be_len_input(headers['alg']) + + # PartyUInfo + apu_info = u32be_len_input(headers.get('apu'), True) + + # PartyVInfo + apv_info = u32be_len_input(headers.get('apv'), True) + + # SuppPubInfo + pub_info = struct.pack('>I', bit_size) + + return alg_id + apu_info + apv_info + pub_info + + def compute_derived_key(self, shared_key, fixed_info, bit_size): + ckdf = ConcatKDFHash( + algorithm=hashes.SHA256(), + length=bit_size // 8, + otherinfo=fixed_info, + backend=default_backend() + ) + return ckdf.derive(shared_key) + + def deliver(self, key, pubkey, headers, bit_size): + shared_key = key.exchange_shared_key(pubkey) + fixed_info = self.compute_fixed_info(headers, bit_size) + return self.compute_derived_key(shared_key, fixed_info, bit_size) + + def _generate_ephemeral_key(self, key): + return key.generate_key(key['crv'], is_private=True) + + def _prepare_headers(self, epk): + # REQUIRED_JSON_FIELDS contains only public fields + pub_epk = {k: epk[k] for k in epk.REQUIRED_JSON_FIELDS} + pub_epk['kty'] = epk.kty + return {'epk': pub_epk} + + def wrap(self, enc_alg, headers, key, preset=None): + if self.key_size is None: + bit_size = enc_alg.CEK_SIZE + else: + bit_size = self.key_size + + if preset and 'epk' in preset: + epk = preset['epk'] + h = {} + else: + epk = self._generate_ephemeral_key(key) + h = self._prepare_headers(epk) + + public_key = key.get_op_key('wrapKey') + dk = self.deliver(epk, public_key, headers, bit_size) + + if self.key_size is None: + return {'ek': b'', 'cek': dk, 'header': h} + + if preset and 'cek' in preset: + preset_for_kw = {'cek': preset['cek']} + else: + preset_for_kw = None + + kek = self.aeskw.prepare_key(dk) + rv = self.aeskw.wrap(enc_alg, headers, kek, preset_for_kw) + rv['header'] = h + return rv + + def unwrap(self, enc_alg, ek, headers, key): + if 'epk' not in headers: + raise ValueError('Missing "epk" in headers') + + if self.key_size is None: + bit_size = enc_alg.CEK_SIZE + else: + bit_size = self.key_size + + epk = key.import_key(headers['epk']) + public_key = epk.get_op_key('wrapKey') + dk = self.deliver(key, public_key, headers, bit_size) + + if self.key_size is None: + return dk + + kek = self.aeskw.prepare_key(dk) + return self.aeskw.unwrap(enc_alg, ek, headers, kek) + + +def u32be_len_input(s, base64=False): + if not s: + return b'\x00\x00\x00\x00' + if base64: + s = urlsafe_b64decode(to_bytes(s)) + else: + s = to_bytes(s) + return struct.pack('>I', len(s)) + s + + +JWE_ALG_ALGORITHMS = [ + DirectAlgorithm(), # dir + RSAAlgorithm('RSA1_5', 'RSAES-PKCS1-v1_5', padding.PKCS1v15()), + RSAAlgorithm( + 'RSA-OAEP', 'RSAES OAEP using default parameters', + padding.OAEP(padding.MGF1(hashes.SHA1()), hashes.SHA1(), None)), + RSAAlgorithm( + 'RSA-OAEP-256', 'RSAES OAEP using SHA-256 and MGF1 with SHA-256', + padding.OAEP(padding.MGF1(hashes.SHA256()), hashes.SHA256(), None)), + + AESAlgorithm(128), # A128KW + AESAlgorithm(192), # A192KW + AESAlgorithm(256), # A256KW + AESGCMAlgorithm(128), # A128GCMKW + AESGCMAlgorithm(192), # A192GCMKW + AESGCMAlgorithm(256), # A256GCMKW + ECDHESAlgorithm(None), # ECDH-ES + ECDHESAlgorithm(128), # ECDH-ES+A128KW + ECDHESAlgorithm(192), # ECDH-ES+A192KW + ECDHESAlgorithm(256), # ECDH-ES+A256KW +] + +# 'PBES2-HS256+A128KW': '', +# 'PBES2-HS384+A192KW': '', +# 'PBES2-HS512+A256KW': '', diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7518/jwe_encs.py b/.venv/Lib/site-packages/authlib/jose/rfc7518/jwe_encs.py new file mode 100644 index 00000000..f951d101 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc7518/jwe_encs.py @@ -0,0 +1,144 @@ +""" + authlib.jose.rfc7518 + ~~~~~~~~~~~~~~~~~~~~ + + Cryptographic Algorithms for Cryptographic Algorithms for Content + Encryption per `Section 5`_. + + .. _`Section 5`: https://tools.ietf.org/html/rfc7518#section-5 +""" +import hmac +import hashlib +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives.ciphers import Cipher +from cryptography.hazmat.primitives.ciphers.algorithms import AES +from cryptography.hazmat.primitives.ciphers.modes import GCM, CBC +from cryptography.hazmat.primitives.padding import PKCS7 +from cryptography.exceptions import InvalidTag +from ..rfc7516 import JWEEncAlgorithm +from .util import encode_int + + +class CBCHS2EncAlgorithm(JWEEncAlgorithm): + # The IV used is a 128-bit value generated randomly or + # pseudo-randomly for use in the cipher. + IV_SIZE = 128 + + def __init__(self, key_size, hash_type): + self.name = f'A{key_size}CBC-HS{hash_type}' + tpl = 'AES_{}_CBC_HMAC_SHA_{} authenticated encryption algorithm' + self.description = tpl.format(key_size, hash_type) + + # bit length + self.key_size = key_size + # byte length + self.key_len = key_size // 8 + + self.CEK_SIZE = key_size * 2 + self.hash_alg = getattr(hashlib, f'sha{hash_type}') + + def _hmac(self, ciphertext, aad, iv, key): + al = encode_int(len(aad) * 8, 64) + msg = aad + iv + ciphertext + al + d = hmac.new(key, msg, self.hash_alg).digest() + return d[:self.key_len] + + def encrypt(self, msg, aad, iv, key): + """Key Encryption with AES_CBC_HMAC_SHA2. + + :param msg: text to be encrypt in bytes + :param aad: additional authenticated data in bytes + :param iv: initialization vector in bytes + :param key: encrypted key in bytes + :return: (ciphertext, iv, tag) + """ + self.check_iv(iv) + hkey = key[:self.key_len] + ekey = key[self.key_len:] + + pad = PKCS7(AES.block_size).padder() + padded_data = pad.update(msg) + pad.finalize() + + cipher = Cipher(AES(ekey), CBC(iv), backend=default_backend()) + enc = cipher.encryptor() + ciphertext = enc.update(padded_data) + enc.finalize() + tag = self._hmac(ciphertext, aad, iv, hkey) + return ciphertext, tag + + def decrypt(self, ciphertext, aad, iv, tag, key): + """Key Decryption with AES AES_CBC_HMAC_SHA2. + + :param ciphertext: ciphertext in bytes + :param aad: additional authenticated data in bytes + :param iv: initialization vector in bytes + :param tag: authentication tag in bytes + :param key: encrypted key in bytes + :return: message + """ + self.check_iv(iv) + hkey = key[:self.key_len] + dkey = key[self.key_len:] + + _tag = self._hmac(ciphertext, aad, iv, hkey) + if not hmac.compare_digest(_tag, tag): + raise InvalidTag() + + cipher = Cipher(AES(dkey), CBC(iv), backend=default_backend()) + d = cipher.decryptor() + data = d.update(ciphertext) + d.finalize() + unpad = PKCS7(AES.block_size).unpadder() + return unpad.update(data) + unpad.finalize() + + +class GCMEncAlgorithm(JWEEncAlgorithm): + # Use of an IV of size 96 bits is REQUIRED with this algorithm. + # https://tools.ietf.org/html/rfc7518#section-5.3 + IV_SIZE = 96 + + def __init__(self, key_size): + self.name = f'A{key_size}GCM' + self.description = f'AES GCM using {key_size}-bit key' + self.key_size = key_size + self.CEK_SIZE = key_size + + def encrypt(self, msg, aad, iv, key): + """Key Encryption with AES GCM + + :param msg: text to be encrypt in bytes + :param aad: additional authenticated data in bytes + :param iv: initialization vector in bytes + :param key: encrypted key in bytes + :return: (ciphertext, iv, tag) + """ + self.check_iv(iv) + cipher = Cipher(AES(key), GCM(iv), backend=default_backend()) + enc = cipher.encryptor() + enc.authenticate_additional_data(aad) + ciphertext = enc.update(msg) + enc.finalize() + return ciphertext, enc.tag + + def decrypt(self, ciphertext, aad, iv, tag, key): + """Key Decryption with AES GCM + + :param ciphertext: ciphertext in bytes + :param aad: additional authenticated data in bytes + :param iv: initialization vector in bytes + :param tag: authentication tag in bytes + :param key: encrypted key in bytes + :return: message + """ + self.check_iv(iv) + cipher = Cipher(AES(key), GCM(iv, tag), backend=default_backend()) + d = cipher.decryptor() + d.authenticate_additional_data(aad) + return d.update(ciphertext) + d.finalize() + + +JWE_ENC_ALGORITHMS = [ + CBCHS2EncAlgorithm(128, 256), # A128CBC-HS256 + CBCHS2EncAlgorithm(192, 384), # A192CBC-HS384 + CBCHS2EncAlgorithm(256, 512), # A256CBC-HS512 + GCMEncAlgorithm(128), # A128GCM + GCMEncAlgorithm(192), # A192GCM + GCMEncAlgorithm(256), # A256GCM +] diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7518/jwe_zips.py b/.venv/Lib/site-packages/authlib/jose/rfc7518/jwe_zips.py new file mode 100644 index 00000000..23968610 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc7518/jwe_zips.py @@ -0,0 +1,21 @@ +import zlib +from ..rfc7516 import JWEZipAlgorithm, JsonWebEncryption + + +class DeflateZipAlgorithm(JWEZipAlgorithm): + name = 'DEF' + description = 'DEFLATE' + + def compress(self, s): + """Compress bytes data with DEFLATE algorithm.""" + data = zlib.compress(s) + # drop gzip headers and tail + return data[2:-4] + + def decompress(self, s): + """Decompress DEFLATE bytes data.""" + return zlib.decompress(s, -zlib.MAX_WBITS) + + +def register_jwe_rfc7518(): + JsonWebEncryption.register_algorithm(DeflateZipAlgorithm()) diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7518/jws_algs.py b/.venv/Lib/site-packages/authlib/jose/rfc7518/jws_algs.py new file mode 100644 index 00000000..2c028403 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc7518/jws_algs.py @@ -0,0 +1,215 @@ +""" + authlib.jose.rfc7518 + ~~~~~~~~~~~~~~~~~~~~ + + "alg" (Algorithm) Header Parameter Values for JWS per `Section 3`_. + + .. _`Section 3`: https://tools.ietf.org/html/rfc7518#section-3 +""" + +import hmac +import hashlib +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric.utils import ( + decode_dss_signature, encode_dss_signature +) +from cryptography.hazmat.primitives.asymmetric.ec import ECDSA +from cryptography.hazmat.primitives.asymmetric import padding +from cryptography.exceptions import InvalidSignature +from ..rfc7515 import JWSAlgorithm +from .oct_key import OctKey +from .rsa_key import RSAKey +from .ec_key import ECKey +from .util import encode_int, decode_int + + +class NoneAlgorithm(JWSAlgorithm): + name = 'none' + description = 'No digital signature or MAC performed' + + def prepare_key(self, raw_data): + return None + + def sign(self, msg, key): + return b'' + + def verify(self, msg, sig, key): + return False + + +class HMACAlgorithm(JWSAlgorithm): + """HMAC using SHA algorithms for JWS. Available algorithms: + + - HS256: HMAC using SHA-256 + - HS384: HMAC using SHA-384 + - HS512: HMAC using SHA-512 + """ + SHA256 = hashlib.sha256 + SHA384 = hashlib.sha384 + SHA512 = hashlib.sha512 + + def __init__(self, sha_type): + self.name = f'HS{sha_type}' + self.description = f'HMAC using SHA-{sha_type}' + self.hash_alg = getattr(self, f'SHA{sha_type}') + + def prepare_key(self, raw_data): + return OctKey.import_key(raw_data) + + def sign(self, msg, key): + # it is faster than the one in cryptography + op_key = key.get_op_key('sign') + return hmac.new(op_key, msg, self.hash_alg).digest() + + def verify(self, msg, sig, key): + op_key = key.get_op_key('verify') + v_sig = hmac.new(op_key, msg, self.hash_alg).digest() + return hmac.compare_digest(sig, v_sig) + + +class RSAAlgorithm(JWSAlgorithm): + """RSA using SHA algorithms for JWS. Available algorithms: + + - RS256: RSASSA-PKCS1-v1_5 using SHA-256 + - RS384: RSASSA-PKCS1-v1_5 using SHA-384 + - RS512: RSASSA-PKCS1-v1_5 using SHA-512 + """ + SHA256 = hashes.SHA256 + SHA384 = hashes.SHA384 + SHA512 = hashes.SHA512 + + def __init__(self, sha_type): + self.name = f'RS{sha_type}' + self.description = f'RSASSA-PKCS1-v1_5 using SHA-{sha_type}' + self.hash_alg = getattr(self, f'SHA{sha_type}') + self.padding = padding.PKCS1v15() + + def prepare_key(self, raw_data): + return RSAKey.import_key(raw_data) + + def sign(self, msg, key): + op_key = key.get_op_key('sign') + return op_key.sign(msg, self.padding, self.hash_alg()) + + def verify(self, msg, sig, key): + op_key = key.get_op_key('verify') + try: + op_key.verify(sig, msg, self.padding, self.hash_alg()) + return True + except InvalidSignature: + return False + + +class ECAlgorithm(JWSAlgorithm): + """ECDSA using SHA algorithms for JWS. Available algorithms: + + - ES256: ECDSA using P-256 and SHA-256 + - ES384: ECDSA using P-384 and SHA-384 + - ES512: ECDSA using P-521 and SHA-512 + """ + SHA256 = hashes.SHA256 + SHA384 = hashes.SHA384 + SHA512 = hashes.SHA512 + + def __init__(self, name, curve, sha_type): + self.name = name + self.curve = curve + self.description = f'ECDSA using {self.curve} and SHA-{sha_type}' + self.hash_alg = getattr(self, f'SHA{sha_type}') + + def prepare_key(self, raw_data): + key = ECKey.import_key(raw_data) + if key['crv'] != self.curve: + raise ValueError(f'Key for "{self.name}" not supported, only "{self.curve}" allowed') + return key + + def sign(self, msg, key): + op_key = key.get_op_key('sign') + der_sig = op_key.sign(msg, ECDSA(self.hash_alg())) + r, s = decode_dss_signature(der_sig) + size = key.curve_key_size + return encode_int(r, size) + encode_int(s, size) + + def verify(self, msg, sig, key): + key_size = key.curve_key_size + length = (key_size + 7) // 8 + + if len(sig) != 2 * length: + return False + + r = decode_int(sig[:length]) + s = decode_int(sig[length:]) + der_sig = encode_dss_signature(r, s) + + try: + op_key = key.get_op_key('verify') + op_key.verify(der_sig, msg, ECDSA(self.hash_alg())) + return True + except InvalidSignature: + return False + + +class RSAPSSAlgorithm(JWSAlgorithm): + """RSASSA-PSS using SHA algorithms for JWS. Available algorithms: + + - PS256: RSASSA-PSS using SHA-256 and MGF1 with SHA-256 + - PS384: RSASSA-PSS using SHA-384 and MGF1 with SHA-384 + - PS512: RSASSA-PSS using SHA-512 and MGF1 with SHA-512 + """ + SHA256 = hashes.SHA256 + SHA384 = hashes.SHA384 + SHA512 = hashes.SHA512 + + def __init__(self, sha_type): + self.name = f'PS{sha_type}' + tpl = 'RSASSA-PSS using SHA-{} and MGF1 with SHA-{}' + self.description = tpl.format(sha_type, sha_type) + self.hash_alg = getattr(self, f'SHA{sha_type}') + + def prepare_key(self, raw_data): + return RSAKey.import_key(raw_data) + + def sign(self, msg, key): + op_key = key.get_op_key('sign') + return op_key.sign( + msg, + padding.PSS( + mgf=padding.MGF1(self.hash_alg()), + salt_length=self.hash_alg.digest_size + ), + self.hash_alg() + ) + + def verify(self, msg, sig, key): + op_key = key.get_op_key('verify') + try: + op_key.verify( + sig, + msg, + padding.PSS( + mgf=padding.MGF1(self.hash_alg()), + salt_length=self.hash_alg.digest_size + ), + self.hash_alg() + ) + return True + except InvalidSignature: + return False + + +JWS_ALGORITHMS = [ + NoneAlgorithm(), # none + HMACAlgorithm(256), # HS256 + HMACAlgorithm(384), # HS384 + HMACAlgorithm(512), # HS512 + RSAAlgorithm(256), # RS256 + RSAAlgorithm(384), # RS384 + RSAAlgorithm(512), # RS512 + ECAlgorithm('ES256', 'P-256', 256), + ECAlgorithm('ES384', 'P-384', 384), + ECAlgorithm('ES512', 'P-521', 512), + ECAlgorithm('ES256K', 'secp256k1', 256), # defined in RFC8812 + RSAPSSAlgorithm(256), # PS256 + RSAPSSAlgorithm(384), # PS384 + RSAPSSAlgorithm(512), # PS512 +] diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7518/oct_key.py b/.venv/Lib/site-packages/authlib/jose/rfc7518/oct_key.py new file mode 100644 index 00000000..1db321a7 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc7518/oct_key.py @@ -0,0 +1,80 @@ +from authlib.common.encoding import ( + to_bytes, to_unicode, + urlsafe_b64encode, urlsafe_b64decode, +) +from authlib.common.security import generate_token +from ..rfc7517 import Key + + +class OctKey(Key): + """Key class of the ``oct`` key type.""" + + kty = 'oct' + REQUIRED_JSON_FIELDS = ['k'] + + def __init__(self, raw_key=None, options=None): + super().__init__(options) + self.raw_key = raw_key + + @property + def public_only(self): + return False + + def get_op_key(self, operation): + """Get the raw key for the given key_op. This method will also + check if the given key_op is supported by this key. + + :param operation: key operation value, such as "sign", "encrypt". + :return: raw key + """ + self.check_key_op(operation) + if not self.raw_key: + self.load_raw_key() + return self.raw_key + + def load_raw_key(self): + self.raw_key = urlsafe_b64decode(to_bytes(self.tokens['k'])) + + def load_dict_key(self): + k = to_unicode(urlsafe_b64encode(self.raw_key)) + self._dict_data = {'kty': self.kty, 'k': k} + + def as_dict(self, is_private=False, **params): + tokens = self.tokens + if 'kid' not in tokens: + tokens['kid'] = self.thumbprint() + + tokens.update(params) + return tokens + + @classmethod + def validate_raw_key(cls, key): + return isinstance(key, bytes) + + @classmethod + def import_key(cls, raw, options=None): + """Import a key from bytes, string, or dict data.""" + if isinstance(raw, cls): + if options is not None: + raw.options.update(options) + return raw + + if isinstance(raw, dict): + cls.check_required_fields(raw) + key = cls(options=options) + key._dict_data = raw + else: + raw_key = to_bytes(raw) + key = cls(raw_key=raw_key, options=options) + return key + + @classmethod + def generate_key(cls, key_size=256, options=None, is_private=True): + """Generate a ``OctKey`` with the given bit size.""" + if not is_private: + raise ValueError('oct key can not be generated as public') + + if key_size % 8 != 0: + raise ValueError('Invalid bit size for oct key') + + return cls.import_key(generate_token(key_size // 8), options) diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7518/rsa_key.py b/.venv/Lib/site-packages/authlib/jose/rfc7518/rsa_key.py new file mode 100644 index 00000000..53bd9958 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc7518/rsa_key.py @@ -0,0 +1,123 @@ +from cryptography.hazmat.primitives.asymmetric import rsa +from cryptography.hazmat.primitives.asymmetric.rsa import ( + RSAPublicKey, RSAPrivateKeyWithSerialization, + RSAPrivateNumbers, RSAPublicNumbers, + rsa_recover_prime_factors, rsa_crt_dmp1, rsa_crt_dmq1, rsa_crt_iqmp +) +from cryptography.hazmat.backends import default_backend +from authlib.common.encoding import base64_to_int, int_to_base64 +from ..rfc7517 import AsymmetricKey + + +class RSAKey(AsymmetricKey): + """Key class of the ``RSA`` key type.""" + + kty = 'RSA' + PUBLIC_KEY_CLS = RSAPublicKey + PRIVATE_KEY_CLS = RSAPrivateKeyWithSerialization + + PUBLIC_KEY_FIELDS = ['e', 'n'] + PRIVATE_KEY_FIELDS = ['d', 'dp', 'dq', 'e', 'n', 'p', 'q', 'qi'] + REQUIRED_JSON_FIELDS = ['e', 'n'] + SSH_PUBLIC_PREFIX = b'ssh-rsa' + + def dumps_private_key(self): + numbers = self.private_key.private_numbers() + return { + 'n': int_to_base64(numbers.public_numbers.n), + 'e': int_to_base64(numbers.public_numbers.e), + 'd': int_to_base64(numbers.d), + 'p': int_to_base64(numbers.p), + 'q': int_to_base64(numbers.q), + 'dp': int_to_base64(numbers.dmp1), + 'dq': int_to_base64(numbers.dmq1), + 'qi': int_to_base64(numbers.iqmp) + } + + def dumps_public_key(self): + numbers = self.public_key.public_numbers() + return { + 'n': int_to_base64(numbers.n), + 'e': int_to_base64(numbers.e) + } + + def load_private_key(self): + obj = self._dict_data + + if 'oth' in obj: # pragma: no cover + # https://tools.ietf.org/html/rfc7518#section-6.3.2.7 + raise ValueError('"oth" is not supported yet') + + public_numbers = RSAPublicNumbers( + base64_to_int(obj['e']), base64_to_int(obj['n'])) + + if has_all_prime_factors(obj): + numbers = RSAPrivateNumbers( + d=base64_to_int(obj['d']), + p=base64_to_int(obj['p']), + q=base64_to_int(obj['q']), + dmp1=base64_to_int(obj['dp']), + dmq1=base64_to_int(obj['dq']), + iqmp=base64_to_int(obj['qi']), + public_numbers=public_numbers) + else: + d = base64_to_int(obj['d']) + p, q = rsa_recover_prime_factors( + public_numbers.n, d, public_numbers.e) + numbers = RSAPrivateNumbers( + d=d, + p=p, + q=q, + dmp1=rsa_crt_dmp1(d, p), + dmq1=rsa_crt_dmq1(d, q), + iqmp=rsa_crt_iqmp(p, q), + public_numbers=public_numbers) + + return numbers.private_key(default_backend()) + + def load_public_key(self): + numbers = RSAPublicNumbers( + base64_to_int(self._dict_data['e']), + base64_to_int(self._dict_data['n']) + ) + return numbers.public_key(default_backend()) + + @classmethod + def generate_key(cls, key_size=2048, options=None, is_private=False) -> 'RSAKey': + if key_size < 512: + raise ValueError('key_size must not be less than 512') + if key_size % 8 != 0: + raise ValueError('Invalid key_size for RSAKey') + raw_key = rsa.generate_private_key( + public_exponent=65537, + key_size=key_size, + backend=default_backend(), + ) + if not is_private: + raw_key = raw_key.public_key() + return cls.import_key(raw_key, options=options) + + @classmethod + def import_dict_key(cls, raw, options=None): + cls.check_required_fields(raw) + key = cls(options=options) + key._dict_data = raw + if 'd' in raw and not has_all_prime_factors(raw): + # reload dict key + key.load_raw_key() + key.load_dict_key() + return key + + +def has_all_prime_factors(obj): + props = ['p', 'q', 'dp', 'dq', 'qi'] + props_found = [prop in obj for prop in props] + if all(props_found): + return True + + if any(props_found): + raise ValueError( + 'RSA key must include all parameters ' + 'if any are present besides d') + + return False diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7518/util.py b/.venv/Lib/site-packages/authlib/jose/rfc7518/util.py new file mode 100644 index 00000000..d2d13ec1 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc7518/util.py @@ -0,0 +1,12 @@ +import binascii + + +def encode_int(num, bits): + length = ((bits + 7) // 8) * 2 + padded_hex = '%0*x' % (length, num) + big_endian = binascii.a2b_hex(padded_hex.encode('ascii')) + return big_endian + + +def decode_int(b): + return int(binascii.b2a_hex(b), 16) diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7519/__init__.py b/.venv/Lib/site-packages/authlib/jose/rfc7519/__init__.py new file mode 100644 index 00000000..5eea5b7f --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc7519/__init__.py @@ -0,0 +1,15 @@ +""" + authlib.jose.rfc7519 + ~~~~~~~~~~~~~~~~~~~~ + + This module represents a direct implementation of + JSON Web Token (JWT). + + https://tools.ietf.org/html/rfc7519 +""" + +from .jwt import JsonWebToken +from .claims import BaseClaims, JWTClaims + + +__all__ = ['JsonWebToken', 'BaseClaims', 'JWTClaims'] diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7519/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc7519/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1aff8b86f651ee2be6ab4c8f6ccd942a77393057 GIT binary patch literal 583 zcmZutF;Cnu6tnEVQn?B#ie%;DcXtLmj%-6khl+o} z&Vo90?EknCW$nav5*uCW5IOwY{R0Dx(BI}`1@D2}#g1Ge zhEl{Z^8}V&>fwg_!k0lB$WGe9Xo^^Hh0`wU9HOZE<9A3L@>4q#d>kJu1F@bITZ6an z+rrOh5Vn=kj2j{qI~71QR2mGF){vYquA#7m%SwQB|8mP!Nz|mB8Xg|(lOq_Dkvf5r zycr&iqIfAdv$itZNn(`}Cgxx#vC`9IW~E40Pr7yHQH1M_p;4uiX;mVx4tH_`pG3~3 zsb4tFC5?RTyM7%sspHaq)T?`xGF4Do`^VpHTd%uCJNekxH0452`U~B;F?64O-p&fe zcsb3!smbU|UYwZhtFtG^;G7pw7LdhfP@ZLbe4H6>VY6~g`4mj{u-v3s?#f9*DKELD zG_KC?*FG%w_)+)WWsOC%=hDK*7%#jv94t_iULyQ@j$S>D8x+l-i$xc$zng~x7Z<(e I=yfOfA2wL26#xJL literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7519/__pycache__/claims.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc7519/__pycache__/claims.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..26539704aaf8ce54e83b570a119bd686ed0b2719 GIT binary patch literal 12107 zcmc&)+ix3JdY|D>BYLd=EFk;4|fDbP{gD# zL3dYDOt~gpDffgs<(crLyc1qga0xF9iu*l5@uikO6 zd%{FO5w8eQ|DUPDSkzN(zo_ZDmYzA6l(p0dV;NR$A5G88NlkGUjoip;OjX7+b85Q2 zRjnvtQo(N)O%Gqh>#y)tsxToc!h}l^C)_i_gh%lgg=rDr5t#5Q9#G~}K=(wG;sZ2k zEebcpi6H0=RD(a0b(K@3%lm-*b$KzFkrgRHbnDV|hDopde7s*;nAH-qQX-Si$y!>M zWQl)@oKqz&om1JgoKR!IpoD8ED>FGIWer3_Qf^kYUL-|J(#LRb@qGMpNT? zrbjcFX>te@Aqc0H$UKbplssI?yBXk3rX zep@!CHx`rPJ1oJF-Iitw6P3YAX-X`u<_7hwn$XRH0dO%b9qvpWI2At`o6V(?y`yPG zo7a@QoHUm7vic5YKBsf6V+l){kQ9;-(*MH(z^}zSLQcekd3}!im)480=BTj?g@X7w z%D=ShM4{j+2yvIyqTtSont&1-gmxu6yb{Sg*X=VR=s*YtFo#;9@o-ZE*`J? z3?ZsEnfzV#8A1^CRXw_zoUS&R(#cwZjqM>20;mS!aR|Py$K$#W@3iF7&2J~p4^1XA z3bfhe)y(wx1vxRNPhM72YHCVls-95O33W0yucqfGU(=>0buFh3WYI{TQT0hVpPNl; zQ-jwtx;n_F6K77JdUnvzF0t$)Yr!x}k(v^USs!r%75ei4k8TS0{jKje-DuJK4PilKWaF^VzRc8hFmAOi9-mQjaxTZTseDewitib= zUQ8=;dF18ME8`=VN6yF3y*500@k-T=E>SmY1FEWfPF<{eRWeIDQH*6~5vpjmF~{Re zopsA%ju?-}&`?hU+!Qul-ayy=$o_kgzKuxV-KYLJQi_}|M^3M|oPKmabZAp>2fAvY z5(=*<<<9=~5dA9q4&1r%(Tz3ths(E@*V~RX{3_vn#aAEU+H3+6+;s^Z*b=-~Xyztf=%d}or0oG){{k%ON zC=Ei(&d`d_i!79LD2GPTeiv=F$Jf|W59OL{61MQjyW*`068WfWtQxQlN7Q3TZ#OzJ zT1iG99d#MYEY9h~v)1Bv$89}pBOrN)pL7I{-I@N_)rcgPVdkFvvl1 zxDtxoDy$CQ`sKY)&qk(X5`r@LLDWp}}~ zJ?=){SoRb=tfSyAc;>i9_)Z?#39qZ(P%L{3UKRmf?=JXmC!FpEoW6pO9dHQ+UqL9i z>ouL;{&?P|+2dU48LN81HhHz`<2SwPx3~yOhg%rVqntgP4E79i-ixQ@6nYt^iuGcd zt1ZS0u`3X^I^T45lz5N?1xkx9LveM~c-z3r`z}e_vbCed3xw?}0F$HdwIAMSKfKmg zY9A=K4-|csPzM+@5UI3;i!VKB+k40Vk$<(j)OMuYcBJU7>^pR4>7%8!^k@uKvv@O)IXIQy+RCRYL8>0RMC-&#`DTc}m1|u$#enJe5)MNqTOH$KQeXXVx^u z<4PtGkMj@WZVEeuvDsk)eFO#os;#ESlu(n&csweyFiLfr;TJh$GCwsXKsH?e2LL!U z*59V9+w0#H2s|z9Kd|oU*z|b3z0jFEfEJ$@{9=PPpBD<&25oI#thf!1c)ejL=f?m( zDV(|l2(vHC(Rp|QMYRxf1_AVM5oRha2rNZ}niN=id0^?|L2#4e=RsxwFrWkhgGw`C zvjWE^+FA`D?mNfrO|+@%Mp#sJBNnN;<-AgLt2eS$cY10X6>_fXMkFxCh>!$VpeAjk zKIr{n5LKk~*UXCgTfGks?^?Vm;m+<~DsUVSf&wS&{QO*@C% z@K}7lT5au##IIgi^RXQ+#CNtOw%l^q0aWP3 zvOl`+k3MMLQ+)1zxZ~H#ZSBLk+jFIGPdVIEJjYw^-|+7*`45!+2iE-uD%5wkC9A!w z^CkbWvj5n+|CrtL`;^+_Zu*41UALdV7df&KIZ}!oD@Trz7Ki=$Pn^WV&U&KJZ4;3igr;)K5zOm2 z5?4HTBb@+Wr!LK?X_d*z!>Q>sg%%mv0u#B6Ley10)+Nh(=NAdNSGY!ZTR zZC;ghgoYTy%-7MQEM4Jcm)O{&aJ#kf|a4RPXHinY!L#j_xwE@{+_kdHqU}>@%ziK<)5v!q`a4O z0+52}-7aR`LYjSzsZuG8X|5~xC@EQpc}A%uGgV4c4w05qN2rc$N!rXMk!Z_PnS72= zOD0Mak2Qd?vKOyj8JAQI&6qTWrU_)Uz*!l**ejUKB={itw1#{YQ9xK};nf>F*GjJj z|4K;a0?kY^Gv(+~Tix*=$Do|UZMt}tkrI1E)c+xeQiwXnUIApU631cj1(Q2p#N)Qy ziCJHuwkCImzYllX9?1t7=~v#}1fq>vhg|MmhLuP%F(YiHRFSwtuLdhg7FO@xv9+h( zrt;7gf$NOO`?*LXI{l>ryuexzkaPGZ_1*{z)VKV=n{FtX5kK(e9DYU7i;WBKd;Ws^ ze1m6EPazT|4&S12HjzFf9qyCcVE~AwdtkXC_kbE@Dt8ck1~r>SgB&S!sBsb-l4Q+D z0F%(tPDfgS1Y&mp@;V}8M4MCi`L98XKF#qEG{_h$JNg+my~=1H&*?j~mOzWXzL+U}07zLY(F)i&QVB zhwqOVMAGzd73EMzOeN*2Dnzo;$~0@-LK&MY#y~aI0Hw*8yhvJ=n=zZBMti3BODawJ zPG-%RLwo2N9;$QjHQ!qayg2*@DNVVC4AvC;N8iuj+LVDI zZA^UU4ATnpK$ae#Z;@d%hdtT7SFl?Peg=wej2!{wxt1*nQ%VCr>;j;DjTuBUZ~35~ z#P?nE!iTO~P1th~*d4{rfrza3@` zS);S{W?2vA=>1|kF!!B4KBTMN#Z8O?mS*QEQ@+p;RiSrcp z^M1gwTSfQ`7-$Syth1Im#!!SVPSeUY2cry)8K|?D@ysYA#;9vUl>RdmZL1!z1iwSw z!?yvT9l}COJ93m~i)Sn0&XxS_CyVFqN1}IoOOaSP5+kV|yx)2JuD8?~D|g1$+hVk7 zmRNo1!{kP&cRkdL%2H>v+!p|nN*Y-~S34(og`8_|!E!)L)YV_&!#<+BW- zBh$N8=%`(T(49lkwnB%={3D^8B*1qL9ae?gD0+Xm0$|&zpZ+h{Dd0E7BJ8wNit7&z zAsTFz2Rmu_k9y@BR>A^_M2H3t-W5sSDP_SW0})G|R7eZ5BXFVg6}jZ&HIF_ar^!g= zbt9vo(Ag*GXv1#c_@l$GJjCB51My3%O82LO6 zx^3P}&ixBDPXfSt?D_H5qayu$)9u<9{#pR|h5$0I?cr^03FS_#iv)%X%@53|j#&Dh z&VxxO$XOaaZ|Qndtx=lD%41nMR>r*qQ`grxkrv3#!?H%F0U6erwBh5(QcA{gF9v@I zGJ*st7Rqp^Y!(7?_)9!Vl~!kx+Ke`Z01q@x$x~WV%Pksxi3T0phUQ=k8XO=;B&B3X?#Vl&RUIylAQ!3z^}}@u_`$X#YJNx97l#J7oAqP_?Zb;miIV zbykLN?{{SQuushQ9-}RcPCKzd0>t>n_RUdxqFgt7kpP8;j2u9AjsOWWBT9Ij%*~In z75o&H5%@d&>%RfGY5!HaM%RrW?E!~rAGaQy@Ok@atJef=0eZ4Q=V33RG8?=k?xAWM zNcIyi!z-lT22zk3Zv_VFL~vb}z>5N|2}qIEpM5L{If%J+IgiLqH|$kf2L{}19L?ET zfU0*IM~`#RqN46h+j7T%z<=Oh?*zb!Kt#Fnr@f!%R}Yq&kCmH`t$U7fa-%`^0^y37 z=MH0Z?l5MYbgLbZ;(k3NKcniQGs(s-JzpO_8YMVt3-_)6dE=143v31zq!sml13)Y+ ziWQ;xCjY}(IMIde_8$b=UKK?w$@Xw%@7KKM8)yBb>t&aSW!oOE1i$7r-#F{XJ)(&7 K5?cZP)c*lD;l)z` literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7519/__pycache__/jwt.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc7519/__pycache__/jwt.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e7779351093bb68be8271a399e86811e5f4cf98b GIT binary patch literal 8599 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 rDBPOZ5H6HD literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7519/claims.py b/.venv/Lib/site-packages/authlib/jose/rfc7519/claims.py new file mode 100644 index 00000000..6a9877bc --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc7519/claims.py @@ -0,0 +1,227 @@ +import time +from authlib.jose.errors import ( + MissingClaimError, + InvalidClaimError, + ExpiredTokenError, + InvalidTokenError, +) + + +class BaseClaims(dict): + """Payload claims for JWT, which contains a validate interface. + + :param payload: the payload dict of JWT + :param header: the header dict of JWT + :param options: validate options + :param params: other params + + An example on ``options`` parameter, the format is inspired by + `OpenID Connect Claims`_:: + + { + "iss": { + "essential": True, + "values": ["https://example.com", "https://example.org"] + }, + "sub": { + "essential": True + "value": "248289761001" + }, + "jti": { + "validate": validate_jti + } + } + + .. _`OpenID Connect Claims`: + http://openid.net/specs/openid-connect-core-1_0.html#IndividualClaimsRequests + """ + REGISTERED_CLAIMS = [] + + def __init__(self, payload, header, options=None, params=None): + super().__init__(payload) + self.header = header + self.options = options or {} + self.params = params or {} + + def __getattr__(self, key): + try: + return object.__getattribute__(self, key) + except AttributeError as error: + if key in self.REGISTERED_CLAIMS: + return self.get(key) + raise error + + def _validate_essential_claims(self): + for k in self.options: + if self.options[k].get('essential'): + if k not in self: + raise MissingClaimError(k) + elif not self.get(k): + raise InvalidClaimError(k) + + def _validate_claim_value(self, claim_name): + option = self.options.get(claim_name) + if not option: + return + + value = self.get(claim_name) + option_value = option.get('value') + if option_value and value != option_value: + raise InvalidClaimError(claim_name) + + option_values = option.get('values') + if option_values and value not in option_values: + raise InvalidClaimError(claim_name) + + validate = option.get('validate') + if validate and not validate(self, value): + raise InvalidClaimError(claim_name) + + def get_registered_claims(self): + rv = {} + for k in self.REGISTERED_CLAIMS: + if k in self: + rv[k] = self[k] + return rv + + +class JWTClaims(BaseClaims): + REGISTERED_CLAIMS = ['iss', 'sub', 'aud', 'exp', 'nbf', 'iat', 'jti'] + + def validate(self, now=None, leeway=0): + """Validate everything in claims payload.""" + self._validate_essential_claims() + + if now is None: + now = int(time.time()) + + self.validate_iss() + self.validate_sub() + self.validate_aud() + self.validate_exp(now, leeway) + self.validate_nbf(now, leeway) + self.validate_iat(now, leeway) + self.validate_jti() + + # Validate custom claims + for key in self.options.keys(): + if key not in self.REGISTERED_CLAIMS: + self._validate_claim_value(key) + + def validate_iss(self): + """The "iss" (issuer) claim identifies the principal that issued the + JWT. The processing of this claim is generally application specific. + The "iss" value is a case-sensitive string containing a StringOrURI + value. Use of this claim is OPTIONAL. + """ + self._validate_claim_value('iss') + + def validate_sub(self): + """The "sub" (subject) claim identifies the principal that is the + subject of the JWT. The claims in a JWT are normally statements + about the subject. The subject value MUST either be scoped to be + locally unique in the context of the issuer or be globally unique. + The processing of this claim is generally application specific. The + "sub" value is a case-sensitive string containing a StringOrURI + value. Use of this claim is OPTIONAL. + """ + self._validate_claim_value('sub') + + def validate_aud(self): + """The "aud" (audience) claim identifies the recipients that the JWT is + intended for. Each principal intended to process the JWT MUST + identify itself with a value in the audience claim. If the principal + processing the claim does not identify itself with a value in the + "aud" claim when this claim is present, then the JWT MUST be + rejected. In the general case, the "aud" value is an array of case- + sensitive strings, each containing a StringOrURI value. In the + special case when the JWT has one audience, the "aud" value MAY be a + single case-sensitive string containing a StringOrURI value. The + interpretation of audience values is generally application specific. + Use of this claim is OPTIONAL. + """ + aud_option = self.options.get('aud') + aud = self.get('aud') + if not aud_option or not aud: + return + + aud_values = aud_option.get('values') + if not aud_values: + aud_value = aud_option.get('value') + if aud_value: + aud_values = [aud_value] + + if not aud_values: + return + + if isinstance(self['aud'], list): + aud_list = self['aud'] + else: + aud_list = [self['aud']] + + if not any([v in aud_list for v in aud_values]): + raise InvalidClaimError('aud') + + def validate_exp(self, now, leeway): + """The "exp" (expiration time) claim identifies the expiration time on + or after which the JWT MUST NOT be accepted for processing. The + processing of the "exp" claim requires that the current date/time + MUST be before the expiration date/time listed in the "exp" claim. + Implementers MAY provide for some small leeway, usually no more than + a few minutes, to account for clock skew. Its value MUST be a number + containing a NumericDate value. Use of this claim is OPTIONAL. + """ + if 'exp' in self: + exp = self['exp'] + if not _validate_numeric_time(exp): + raise InvalidClaimError('exp') + if exp < (now - leeway): + raise ExpiredTokenError() + + def validate_nbf(self, now, leeway): + """The "nbf" (not before) claim identifies the time before which the JWT + MUST NOT be accepted for processing. The processing of the "nbf" + claim requires that the current date/time MUST be after or equal to + the not-before date/time listed in the "nbf" claim. Implementers MAY + provide for some small leeway, usually no more than a few minutes, to + account for clock skew. Its value MUST be a number containing a + NumericDate value. Use of this claim is OPTIONAL. + """ + if 'nbf' in self: + nbf = self['nbf'] + if not _validate_numeric_time(nbf): + raise InvalidClaimError('nbf') + if nbf > (now + leeway): + raise InvalidTokenError() + + def validate_iat(self, now, leeway): + """The "iat" (issued at) claim identifies the time at which the JWT was + issued. This claim can be used to determine the age of the JWT. + Implementers MAY provide for some small leeway, usually no more + than a few minutes, to account for clock skew. Its value MUST be a + number containing a NumericDate value. Use of this claim is OPTIONAL. + """ + if 'iat' in self: + iat = self['iat'] + if not _validate_numeric_time(iat): + raise InvalidClaimError('iat') + if iat > (now + leeway): + raise InvalidTokenError( + description='The token is not valid as it was issued in the future' + ) + + def validate_jti(self): + """The "jti" (JWT ID) claim provides a unique identifier for the JWT. + The identifier value MUST be assigned in a manner that ensures that + there is a negligible probability that the same value will be + accidentally assigned to a different data object; if the application + uses multiple issuers, collisions MUST be prevented among values + produced by different issuers as well. The "jti" claim can be used + to prevent the JWT from being replayed. The "jti" value is a case- + sensitive string. Use of this claim is OPTIONAL. + """ + self._validate_claim_value('jti') + + +def _validate_numeric_time(s): + return isinstance(s, (int, float)) diff --git a/.venv/Lib/site-packages/authlib/jose/rfc7519/jwt.py b/.venv/Lib/site-packages/authlib/jose/rfc7519/jwt.py new file mode 100644 index 00000000..ba27998b --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc7519/jwt.py @@ -0,0 +1,183 @@ +import re +import random +import datetime +import calendar +from authlib.common.encoding import ( + to_bytes, to_unicode, + json_loads, json_dumps, +) +from .claims import JWTClaims +from ..errors import DecodeError, InsecureClaimError +from ..rfc7515 import JsonWebSignature +from ..rfc7516 import JsonWebEncryption +from ..rfc7517 import KeySet, Key + + +class JsonWebToken: + SENSITIVE_NAMES = ('password', 'token', 'secret', 'secret_key') + # Thanks to sentry SensitiveDataFilter + SENSITIVE_VALUES = re.compile(r'|'.join([ + # http://www.richardsramblings.com/regex/credit-card-numbers/ + r'\b(?:3[47]\d|(?:4\d|5[1-5]|65)\d{2}|6011)\d{12}\b', + # various private keys + r'-----BEGIN[A-Z ]+PRIVATE KEY-----.+-----END[A-Z ]+PRIVATE KEY-----', + # social security numbers (US) + r'^\b(?!(000|666|9))\d{3}-(?!00)\d{2}-(?!0000)\d{4}\b', + ]), re.DOTALL) + + def __init__(self, algorithms, private_headers=None): + self._jws = JsonWebSignature(algorithms, private_headers=private_headers) + self._jwe = JsonWebEncryption(algorithms, private_headers=private_headers) + + def check_sensitive_data(self, payload): + """Check if payload contains sensitive information.""" + for k in payload: + # check claims key name + if k in self.SENSITIVE_NAMES: + raise InsecureClaimError(k) + + # check claims values + v = payload[k] + if isinstance(v, str) and self.SENSITIVE_VALUES.search(v): + raise InsecureClaimError(k) + + def encode(self, header, payload, key, check=True): + """Encode a JWT with the given header, payload and key. + + :param header: A dict of JWS header + :param payload: A dict to be encoded + :param key: key used to sign the signature + :param check: check if sensitive data in payload + :return: bytes + """ + header.setdefault('typ', 'JWT') + + for k in ['exp', 'iat', 'nbf']: + # convert datetime into timestamp + claim = payload.get(k) + if isinstance(claim, datetime.datetime): + payload[k] = calendar.timegm(claim.utctimetuple()) + + if check: + self.check_sensitive_data(payload) + + key = find_encode_key(key, header) + text = to_bytes(json_dumps(payload)) + if 'enc' in header: + return self._jwe.serialize_compact(header, text, key) + else: + return self._jws.serialize_compact(header, text, key) + + def decode(self, s, key, claims_cls=None, + claims_options=None, claims_params=None): + """Decode the JWT with the given key. This is similar with + :meth:`verify`, except that it will raise BadSignatureError when + signature doesn't match. + + :param s: text of JWT + :param key: key used to verify the signature + :param claims_cls: class to be used for JWT claims + :param claims_options: `options` parameters for claims_cls + :param claims_params: `params` parameters for claims_cls + :return: claims_cls instance + :raise: BadSignatureError + """ + if claims_cls is None: + claims_cls = JWTClaims + + if callable(key): + load_key = key + else: + load_key = create_load_key(prepare_raw_key(key)) + + s = to_bytes(s) + dot_count = s.count(b'.') + if dot_count == 2: + data = self._jws.deserialize_compact(s, load_key, decode_payload) + elif dot_count == 4: + data = self._jwe.deserialize_compact(s, load_key, decode_payload) + else: + raise DecodeError('Invalid input segments length') + return claims_cls( + data['payload'], data['header'], + options=claims_options, + params=claims_params, + ) + + +def decode_payload(bytes_payload): + try: + payload = json_loads(to_unicode(bytes_payload)) + except ValueError: + raise DecodeError('Invalid payload value') + if not isinstance(payload, dict): + raise DecodeError('Invalid payload type') + return payload + + +def prepare_raw_key(raw): + if isinstance(raw, KeySet): + return raw + + if isinstance(raw, str) and \ + raw.startswith('{') and raw.endswith('}'): + raw = json_loads(raw) + elif isinstance(raw, (tuple, list)): + raw = {'keys': raw} + return raw + + +def find_encode_key(key, header): + if isinstance(key, KeySet): + kid = header.get('kid') + if kid: + return key.find_by_kid(kid) + + rv = random.choice(key.keys) + # use side effect to add kid value into header + header['kid'] = rv.kid + return rv + + if isinstance(key, dict) and 'keys' in key: + keys = key['keys'] + kid = header.get('kid') + for k in keys: + if k.get('kid') == kid: + return k + + if not kid: + rv = random.choice(keys) + header['kid'] = rv['kid'] + return rv + raise ValueError('Invalid JSON Web Key Set') + + # append kid into header + if isinstance(key, dict) and 'kid' in key: + header['kid'] = key['kid'] + elif isinstance(key, Key) and key.kid: + header['kid'] = key.kid + return key + + +def create_load_key(key): + def load_key(header, payload): + if isinstance(key, KeySet): + return key.find_by_kid(header.get('kid')) + + if isinstance(key, dict) and 'keys' in key: + keys = key['keys'] + kid = header.get('kid') + + if kid is not None: + # look for the requested key + for k in keys: + if k.get('kid') == kid: + return k + else: + # use the only key + if len(keys) == 1: + return keys[0] + raise ValueError('Invalid JSON Web Key Set') + return key + + return load_key diff --git a/.venv/Lib/site-packages/authlib/jose/rfc8037/__init__.py b/.venv/Lib/site-packages/authlib/jose/rfc8037/__init__.py new file mode 100644 index 00000000..fd0f3fe4 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc8037/__init__.py @@ -0,0 +1,5 @@ +from .okp_key import OKPKey +from .jws_eddsa import register_jws_rfc8037 + + +__all__ = ['register_jws_rfc8037', 'OKPKey'] diff --git a/.venv/Lib/site-packages/authlib/jose/rfc8037/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc8037/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bd21d8d341206723b3d37c38b68a925ffb2ea1e9 GIT binary patch literal 360 zcmZ3^%ge<81i#(4rj`Tg#~=<2FhLog)qsrY3@HpLj5!Rsj8Tk?AU0DDQ!aB9Gmy=k z!jjGu#gf7r%%I8kk`bs_lkpatzjuIlY9){*Qk0sWSzMA@6rWXI9AA`{Y++z*Uc>@a zR>TY>{4`l_vFB$O#Al~gf(34Ig4Cs^q!cHDRo!Bbk5A0WiH~2&@ENF{;a7}{RZMbz zN@iYqOlW>uh(}^_c5zHlYHn(7Qfg6ZadK*2a%zlTS!!Ncj8A4#OmSvOs%`;LQDS;( zaZF-qNk&d)l73cxajHJlG5YcGnR%Hd@$q^EmA^P_a`RJ4b5iY!xPg{|d{b-*Bt9@R kGBVy^kiLM5ZZK$HKt&(e7w$HB0-augj99fDweC&vNMX`jXWsk0 zH}h*xPZ&`Cz4wOxAp^V?#0z__ZXdkB9wtbQX-I)iIh}`oK%T|n+AxAsF8r@ zfQAkP-E(tfHgVVA!VP%+&Fgby!(@a{T5D{b#%Jxc?UiBfgYparDv>9=An= zE53tqgfcj7@36Px>s!(;>U(}a0k5S6U1mX?<%aESA*Y0AnIJC{yT8;%*+t4Iw`k6ysi}3ETTeZ(7gOAJ=wtyW znQ6*X=9;sdu@|RT@|;eyCF_%qZ`_(*+295xgqu@^qT5|yv|utSoY)*bP1Mv0nSG)3nB*AkH6_EJBN*{WO>?EaMaaWR<7c39EF`n#hbg?cP41DW)E8V zM+hZo#QMvZe!f)EYOyQz*p(MrBRcTv*~@1;H)_$*dUUiJ8fCpW(-KR!Md)5_lu*I= zl?t|<(hFd!obSQC4G4T__gfH81R?EE1xRe~o#lmu+RQ{@S4NV>Yk1n{N7%3c;i4Y!xMCMjcNGkt4GPl`0vES}VC#r3@z3VK8M;~v$Hepm!ZBf? zT1>CU^cPxFR=X}XBE7F3zI?bdw!>?Yv3g{z8X0T!4Q}5&d>b8Yg4A{K7#e*;+cVoU zO$A2}4-a_+*DYU|hTp=smEWb?%7PwpLxzzvv(zx$uwi8LWGy4~h++J&W@e5os%YJA zf~SPp1;@_knDEm}yGOul@KV<*hAv?epy9{o5la5k=OrWc6(Bwe8 z2|k3h00zLVmpc5XI{eF>+Q>wG zWTK{CtE<XFaAdUJ!g{H>YmGfY&M8_ch^&aJo+ zJ@>qA*$1L4&Xt#(_o2^PIljYm921`NpAfJ_B&h*6tEb-vT&|ve8!%Em{Wi6jgsJL; V?bP35^q*tXRY{t}ly`vV-+wRvr!xQm literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc8037/__pycache__/okp_key.cpython-311.pyc b/.venv/Lib/site-packages/authlib/jose/rfc8037/__pycache__/okp_key.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2e2e2265cc6dca734236d164a49b73a4a0bf5acf GIT binary patch literal 5917 zcmdrQNo*U}bruduap#btHcFvwIW|?9vMkAxmqeCi*;e8*sudgQL@7;iMiOlfss0%$ zmO!UMpaW9`sBSjU1mGcc)y6J-DNq#Xv9}&L#Hb<$5D=g!(A=0h?IFGN{TZ&Zob6Je zU((b6Z~5C>|NPqNv=Pw$bM^PaKb!>dH$12|rqX%#N9a5tc!DQWgh+CvNO2U2$5e_I zO`J(&I7T1SDYIzdETWaO>SI%?MYM4?(azcRF_UtLPR=R1IG5<=+@go`=y-F=E3zCb z`Z%BH=lo(T*9v$GZ%qZnHm;2%1X3^w7Qx21d}QL<1xjE9t6Ez9vi??hMoLlhl z)~y5Ua9+LzXe_oH&d1vU`gxXjZjoH85a4~hpZ9Jt&3oh8bZctW%x}Ct3zo8R6hJ7E zic3-`vlx<>h0yKWK)QW9bQcKn`icgdzVcV(j$L=s@P~3f^jDWnJ@C_Z2fvh4CAmhD}5cp`C_J zNjCv(5}yS+_X2&zK%WxmR|EYyd&wRs6J*QjkI(1t?har6bGk5eQ|Y>;cHPp^C11~; z??lmeV#lob22|fb!7;G!YAY@1J@x(}vZgsmOAzvz zC~5^p6u_VjgLVMn7IXynv6&!zc!ci?;bS2S2D)akSXqnxC@j~|{#W|rmL6FA8uI({{C_ec~q5GoZd_{G> zf~^H;9ouKiH1zZ#3d0_nECU}@4=}%l4p;`jYReLLYP#mhjw+g{_wJK2zO71=@qJZV zlPp!2XbvIGBM4jM3qlXo%n910qbLY#p&kHXM)S=LcBkHkpDtkU>*=LXa>e|kmk7IwBQ%_AOy_0J1q{2?A>{QND zatHR@;i5adb3$>SQQc<>)-(Tq3hRc80fo6|Z%$sHnX2gv4FJADQC>q)dR1nqqoOA? z2#lKL-eEd&8>%pbu!;grDyreH!W1&wUFGoh-Uf?zAcHLDfB2 zunvBWhWy|@FV5MGE|PBu!LYYVdj$VqR0rKBo8++zKi3)q@|~KaHip^;th+9LU|pEI zUO(TbWb93qCi|*ATw^plY4a#c^5jKe&O!=-%E0hjo95wH#T6+Ai5seK?0x8EVA5=L zgyyVfbKP4Jt~oUNM*Lj_ZxaIHJb>`t5euN|%XDVp4mtyfW*_!eR;$+;8|@Vfd5&@& zOJ@LV5+xVA=Q>t&9m`)jnFNB6#?{e$R-(Jw3}pY2NmK+f_n8{zNS?HPD#QF_MIo-xIDPW7G3(YdJ)tR**_ zv+4E}Z7Kq5G5RmC9WW?z(*nwezR|!G$b2nQSF!kiV>Z82Gm$2=MWvqrulN*fa>&<~DKZ1Gy3?WPzaa<1zR&)Vo(i|1-*A?n1a_xftwCnpo|y?WJ}=ww5|y%KIJ$3#LG+ zwR8LC!|}bY!D82-(lw-Z4Joa|YU}W3v=r#t77D@sz2HzWIHUwe)ZmB`II9NEZoW}! ze;KAJn;2%2g!;S=U4)q}Q&tA5Z2(`;Fx;9q5Pq5&f~ZghHkvtuhZSJ6GCnL*0e%Yu zA*30wgxOoBEX)`tGyuGcckAr~B;%Iw1x3SM+MxcaD6@p(E6eMV<@g4CQi_15h)FrQ zCP*srV?4QG87@qoigTlxebywFIpOi?6NCcYV%znMj!<$uL@*b&S$ zKHK*LR)Xv;5XTyS%T~e@DmlAKuI`efquj#yV0HkT?y`&U94R@2C09?$(FqhkrueA> Z;VFA2NfJEgaF~1N3!U=i3+TEQ{|jDbG_n8y literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/jose/rfc8037/jws_eddsa.py b/.venv/Lib/site-packages/authlib/jose/rfc8037/jws_eddsa.py new file mode 100644 index 00000000..872da8e3 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc8037/jws_eddsa.py @@ -0,0 +1,27 @@ +from cryptography.exceptions import InvalidSignature +from ..rfc7515 import JWSAlgorithm +from .okp_key import OKPKey + + +class EdDSAAlgorithm(JWSAlgorithm): + name = 'EdDSA' + description = 'Edwards-curve Digital Signature Algorithm for JWS' + + def prepare_key(self, raw_data): + return OKPKey.import_key(raw_data) + + def sign(self, msg, key): + op_key = key.get_op_key('sign') + return op_key.sign(msg) + + def verify(self, msg, sig, key): + op_key = key.get_op_key('verify') + try: + op_key.verify(sig, msg) + return True + except InvalidSignature: + return False + + +def register_jws_rfc8037(cls): + cls.register_algorithm(EdDSAAlgorithm()) diff --git a/.venv/Lib/site-packages/authlib/jose/rfc8037/okp_key.py b/.venv/Lib/site-packages/authlib/jose/rfc8037/okp_key.py new file mode 100644 index 00000000..40f74689 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/rfc8037/okp_key.py @@ -0,0 +1,103 @@ +from cryptography.hazmat.primitives.asymmetric.ed25519 import ( + Ed25519PublicKey, Ed25519PrivateKey +) +from cryptography.hazmat.primitives.asymmetric.ed448 import ( + Ed448PublicKey, Ed448PrivateKey +) +from cryptography.hazmat.primitives.asymmetric.x25519 import ( + X25519PublicKey, X25519PrivateKey +) +from cryptography.hazmat.primitives.asymmetric.x448 import ( + X448PublicKey, X448PrivateKey +) +from cryptography.hazmat.primitives.serialization import ( + Encoding, PublicFormat, PrivateFormat, NoEncryption +) +from authlib.common.encoding import ( + to_unicode, to_bytes, + urlsafe_b64decode, urlsafe_b64encode, +) +from ..rfc7517 import AsymmetricKey + + +PUBLIC_KEYS_MAP = { + 'Ed25519': Ed25519PublicKey, + 'Ed448': Ed448PublicKey, + 'X25519': X25519PublicKey, + 'X448': X448PublicKey, +} +PRIVATE_KEYS_MAP = { + 'Ed25519': Ed25519PrivateKey, + 'Ed448': Ed448PrivateKey, + 'X25519': X25519PrivateKey, + 'X448': X448PrivateKey, +} + + +class OKPKey(AsymmetricKey): + """Key class of the ``OKP`` key type.""" + + kty = 'OKP' + REQUIRED_JSON_FIELDS = ['crv', 'x'] + PUBLIC_KEY_FIELDS = REQUIRED_JSON_FIELDS + PRIVATE_KEY_FIELDS = ['crv', 'd'] + PUBLIC_KEY_CLS = tuple(PUBLIC_KEYS_MAP.values()) + PRIVATE_KEY_CLS = tuple(PRIVATE_KEYS_MAP.values()) + SSH_PUBLIC_PREFIX = b'ssh-ed25519' + + def exchange_shared_key(self, pubkey): + # used in ECDHESAlgorithm + private_key = self.get_private_key() + if private_key and isinstance(private_key, (X25519PrivateKey, X448PrivateKey)): + return private_key.exchange(pubkey) + raise ValueError('Invalid key for exchanging shared key') + + @staticmethod + def get_key_curve(key): + if isinstance(key, (Ed25519PublicKey, Ed25519PrivateKey)): + return 'Ed25519' + elif isinstance(key, (Ed448PublicKey, Ed448PrivateKey)): + return 'Ed448' + elif isinstance(key, (X25519PublicKey, X25519PrivateKey)): + return 'X25519' + elif isinstance(key, (X448PublicKey, X448PrivateKey)): + return 'X448' + + def load_private_key(self): + crv_key = PRIVATE_KEYS_MAP[self._dict_data['crv']] + d_bytes = urlsafe_b64decode(to_bytes(self._dict_data['d'])) + return crv_key.from_private_bytes(d_bytes) + + def load_public_key(self): + crv_key = PUBLIC_KEYS_MAP[self._dict_data['crv']] + x_bytes = urlsafe_b64decode(to_bytes(self._dict_data['x'])) + return crv_key.from_public_bytes(x_bytes) + + def dumps_private_key(self): + obj = self.dumps_public_key(self.private_key.public_key()) + d_bytes = self.private_key.private_bytes( + Encoding.Raw, + PrivateFormat.Raw, + NoEncryption() + ) + obj['d'] = to_unicode(urlsafe_b64encode(d_bytes)) + return obj + + def dumps_public_key(self, public_key=None): + if public_key is None: + public_key = self.public_key + x_bytes = public_key.public_bytes(Encoding.Raw, PublicFormat.Raw) + return { + 'crv': self.get_key_curve(public_key), + 'x': to_unicode(urlsafe_b64encode(x_bytes)), + } + + @classmethod + def generate_key(cls, crv='Ed25519', options=None, is_private=False) -> 'OKPKey': + if crv not in PRIVATE_KEYS_MAP: + raise ValueError(f'Invalid crv value: "{crv}"') + private_key_cls = PRIVATE_KEYS_MAP[crv] + raw_key = private_key_cls.generate() + if not is_private: + raw_key = raw_key.public_key() + return cls.import_key(raw_key, options=options) diff --git a/.venv/Lib/site-packages/authlib/jose/util.py b/.venv/Lib/site-packages/authlib/jose/util.py new file mode 100644 index 00000000..5b0c759f --- /dev/null +++ b/.venv/Lib/site-packages/authlib/jose/util.py @@ -0,0 +1,37 @@ +import binascii +from authlib.common.encoding import urlsafe_b64decode, json_loads, to_unicode +from authlib.jose.errors import DecodeError + + +def extract_header(header_segment, error_cls): + header_data = extract_segment(header_segment, error_cls, 'header') + + try: + header = json_loads(header_data.decode('utf-8')) + except ValueError as e: + raise error_cls(f'Invalid header string: {e}') + + if not isinstance(header, dict): + raise error_cls('Header must be a json object') + return header + + +def extract_segment(segment, error_cls, name='payload'): + try: + return urlsafe_b64decode(segment) + except (TypeError, binascii.Error): + msg = f'Invalid {name} padding' + raise error_cls(msg) + + +def ensure_dict(s, structure_name): + if not isinstance(s, dict): + try: + s = json_loads(to_unicode(s)) + except (ValueError, TypeError): + raise DecodeError(f'Invalid {structure_name}') + + if not isinstance(s, dict): + raise DecodeError(f'Invalid {structure_name}') + + return s diff --git a/.venv/Lib/site-packages/authlib/oauth1/__init__.py b/.venv/Lib/site-packages/authlib/oauth1/__init__.py new file mode 100644 index 00000000..c9a73ddf --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth1/__init__.py @@ -0,0 +1,34 @@ +from .rfc5849 import ( + OAuth1Request, + ClientAuth, + SIGNATURE_HMAC_SHA1, + SIGNATURE_RSA_SHA1, + SIGNATURE_PLAINTEXT, + SIGNATURE_TYPE_HEADER, + SIGNATURE_TYPE_QUERY, + SIGNATURE_TYPE_BODY, + ClientMixin, + TemporaryCredentialMixin, + TokenCredentialMixin, + TemporaryCredential, + AuthorizationServer, + ResourceProtector, +) + +__all__ = [ + 'OAuth1Request', + 'ClientAuth', + 'SIGNATURE_HMAC_SHA1', + 'SIGNATURE_RSA_SHA1', + 'SIGNATURE_PLAINTEXT', + 'SIGNATURE_TYPE_HEADER', + 'SIGNATURE_TYPE_QUERY', + 'SIGNATURE_TYPE_BODY', + + 'ClientMixin', + 'TemporaryCredentialMixin', + 'TokenCredentialMixin', + 'TemporaryCredential', + 'AuthorizationServer', + 'ResourceProtector', +] diff --git a/.venv/Lib/site-packages/authlib/oauth1/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth1/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f80b60cc3c140a91a4b60db17133589e2ffe88a0 GIT binary patch literal 807 zcmd6kPjAyO7{;CSPuiww3oVE%q|ip|q^&Dyil`MSN|SfRS{xTAtr#c1 z1$Qop55R?w;tK~(+$!xhF4(K4O%or0*V4~^A3wHV+g~lKhGhIX_zpjHgnp^yI%Iwo z7bDqyMlp)D1W^rZRL43k-~uh;A}!$(E#opZut6)hLaVq+Yq&;DY|=WeQwv+Pfg2iH z$n{?|+>G@J>K1-$a?@@@SSR)>f7f&2{R*;N)cOg5G*_BvPYw@8wl{U1V0dizgUQhD ziTgLAJF&OgE#vseJ{)<@TTeW=F?zGH+`_R3jw?EM~U znWD=#gFQcDF-aHxl%0CRFgnY87bwsn+a literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth1/__pycache__/client.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth1/__pycache__/client.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6db5599ee21f6c56c9be7767256685d0ad15fa40 GIT binary patch literal 8605 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth1/__pycache__/errors.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth1/__pycache__/errors.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a69bf0432e1a22faf2e391c6efc5eef4eee14101 GIT binary patch literal 234 zcmZ3^%ge<81i#(4rs@Id#~=<2FhLog`GAb+3@HpLj5!P;3@J>(44TX@8G(YDjJFuI z{D351QChO8g^8tJYEe;sQSnNK&mg_OLR_q3lJiqC^U`BN^V32+5|guwV}eq1Q*)D2 zi&Be|Q}dEjWAw^W^U7j;GLvG8GfPr+3xJ9e(^HFM5=%=max#= 400: + message = ( + "Token request failed with code {}, " + "response was '{}'." + ).format(status_code, text) + self.handle_error('fetch_token_denied', message) + + try: + text = text.strip() + if text.startswith('{'): + token = json_loads(text) + else: + token = dict(url_decode(text)) + except (TypeError, ValueError) as e: + error = ( + "Unable to decode token from token response. " + "This is commonly caused by an unsuccessful request where" + " a non urlencoded error message is returned. " + "The decoding error was {}" + ).format(e) + raise ValueError(error) + return token + + @staticmethod + def handle_error(error_type, error_description): + raise ValueError(f'{error_type}: {error_description}') diff --git a/.venv/Lib/site-packages/authlib/oauth1/errors.py b/.venv/Lib/site-packages/authlib/oauth1/errors.py new file mode 100644 index 00000000..e7770da5 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth1/errors.py @@ -0,0 +1,3 @@ +# flake8: noqa + +from .rfc5849.errors import * diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__init__.py b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__init__.py new file mode 100644 index 00000000..1f029fbb --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__init__.py @@ -0,0 +1,45 @@ +""" + authlib.oauth1.rfc5849 + ~~~~~~~~~~~~~~~~~~~~~~ + + This module represents a direct implementation of The OAuth 1.0 Protocol. + + https://tools.ietf.org/html/rfc5849 +""" + +from .wrapper import OAuth1Request +from .client_auth import ClientAuth +from .signature import ( + SIGNATURE_HMAC_SHA1, + SIGNATURE_RSA_SHA1, + SIGNATURE_PLAINTEXT, + SIGNATURE_TYPE_HEADER, + SIGNATURE_TYPE_QUERY, + SIGNATURE_TYPE_BODY, +) +from .models import ( + ClientMixin, + TemporaryCredentialMixin, + TokenCredentialMixin, + TemporaryCredential, +) +from .authorization_server import AuthorizationServer +from .resource_protector import ResourceProtector + +__all__ = [ + 'OAuth1Request', + 'ClientAuth', + 'SIGNATURE_HMAC_SHA1', + 'SIGNATURE_RSA_SHA1', + 'SIGNATURE_PLAINTEXT', + 'SIGNATURE_TYPE_HEADER', + 'SIGNATURE_TYPE_QUERY', + 'SIGNATURE_TYPE_BODY', + + 'ClientMixin', + 'TemporaryCredentialMixin', + 'TokenCredentialMixin', + 'TemporaryCredential', + 'AuthorizationServer', + 'ResourceProtector', +] diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6249482928e2b44397c1040381980756a8df2aea GIT binary patch literal 1267 zcmb_b&ubGw6rRnm&CfPXQW5d6=qU#`2CQfiA-16{^q0vN>=0bGyOU(-%+5NyskR64 zzwquwJbCi}=&|h8lea)`)q^t=V^b*}#L4jS^3CIY?>)Z#SSsa#IN#U4pkfMuukz3I zBz^_wCn9(cJOF{Gc?qJ?1Waf$PLd=|!IX+qBuz6gLv^UrEX>jz%+Wl|(*i80_cSTe z5-ia@Et zc3MKjXqxwpUCturGGb234WlRsmm7_UF%p^>MSYX;L1P$E(wMgNO%ofdYjH_cX?D=7 z5eg$giZFl0@AN2FRc4vQ9N+mzrS>3Ov;=-h#E&K-i@l6ZSfN_T(uW;mvHnBq{ zFExuDBL7dedQHBVu_~uy9G|Ftb`d{9T+j<06tWR_k=&=)JLB~^o)mlH!gqkDC1fP% z60#C<5~M$QK|)bNNy40jc?o3!+w~iA_9t*IdIlFSSC@M( z^RPeY?XkYK?zo3xuOo~|50I$gBHu+l^9cDzy-j@33vq<*1tQ5Aps*+P#i!7idEZ`?Rt73`( literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/authorization_server.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/authorization_server.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6c4e9142b20568b67200951afa4a963f3ccf6c67 GIT binary patch literal 16553 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 TakDO8Ui>Y2^1B+(Nk{(=a!mrq literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/base_server.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/base_server.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dc6f70bb29b40bd4c46f9423b87c14a625aec5df GIT binary patch literal 4908 zcmb_gT}&L;6~427>>upz7%1B(NsnwAt6DyM1w41ko%N(V*^X2Pa6^ zeWY|eav<~s{;Vg}rEp6~^nOcU6W?+`MW=aeDL$K+OfE0ZNOSX(m!+k-$+1S}!qv%m zB02L((&X!si%XMC5Y~scF;UlVOPg6aEoqzbn9bSB$ZAfmm-wvRGjw_xYz|Wq_}~G=_RBhN(Xhi>7SA{yo3pL#W46j z?X=e-M91{+*$E&I(2ipVUAL!qxDQ~=?#?0q6_(E2(s51^w3-V9@DcbxU|v?!vaaTH zqkg|oePUbGjY1Aw851T2O()=DLC*^WZxO8FoZhBtv~{s{fpqzLA(y5bPz4sZzPe%4 z)W@ z*h)ID!1b*x=hu^Sa{7k0vWT-dyN2N=(-^{jWpo?owpXsIYb% z>e|IT9gJNh>*;rY{LXt9*B~qk<5NC%gfsYR7@xMU^+u(8#XS z@DA)LW$$2#{XT;!l(sPmUMLc>*pC7iVxOx={zHmUZI8k|0{#CorT5q8n@@U=qqiY?ip7sz*BR=Tr#;(!-58+s={LxBw|7nG{HL13M%ZpHA5{M zngNT!c1jQ$KE>13sw13f5k4b8)hl4J(+pZO4D~eAxq)>v+=?i~4ax|0oauy8N@zP_ z24+54h%bIBCFAomri-52^n*JJ)q>|s-rlMXgZLI8l_oLE2#q??Wx6z+SvNbX$2EPn z<4iY`(`f8a93{PUw^OW2gQx2rmcYN3&f-u5B)m%SBB;`)A!7j*{HW)Y(S81D_wauA zaA{f0Op<(=I-hrMFy!j*FGRipQ6DSY)Pbj%2yrV8h|-%o!P|J{|Zu6!ewqwoJoF(wlG z(L^blXj$_7`C<6PZ{wxVIl6V6Yov$#+0wb$GCybVbEV*1#YqL8KYtF^hkK~thhXS8 zon?N);3rDKiK9U1Y2eg;;MCso!`X6R*a!?$sdIrbABxAjYjf~qIZETGrfg00-%l1WPp+` zAfk($rQ>rzOpnzoksf$yN$oy6V_PgN4!$U@TZDc_6+Q;SQkw5KBI2&+AjHD^r&c1) zmHD{A$4kNZQ6RF{ZS=oa3eev}eyq%2GWbiS;H9HbuMrYxw6|sNQKZL+3_Xp!wI6xw z>yOHjOGf09y~R7tN_uv;zufr6=U;qIHC;I5hswNY@M0+_(!9CAxTFuPZAujy=B)Lg zet&>;yQOFkbdf85F^hE}ol$ASTq_I0O;z6%bZB-rROq{)>{tSls;sWI7a4o9p%Kro zSCzsVyUN6@E;J@wZr;xpc+8o{5_vtI-O51!2cKEiCy?l1cW?UaoiuvL8k&cp%t+O# zwcD^^@npkQw@z-rN-YfJF8XH>h0c__28}M-$620ifD!oSd<{>^K5#VsKwt&Os))k; z@={V*!$KjaLboo+X_D78LC$1qC0nceT7%};_Jm!)hHICThEGRui3;ugFlz?%{0+F9 zbUwSL!bc-~ylCxL!)$4|7Dx{Im9XC0N!a_oX5V1n=u|$R!E(;lLw*Fl6P;Gho`*3@ z+*;4isxXNHyLi0esv0YM9wuwo6mGkwgvgs-Nuu8ql4SZNDVtXc89EM1(q{!ZW6cl> z4Dz sP~a~6sW@Dmqk>+C_+LkuY4&^Q9{(%h*EkMb`eOPWS>~001HR?lApigX literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/client_auth.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/client_auth.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..db9694a33eacb28d34ca8efa8f47c0ee93facd48 GIT binary patch literal 8468 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/errors.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/errors.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5453fa3b38d9172129a7f51fa27f977e10bb65ff GIT binary patch literal 5399 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/models.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/models.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1a9b28895f0fff6ebb5052ac4000f6199c751ad2 GIT binary patch literal 6023 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/resource_protector.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/resource_protector.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1c01cfd5052107e45070adf9a545b10045aeb479 GIT binary patch literal 2152 zcmb7F&2Jk;6rZ)d-i_<{V`&PMmaLM-ktJ|w1foq*5YV(#f>5R5Vp&>kb|>+Y{cva2 zsZu#og?h-L65PTurx27&FZ>rA>}ac4BSnhD2~I|VOS$l7*B^D#3uEuwH*bFP=FOYm zy#0A}G=-r3d-qrTX9A($d8gOJu5!8v$__G-DcHyn%7Vc4m>qNC<#?#a?SvziMJHKK zI#O8@Pz>EgX5uL_MJ(*a5jub;YGv6>K0rn34*~i`fu%mzDSm*-1}4xO{pPc}U%kGB zAJ#GTi*a`KYl~9LUE>yuVDr9CbO-yGED+)mrrdKkblWn&ur2KRkuBe~Eqm+O4NXRG zasKA(@^*R|#16u!ESRVqGli$995-Vi6J{JDOtAbCre2*G_&)J`Z1^5AdMV)!lJM|t zo&E?ecaYz645o(Ah&AGk#2%#d0G_CAi4F0)K8j}jSG<|R9*i9HN52;uXt$rVo(KMZ z)yMFhtz;ufGycc`y$9++zY9K-4N>c_3ZD2L!geN_*s$j?8mWhU_1zGMky}zjf*A4x z%()mOh@l@N>@p7tW%1|20SvjxWB*6i){-X@=+0x`T5 zg#6TftofD$oYtM1rn{!*dai-lTm8`}E^4j0x?d-_D6<5`_9{yP+pC_*;&o!N#ENHb zGO3Dn6BEiL65SJ$g;hxo1eHOk-S)D2d#+-5CS0G&x8CaVm%6b|D@)kH&I%@&8W=*T zls2%tQTfVRsZh(u@7DmNuVGr@xwEa6nJ}>HGi25H=*EXPXJB4AfC=Ppm_EQTK^eF5SLI#$Mall$@g<>w!_lv{yvYg;&Gf=ae(We;ILsGz9|hAlTKStn{^oYFogL%o>0{+uODP0Op_wkU-yYwVo@Kz- zvn@XODR_E5+EV5NWxko7KgnG@$`ucD#r^44ZZ^oxZj0^gMGh<+E0Zl{Dp01H>8X>e z6WdZCUvA6kBe{4ebGSSk$g@p(HndG0%2T^*Ex8oPrKVhJXD@AMPGMunh;i9%Tn`Jz zyPymgjI)=dC_Mh{4)%?z>Q}KEvP>P2N?j$Mqnf&}s}!mdR&8q?t9oczfpYp@sz-rU zUM(MaWL>3IuWp;F<j-2*YGXREv5QX=4!mes@-#(Q->^sX@(wrf`ti7Mo$)9{kSl-< zm;D8W^P)I-og!TDB1LCGJn8>Bu`%(@4(f}NBwp*F^CEJ`oh%kd*adz-8Vx^qgtLK3 zkBDBYVGOdPFPaH7|0~R2f@9RKZ*7-Po`mje>&(7AUbhD5ZY+6Is9*< hiRSRX6H5rO4*EYLGcLd$&x@Z@e{t*IuNevh{twcw9_|1D literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/rsa.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/rsa.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9ac0a18f52f526e0944922e08f27849efc659d75 GIT binary patch literal 1821 zcmb_cy>Ht_6hD55q9of=V!MW$%8}a+A(BWC8W(Py#xPv8DOwms<+iY@RG`SS#D)}w zJ4%iM8Sv1-$P#bq5}=cd!0r$r`2(_Mk^l_?0Z*N}DRBlPUHXptGSM_ydN}_0?%lih zj_>y#e;*$YBN%^w@dWP(2>rm+($rn`Z7B1@w?@pPvs^=@%%2$X{QyrYYh3oF*NLwwKhQ^d|K3Gw8-6$79jD1>Lbtb>svF zdkF1=craWZa{F-dV0e0)Z}7hjS3@%p8psKa);|wD`u#cMr)+`)*>B^I2>IpLAboO0 zrF6?Cx*HtiR3hDXwi)ls`^L} zAnBCZB@&5O8=qaxX*NrK?mK&P{RR+7bKhbMTLnxY*!fm$z8#zI2E~Z<909y!u(R3?qp|3{#k-4ps}E+{vr23BVte-DAKxGT z`0(c8%~oWo9a(CMOUK|BX{V`Td13407XWW458huMZ!8Wdzk^{3ZVMsQ5dNz?8r=U@ zAVBs3BitL%kbDMxfSlMsgV2Xi5FFY-x{yIz=(ezdwm3yxQ#djPM(dv|A;OyFROv`H zOpMLCS3G2b?XgsmC<7Tl5nTb;BP@tJ;T6!ZU&&ceQg$Jzp9Gm?CXt@M9@+1Lh7nG; z0T|hFM)q7wPPFC3i0Od9m$-<)*yciB9f1Cr6QUUBm^ZN6?8*?N)cIT>-QwCnxj_+~Dx)$_4cFLU`q4 z;pqYgxTZwiIgQjSj$I^brBqLr)H{~yB;ikG8IDoIwAV)Oz0RoLjH zXZW4nQ60lB_ZpZ{;VN%Ar_#D*VTTx6ufb=0_V~7jE6gMH*m7t3jhNJI%d*Q!Xj-qO zdyF$K2qWboBGXJ}l)aL#S+-s^@pbY(EZOgoJ_3N$aa;$boBr8Bi%tLR@;t|P(c3{n l-1R2<^z`hYD^36Gpi52v>`D@Mt&4_mHpBtZ{|4`q{sB6ttI7ZX literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/signature.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/__pycache__/signature.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6ae075c6d04359182f317262b8b4a8c90611a3f9 GIT binary patch literal 13646 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 Cm4^U=> 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 self.EXPIRY_TIME: + raise InvalidRequestError('Invalid "oauth_timestamp" value') + except (ValueError, TypeError): + raise InvalidRequestError('Invalid "oauth_timestamp" value') + + if not nonce: + raise MissingRequiredParameterError('oauth_nonce') + + if self.exists_nonce(nonce, request): + raise InvalidNonceError() + + def validate_oauth_signature(self, request): + """Validate ``oauth_signature`` from HTTP request. + + :param request: OAuth1Request instance + """ + method = request.signature_method + if not method: + raise MissingRequiredParameterError('oauth_signature_method') + + if method not in self.SUPPORTED_SIGNATURE_METHODS: + raise UnsupportedSignatureMethodError() + + if not request.signature: + raise MissingRequiredParameterError('oauth_signature') + + verify = self.SIGNATURE_METHODS.get(method) + if not verify: + raise UnsupportedSignatureMethodError() + + if not verify(request): + raise InvalidSignatureError() + + def get_client_by_id(self, client_id): + """Get client instance with the given ``client_id``. + + :param client_id: A string of client_id + :return: Client instance + """ + raise NotImplementedError() + + def exists_nonce(self, nonce, request): + """The nonce value MUST be unique across all requests with the same + timestamp, client credentials, and token combinations. + + :param nonce: A string value of ``oauth_nonce`` + :param request: OAuth1Request instance + :return: Boolean + """ + raise NotImplementedError() diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/client_auth.py b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/client_auth.py new file mode 100644 index 00000000..2c59b594 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/client_auth.py @@ -0,0 +1,187 @@ +import time +import base64 +import hashlib +from authlib.common.security import generate_token +from authlib.common.urls import extract_params +from authlib.common.encoding import to_native +from .wrapper import OAuth1Request +from .signature import ( + SIGNATURE_HMAC_SHA1, + SIGNATURE_PLAINTEXT, + SIGNATURE_RSA_SHA1, + SIGNATURE_TYPE_HEADER, + SIGNATURE_TYPE_BODY, + SIGNATURE_TYPE_QUERY, +) +from .signature import ( + sign_hmac_sha1, + sign_rsa_sha1, + sign_plaintext +) +from .parameters import ( + prepare_form_encoded_body, + prepare_headers, + prepare_request_uri_query, +) + + +CONTENT_TYPE_FORM_URLENCODED = 'application/x-www-form-urlencoded' +CONTENT_TYPE_MULTI_PART = 'multipart/form-data' + + +class ClientAuth: + SIGNATURE_METHODS = { + SIGNATURE_HMAC_SHA1: sign_hmac_sha1, + SIGNATURE_RSA_SHA1: sign_rsa_sha1, + SIGNATURE_PLAINTEXT: sign_plaintext, + } + + @classmethod + def register_signature_method(cls, name, sign): + """Extend client signature methods. + + :param name: A string to represent signature method. + :param sign: A function to generate signature. + + The ``sign`` method accept 2 parameters:: + + def custom_sign_method(client, request): + # client is the instance of Client. + return 'your-signed-string' + + Client.register_signature_method('custom-name', custom_sign_method) + """ + cls.SIGNATURE_METHODS[name] = sign + + def __init__(self, client_id, client_secret=None, + token=None, token_secret=None, + redirect_uri=None, rsa_key=None, verifier=None, + signature_method=SIGNATURE_HMAC_SHA1, + signature_type=SIGNATURE_TYPE_HEADER, + realm=None, force_include_body=False): + self.client_id = client_id + self.client_secret = client_secret + self.token = token + self.token_secret = token_secret + self.redirect_uri = redirect_uri + self.signature_method = signature_method + self.signature_type = signature_type + self.rsa_key = rsa_key + self.verifier = verifier + self.realm = realm + self.force_include_body = force_include_body + + def get_oauth_signature(self, method, uri, headers, body): + """Get an OAuth signature to be used in signing a request + + To satisfy `section 3.4.1.2`_ item 2, if the request argument's + headers dict attribute contains a Host item, its value will + replace any netloc part of the request argument's uri attribute + value. + + .. _`section 3.4.1.2`: https://tools.ietf.org/html/rfc5849#section-3.4.1.2 + """ + sign = self.SIGNATURE_METHODS.get(self.signature_method) + if not sign: + raise ValueError('Invalid signature method.') + + request = OAuth1Request(method, uri, body=body, headers=headers) + return sign(self, request) + + def get_oauth_params(self, nonce, timestamp): + oauth_params = [ + ('oauth_nonce', nonce), + ('oauth_timestamp', timestamp), + ('oauth_version', '1.0'), + ('oauth_signature_method', self.signature_method), + ('oauth_consumer_key', self.client_id), + ] + if self.token: + oauth_params.append(('oauth_token', self.token)) + if self.redirect_uri: + oauth_params.append(('oauth_callback', self.redirect_uri)) + if self.verifier: + oauth_params.append(('oauth_verifier', self.verifier)) + return oauth_params + + def _render(self, uri, headers, body, oauth_params): + if self.signature_type == SIGNATURE_TYPE_HEADER: + headers = prepare_headers(oauth_params, headers, realm=self.realm) + elif self.signature_type == SIGNATURE_TYPE_BODY: + if CONTENT_TYPE_FORM_URLENCODED in headers.get('Content-Type', ''): + decoded_body = extract_params(body) or [] + body = prepare_form_encoded_body(oauth_params, decoded_body) + headers['Content-Type'] = CONTENT_TYPE_FORM_URLENCODED + elif self.signature_type == SIGNATURE_TYPE_QUERY: + uri = prepare_request_uri_query(oauth_params, uri) + else: + raise ValueError('Unknown signature type specified.') + return uri, headers, body + + def sign(self, method, uri, headers, body): + """Sign the HTTP request, add OAuth parameters and signature. + + :param method: HTTP method of the request. + :param uri: URI of the HTTP request. + :param body: Body payload of the HTTP request. + :param headers: Headers of the HTTP request. + :return: uri, headers, body + """ + nonce = generate_nonce() + timestamp = generate_timestamp() + if body is None: + body = b'' + + # transform int to str + timestamp = str(timestamp) + + if headers is None: + headers = {} + + oauth_params = self.get_oauth_params(nonce, timestamp) + + # https://datatracker.ietf.org/doc/html/draft-eaton-oauth-bodyhash-00.html + # include oauth_body_hash + if body and headers.get('Content-Type') != CONTENT_TYPE_FORM_URLENCODED: + oauth_body_hash = base64.b64encode(hashlib.sha1(body).digest()) + oauth_params.append(('oauth_body_hash', oauth_body_hash.decode('utf-8'))) + + uri, headers, body = self._render(uri, headers, body, oauth_params) + + sig = self.get_oauth_signature(method, uri, headers, body) + oauth_params.append(('oauth_signature', sig)) + + uri, headers, body = self._render(uri, headers, body, oauth_params) + return uri, headers, body + + def prepare(self, method, uri, headers, body): + """Add OAuth parameters to the request. + + Parameters may be included from the body if the content-type is + urlencoded, if no content type is set, a guess is made. + """ + content_type = to_native(headers.get('Content-Type', '')) + if self.signature_type == SIGNATURE_TYPE_BODY: + content_type = CONTENT_TYPE_FORM_URLENCODED + elif not content_type and extract_params(body): + content_type = CONTENT_TYPE_FORM_URLENCODED + + if CONTENT_TYPE_FORM_URLENCODED in content_type: + headers['Content-Type'] = CONTENT_TYPE_FORM_URLENCODED + uri, headers, body = self.sign(method, uri, headers, body) + elif self.force_include_body: + # To allow custom clients to work on non form encoded bodies. + uri, headers, body = self.sign(method, uri, headers, body) + else: + # Omit body data in the signing of non form-encoded requests + uri, headers, _ = self.sign(method, uri, headers, b'') + body = b'' + return uri, headers, body + + +def generate_nonce(): + return generate_token() + + +def generate_timestamp(): + return str(int(time.time())) diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/errors.py b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/errors.py new file mode 100644 index 00000000..93396fce --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/errors.py @@ -0,0 +1,89 @@ +""" + authlib.oauth1.rfc5849.errors + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + RFC5849 has no definition on errors. This module is designed by + Authlib based on OAuth 1.0a `Section 10`_ with some changes. + + .. _`Section 10`: https://oauth.net/core/1.0a/#rfc.section.10 +""" +from authlib.common.errors import AuthlibHTTPError +from authlib.common.security import is_secure_transport + + +class OAuth1Error(AuthlibHTTPError): + def __init__(self, description=None, uri=None, status_code=None): + super().__init__(None, description, uri, status_code) + + def get_headers(self): + """Get a list of headers.""" + return [ + ('Content-Type', 'application/x-www-form-urlencoded'), + ('Cache-Control', 'no-store'), + ('Pragma', 'no-cache') + ] + + +class InsecureTransportError(OAuth1Error): + error = 'insecure_transport' + description = 'OAuth 2 MUST utilize https.' + + @classmethod + def check(cls, uri): + if not is_secure_transport(uri): + raise cls() + + +class InvalidRequestError(OAuth1Error): + error = 'invalid_request' + + +class UnsupportedParameterError(OAuth1Error): + error = 'unsupported_parameter' + + +class UnsupportedSignatureMethodError(OAuth1Error): + error = 'unsupported_signature_method' + + +class MissingRequiredParameterError(OAuth1Error): + error = 'missing_required_parameter' + + def __init__(self, key): + description = f'missing "{key}" in parameters' + super().__init__(description=description) + + +class DuplicatedOAuthProtocolParameterError(OAuth1Error): + error = 'duplicated_oauth_protocol_parameter' + + +class InvalidClientError(OAuth1Error): + error = 'invalid_client' + status_code = 401 + + +class InvalidTokenError(OAuth1Error): + error = 'invalid_token' + description = 'Invalid or expired "oauth_token" in parameters' + status_code = 401 + + +class InvalidSignatureError(OAuth1Error): + error = 'invalid_signature' + status_code = 401 + + +class InvalidNonceError(OAuth1Error): + error = 'invalid_nonce' + status_code = 401 + + +class AccessDeniedError(OAuth1Error): + error = 'access_denied' + description = 'The resource owner or authorization server denied the request' + + +class MethodNotAllowedError(OAuth1Error): + error = 'method_not_allowed' + status_code = 405 diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/models.py b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/models.py new file mode 100644 index 00000000..c9f3ea61 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/models.py @@ -0,0 +1,108 @@ +class ClientMixin: + def get_default_redirect_uri(self): + """A method to get client default redirect_uri. For instance, the + database table for client has a column called ``default_redirect_uri``:: + + def get_default_redirect_uri(self): + return self.default_redirect_uri + + :return: A URL string + """ + raise NotImplementedError() + + def get_client_secret(self): + """A method to return the client_secret of this client. For instance, + the database table has a column called ``client_secret``:: + + def get_client_secret(self): + return self.client_secret + """ + raise NotImplementedError() + + def get_rsa_public_key(self): + """A method to get the RSA public key for RSA-SHA1 signature method. + For instance, the value is saved on column ``rsa_public_key``:: + + def get_rsa_public_key(self): + return self.rsa_public_key + """ + raise NotImplementedError() + + +class TokenCredentialMixin: + def get_oauth_token(self): + """A method to get the value of ``oauth_token``. For instance, the + database table has a column called ``oauth_token``:: + + def get_oauth_token(self): + return self.oauth_token + + :return: A string + """ + raise NotImplementedError() + + def get_oauth_token_secret(self): + """A method to get the value of ``oauth_token_secret``. For instance, + the database table has a column called ``oauth_token_secret``:: + + def get_oauth_token_secret(self): + return self.oauth_token_secret + + :return: A string + """ + raise NotImplementedError() + + +class TemporaryCredentialMixin(TokenCredentialMixin): + def get_client_id(self): + """A method to get the client_id associated with this credential. + For instance, the table in the database has a column ``client_id``:: + + def get_client_id(self): + return self.client_id + """ + raise NotImplementedError() + + def get_redirect_uri(self): + """A method to get temporary credential's ``oauth_callback``. + For instance, the database table for temporary credential has a + column called ``oauth_callback``:: + + def get_redirect_uri(self): + return self.oauth_callback + + :return: A URL string + """ + raise NotImplementedError() + + def check_verifier(self, verifier): + """A method to check if the given verifier matches this temporary + credential. For instance that this temporary credential has recorded + the value in database as column ``oauth_verifier``:: + + def check_verifier(self, verifier): + return self.oauth_verifier == verifier + + :return: Boolean + """ + raise NotImplementedError() + + +class TemporaryCredential(dict, TemporaryCredentialMixin): + def get_client_id(self): + return self.get('client_id') + + def get_user_id(self): + return self.get('user_id') + + def get_redirect_uri(self): + return self.get('oauth_callback') + + def check_verifier(self, verifier): + return self.get('oauth_verifier') == verifier + + def get_oauth_token(self): + return self.get('oauth_token') + + def get_oauth_token_secret(self): + return self.get('oauth_token_secret') diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/parameters.py b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/parameters.py new file mode 100644 index 00000000..0e64e5c6 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/parameters.py @@ -0,0 +1,101 @@ +""" + authlib.spec.rfc5849.parameters + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + This module contains methods related to `section 3.5`_ of the OAuth 1.0a spec. + + .. _`section 3.5`: https://tools.ietf.org/html/rfc5849#section-3.5 +""" +from authlib.common.urls import urlparse, url_encode, extract_params +from .util import escape + + +def prepare_headers(oauth_params, headers=None, realm=None): + """**Prepare the Authorization header.** + Per `section 3.5.1`_ of the spec. + + Protocol parameters can be transmitted using the HTTP "Authorization" + header field as defined by `RFC2617`_ with the auth-scheme name set to + "OAuth" (case insensitive). + + For example:: + + Authorization: OAuth realm="Photos", + oauth_consumer_key="dpf43f3p2l4k3l03", + oauth_signature_method="HMAC-SHA1", + oauth_timestamp="137131200", + oauth_nonce="wIjqoS", + oauth_callback="http%3A%2F%2Fprinter.example.com%2Fready", + oauth_signature="74KNZJeDHnMBp0EMJ9ZHt%2FXKycU%3D", + oauth_version="1.0" + + .. _`section 3.5.1`: https://tools.ietf.org/html/rfc5849#section-3.5.1 + .. _`RFC2617`: https://tools.ietf.org/html/rfc2617 + """ + headers = headers or {} + + # step 1, 2, 3 in Section 3.5.1 + header_parameters = ', '.join([ + f'{escape(k)}="{escape(v)}"' for k, v in oauth_params + if k.startswith('oauth_') + ]) + + # 4. The OPTIONAL "realm" parameter MAY be added and interpreted per + # `RFC2617 section 1.2`_. + # + # .. _`RFC2617 section 1.2`: https://tools.ietf.org/html/rfc2617#section-1.2 + if realm: + # NOTE: realm should *not* be escaped + header_parameters = f'realm="{realm}", ' + header_parameters + + # the auth-scheme name set to "OAuth" (case insensitive). + headers['Authorization'] = f'OAuth {header_parameters}' + return headers + + +def _append_params(oauth_params, params): + """Append OAuth params to an existing set of parameters. + + Both params and oauth_params is must be lists of 2-tuples. + + Per `section 3.5.2`_ and `3.5.3`_ of the spec. + + .. _`section 3.5.2`: https://tools.ietf.org/html/rfc5849#section-3.5.2 + .. _`3.5.3`: https://tools.ietf.org/html/rfc5849#section-3.5.3 + + """ + merged = list(params) + merged.extend(oauth_params) + # The request URI / entity-body MAY include other request-specific + # parameters, in which case, the protocol parameters SHOULD be appended + # following the request-specific parameters, properly separated by an "&" + # character (ASCII code 38) + merged.sort(key=lambda i: i[0].startswith('oauth_')) + return merged + + +def prepare_form_encoded_body(oauth_params, body): + """Prepare the Form-Encoded Body. + + Per `section 3.5.2`_ of the spec. + + .. _`section 3.5.2`: https://tools.ietf.org/html/rfc5849#section-3.5.2 + + """ + # append OAuth params to the existing body + return url_encode(_append_params(oauth_params, body)) + + +def prepare_request_uri_query(oauth_params, uri): + """Prepare the Request URI Query. + + Per `section 3.5.3`_ of the spec. + + .. _`section 3.5.3`: https://tools.ietf.org/html/rfc5849#section-3.5.3 + + """ + # append OAuth params to the existing set of query components + sch, net, path, par, query, fra = urlparse.urlparse(uri) + query = url_encode( + _append_params(oauth_params, extract_params(query) or [])) + return urlparse.urlunparse((sch, net, path, par, query, fra)) diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/resource_protector.py b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/resource_protector.py new file mode 100644 index 00000000..2b5d7819 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/resource_protector.py @@ -0,0 +1,41 @@ +from .base_server import BaseServer +from .wrapper import OAuth1Request +from .errors import ( + MissingRequiredParameterError, + InvalidClientError, + InvalidTokenError, +) + + +class ResourceProtector(BaseServer): + def validate_request(self, method, uri, body, headers): + request = OAuth1Request(method, uri, body, headers) + + if not request.client_id: + raise MissingRequiredParameterError('oauth_consumer_key') + + client = self.get_client_by_id(request.client_id) + if not client: + raise InvalidClientError() + request.client = client + + if not request.token: + raise MissingRequiredParameterError('oauth_token') + + token = self.get_token_credential(request) + if not token: + raise InvalidTokenError() + + request.credential = token + self.validate_timestamp_and_nonce(request) + self.validate_oauth_signature(request) + return request + + def get_token_credential(self, request): + """Fetch the token credential from data store like a database, + framework should implement this function. + + :param request: OAuth1Request instance + :return: Token model instance + """ + raise NotImplementedError() diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/rsa.py b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/rsa.py new file mode 100644 index 00000000..3785b0f7 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/rsa.py @@ -0,0 +1,29 @@ +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives.serialization import ( + load_pem_private_key, load_pem_public_key +) +from cryptography.hazmat.primitives.asymmetric import padding +from cryptography.exceptions import InvalidSignature +from authlib.common.encoding import to_bytes + + +def sign_sha1(msg, rsa_private_key): + key = load_pem_private_key( + to_bytes(rsa_private_key), + password=None, + backend=default_backend() + ) + return key.sign(msg, padding.PKCS1v15(), hashes.SHA1()) + + +def verify_sha1(sig, msg, rsa_public_key): + key = load_pem_public_key( + to_bytes(rsa_public_key), + backend=default_backend() + ) + try: + key.verify(sig, msg, padding.PKCS1v15(), hashes.SHA1()) + return True + except InvalidSignature: + return False diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/signature.py b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/signature.py new file mode 100644 index 00000000..bfb87fee --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/signature.py @@ -0,0 +1,386 @@ +""" + authlib.oauth1.rfc5849.signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + This module represents a direct implementation of `section 3.4`_ of the spec. + + .. _`section 3.4`: https://tools.ietf.org/html/rfc5849#section-3.4 +""" +import binascii +import hashlib +import hmac +from authlib.common.urls import urlparse +from authlib.common.encoding import to_unicode, to_bytes +from .util import escape, unescape + +SIGNATURE_HMAC_SHA1 = "HMAC-SHA1" +SIGNATURE_RSA_SHA1 = "RSA-SHA1" +SIGNATURE_PLAINTEXT = "PLAINTEXT" + +SIGNATURE_TYPE_HEADER = 'HEADER' +SIGNATURE_TYPE_QUERY = 'QUERY' +SIGNATURE_TYPE_BODY = 'BODY' + + +def construct_base_string(method, uri, params, host=None): + """Generate signature base string from request, per `Section 3.4.1`_. + + For example, the HTTP request:: + + POST /request?b5=%3D%253D&a3=a&c%40=&a2=r%20b HTTP/1.1 + Host: example.com + Content-Type: application/x-www-form-urlencoded + Authorization: OAuth realm="Example", + oauth_consumer_key="9djdj82h48djs9d2", + oauth_token="kkk9d7dh3k39sjv7", + oauth_signature_method="HMAC-SHA1", + oauth_timestamp="137131201", + oauth_nonce="7d8f3e4a", + oauth_signature="bYT5CMsGcbgUdFHObYMEfcx6bsw%3D" + + c2&a3=2+q + + is represented by the following signature base string (line breaks + are for display purposes only):: + + POST&http%3A%2F%2Fexample.com%2Frequest&a2%3Dr%2520b%26a3%3D2%2520q + %26a3%3Da%26b5%3D%253D%25253D%26c%2540%3D%26c2%3D%26oauth_consumer_ + key%3D9djdj82h48djs9d2%26oauth_nonce%3D7d8f3e4a%26oauth_signature_m + ethod%3DHMAC-SHA1%26oauth_timestamp%3D137131201%26oauth_token%3Dkkk + 9d7dh3k39sjv7 + + .. _`Section 3.4.1`: https://tools.ietf.org/html/rfc5849#section-3.4.1 + """ + + # Create base string URI per Section 3.4.1.2 + base_string_uri = normalize_base_string_uri(uri, host) + + # Cleanup parameter sources per Section 3.4.1.3.1 + unescaped_params = [] + for k, v in params: + # The "oauth_signature" parameter MUST be excluded from the signature + if k in ('oauth_signature', 'realm'): + continue + + # ensure oauth params are unescaped + if k.startswith('oauth_'): + v = unescape(v) + unescaped_params.append((k, v)) + + # Normalize parameters per Section 3.4.1.3.2 + normalized_params = normalize_parameters(unescaped_params) + + # construct base string + return '&'.join([ + escape(method.upper()), + escape(base_string_uri), + escape(normalized_params), + ]) + + +def normalize_base_string_uri(uri, host=None): + """Normalize Base String URI per `Section 3.4.1.2`_. + + For example, the HTTP request:: + + GET /r%20v/X?id=123 HTTP/1.1 + Host: EXAMPLE.COM:80 + + is represented by the base string URI: "http://example.com/r%20v/X". + + In another example, the HTTPS request:: + + GET /?q=1 HTTP/1.1 + Host: www.example.net:8080 + + is represented by the base string URI: "https://www.example.net:8080/". + + .. _`Section 3.4.1.2`: https://tools.ietf.org/html/rfc5849#section-3.4.1.2 + + The host argument overrides the netloc part of the uri argument. + """ + uri = to_unicode(uri) + scheme, netloc, path, params, query, fragment = urlparse.urlparse(uri) + + # The scheme, authority, and path of the request resource URI `RFC3986` + # are included by constructing an "http" or "https" URI representing + # the request resource (without the query or fragment) as follows: + # + # .. _`RFC3986`: https://tools.ietf.org/html/rfc3986 + + if not scheme or not netloc: + raise ValueError('uri must include a scheme and netloc') + + # Per `RFC 2616 section 5.1.2`_: + # + # Note that the absolute path cannot be empty; if none is present in + # the original URI, it MUST be given as "/" (the server root). + # + # .. _`RFC 2616 section 5.1.2`: https://tools.ietf.org/html/rfc2616#section-5.1.2 + if not path: + path = '/' + + # 1. The scheme and host MUST be in lowercase. + scheme = scheme.lower() + netloc = netloc.lower() + + # 2. The host and port values MUST match the content of the HTTP + # request "Host" header field. + if host is not None: + netloc = host.lower() + + # 3. The port MUST be included if it is not the default port for the + # scheme, and MUST be excluded if it is the default. Specifically, + # the port MUST be excluded when making an HTTP request `RFC2616`_ + # to port 80 or when making an HTTPS request `RFC2818`_ to port 443. + # All other non-default port numbers MUST be included. + # + # .. _`RFC2616`: https://tools.ietf.org/html/rfc2616 + # .. _`RFC2818`: https://tools.ietf.org/html/rfc2818 + default_ports = ( + ('http', '80'), + ('https', '443'), + ) + if ':' in netloc: + host, port = netloc.split(':', 1) + if (scheme, port) in default_ports: + netloc = host + + return urlparse.urlunparse((scheme, netloc, path, params, '', '')) + + +def normalize_parameters(params): + """Normalize parameters per `Section 3.4.1.3.2`_. + + For example, the list of parameters from the previous section would + be normalized as follows: + + Encoded:: + + +------------------------+------------------+ + | Name | Value | + +------------------------+------------------+ + | b5 | %3D%253D | + | a3 | a | + | c%40 | | + | a2 | r%20b | + | oauth_consumer_key | 9djdj82h48djs9d2 | + | oauth_token | kkk9d7dh3k39sjv7 | + | oauth_signature_method | HMAC-SHA1 | + | oauth_timestamp | 137131201 | + | oauth_nonce | 7d8f3e4a | + | c2 | | + | a3 | 2%20q | + +------------------------+------------------+ + + Sorted:: + + +------------------------+------------------+ + | Name | Value | + +------------------------+------------------+ + | a2 | r%20b | + | a3 | 2%20q | + | a3 | a | + | b5 | %3D%253D | + | c%40 | | + | c2 | | + | oauth_consumer_key | 9djdj82h48djs9d2 | + | oauth_nonce | 7d8f3e4a | + | oauth_signature_method | HMAC-SHA1 | + | oauth_timestamp | 137131201 | + | oauth_token | kkk9d7dh3k39sjv7 | + +------------------------+------------------+ + + Concatenated Pairs:: + + +-------------------------------------+ + | Name=Value | + +-------------------------------------+ + | a2=r%20b | + | a3=2%20q | + | a3=a | + | b5=%3D%253D | + | c%40= | + | c2= | + | oauth_consumer_key=9djdj82h48djs9d2 | + | oauth_nonce=7d8f3e4a | + | oauth_signature_method=HMAC-SHA1 | + | oauth_timestamp=137131201 | + | oauth_token=kkk9d7dh3k39sjv7 | + +-------------------------------------+ + + and concatenated together into a single string (line breaks are for + display purposes only):: + + a2=r%20b&a3=2%20q&a3=a&b5=%3D%253D&c%40=&c2=&oauth_consumer_key=9dj + dj82h48djs9d2&oauth_nonce=7d8f3e4a&oauth_signature_method=HMAC-SHA1 + &oauth_timestamp=137131201&oauth_token=kkk9d7dh3k39sjv7 + + .. _`Section 3.4.1.3.2`: https://tools.ietf.org/html/rfc5849#section-3.4.1.3.2 + """ + + # 1. First, the name and value of each parameter are encoded + # (`Section 3.6`_). + # + # .. _`Section 3.6`: https://tools.ietf.org/html/rfc5849#section-3.6 + key_values = [(escape(k), escape(v)) for k, v in params] + + # 2. The parameters are sorted by name, using ascending byte value + # ordering. If two or more parameters share the same name, they + # are sorted by their value. + key_values.sort() + + # 3. The name of each parameter is concatenated to its corresponding + # value using an "=" character (ASCII code 61) as a separator, even + # if the value is empty. + parameter_parts = [f'{k}={v}' for k, v in key_values] + + # 4. The sorted name/value pairs are concatenated together into a + # single string by using an "&" character (ASCII code 38) as + # separator. + return '&'.join(parameter_parts) + + +def generate_signature_base_string(request): + """Generate signature base string from request.""" + host = request.headers.get('Host', None) + return construct_base_string( + request.method, request.uri, request.params, host) + + +def hmac_sha1_signature(base_string, client_secret, token_secret): + """Generate signature via HMAC-SHA1 method, per `Section 3.4.2`_. + + The "HMAC-SHA1" signature method uses the HMAC-SHA1 signature + algorithm as defined in `RFC2104`_:: + + digest = HMAC-SHA1 (key, text) + + .. _`RFC2104`: https://tools.ietf.org/html/rfc2104 + .. _`Section 3.4.2`: https://tools.ietf.org/html/rfc5849#section-3.4.2 + """ + + # The HMAC-SHA1 function variables are used in following way: + + # text is set to the value of the signature base string from + # `Section 3.4.1.1`_. + # + # .. _`Section 3.4.1.1`: https://tools.ietf.org/html/rfc5849#section-3.4.1.1 + text = base_string + + # key is set to the concatenated values of: + # 1. The client shared-secret, after being encoded (`Section 3.6`_). + # + # .. _`Section 3.6`: https://tools.ietf.org/html/rfc5849#section-3.6 + key = escape(client_secret or '') + + # 2. An "&" character (ASCII code 38), which MUST be included + # even when either secret is empty. + key += '&' + + # 3. The token shared-secret, after being encoded (`Section 3.6`_). + # + # .. _`Section 3.6`: https://tools.ietf.org/html/rfc5849#section-3.6 + key += escape(token_secret or '') + + signature = hmac.new(to_bytes(key), to_bytes(text), hashlib.sha1) + + # digest is used to set the value of the "oauth_signature" protocol + # parameter, after the result octet string is base64-encoded + # per `RFC2045, Section 6.8`. + # + # .. _`RFC2045, Section 6.8`: https://tools.ietf.org/html/rfc2045#section-6.8 + sig = binascii.b2a_base64(signature.digest())[:-1] + return to_unicode(sig) + + +def rsa_sha1_signature(base_string, rsa_private_key): + """Generate signature via RSA-SHA1 method, per `Section 3.4.3`_. + + The "RSA-SHA1" signature method uses the RSASSA-PKCS1-v1_5 signature + algorithm as defined in `RFC3447, Section 8.2`_ (also known as + PKCS#1), using SHA-1 as the hash function for EMSA-PKCS1-v1_5. To + use this method, the client MUST have established client credentials + with the server that included its RSA public key (in a manner that is + beyond the scope of this specification). + + .. _`Section 3.4.3`: https://tools.ietf.org/html/rfc5849#section-3.4.3 + .. _`RFC3447, Section 8.2`: https://tools.ietf.org/html/rfc3447#section-8.2 + """ + from .rsa import sign_sha1 + base_string = to_bytes(base_string) + s = sign_sha1(to_bytes(base_string), rsa_private_key) + sig = binascii.b2a_base64(s)[:-1] + return to_unicode(sig) + + +def plaintext_signature(client_secret, token_secret): + """Generate signature via PLAINTEXT method, per `Section 3.4.4`_. + + The "PLAINTEXT" method does not employ a signature algorithm. It + MUST be used with a transport-layer mechanism such as TLS or SSL (or + sent over a secure channel with equivalent protections). It does not + utilize the signature base string or the "oauth_timestamp" and + "oauth_nonce" parameters. + + .. _`Section 3.4.4`: https://tools.ietf.org/html/rfc5849#section-3.4.4 + """ + + # The "oauth_signature" protocol parameter is set to the concatenated + # value of: + + # 1. The client shared-secret, after being encoded (`Section 3.6`_). + # + # .. _`Section 3.6`: https://tools.ietf.org/html/rfc5849#section-3.6 + signature = escape(client_secret or '') + + # 2. An "&" character (ASCII code 38), which MUST be included even + # when either secret is empty. + signature += '&' + + # 3. The token shared-secret, after being encoded (`Section 3.6`_). + # + # .. _`Section 3.6`: https://tools.ietf.org/html/rfc5849#section-3.6 + signature += escape(token_secret or '') + + return signature + + +def sign_hmac_sha1(client, request): + """Sign a HMAC-SHA1 signature.""" + base_string = generate_signature_base_string(request) + return hmac_sha1_signature( + base_string, client.client_secret, client.token_secret) + + +def sign_rsa_sha1(client, request): + """Sign a RSASSA-PKCS #1 v1.5 base64 encoded signature.""" + base_string = generate_signature_base_string(request) + return rsa_sha1_signature(base_string, client.rsa_key) + + +def sign_plaintext(client, request): + """Sign a PLAINTEXT signature.""" + return plaintext_signature(client.client_secret, client.token_secret) + + +def verify_hmac_sha1(request): + """Verify a HMAC-SHA1 signature.""" + base_string = generate_signature_base_string(request) + sig = hmac_sha1_signature( + base_string, request.client_secret, request.token_secret) + return hmac.compare_digest(sig, request.signature) + + +def verify_rsa_sha1(request): + """Verify a RSASSA-PKCS #1 v1.5 base64 encoded signature.""" + from .rsa import verify_sha1 + base_string = generate_signature_base_string(request) + sig = binascii.a2b_base64(to_bytes(request.signature)) + return verify_sha1(sig, to_bytes(base_string), request.rsa_public_key) + + +def verify_plaintext(request): + """Verify a PLAINTEXT signature.""" + sig = plaintext_signature(request.client_secret, request.token_secret) + return hmac.compare_digest(sig, request.signature) diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/util.py b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/util.py new file mode 100644 index 00000000..9383e22e --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/util.py @@ -0,0 +1,9 @@ +from authlib.common.urls import quote, unquote + + +def escape(s): + return quote(s, safe=b'~') + + +def unescape(s): + return unquote(s) diff --git a/.venv/Lib/site-packages/authlib/oauth1/rfc5849/wrapper.py b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/wrapper.py new file mode 100644 index 00000000..c03687ed --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth1/rfc5849/wrapper.py @@ -0,0 +1,129 @@ +from urllib.request import parse_keqv_list, parse_http_list +from authlib.common.urls import ( + urlparse, extract_params, url_decode, +) +from .signature import ( + SIGNATURE_TYPE_QUERY, + SIGNATURE_TYPE_BODY, + SIGNATURE_TYPE_HEADER +) +from .errors import ( + InsecureTransportError, + DuplicatedOAuthProtocolParameterError +) +from .util import unescape + + +class OAuth1Request: + def __init__(self, method, uri, body=None, headers=None): + InsecureTransportError.check(uri) + self.method = method + self.uri = uri + self.body = body + self.headers = headers or {} + + # states namespaces + self.client = None + self.credential = None + self.user = None + + self.query = urlparse.urlparse(uri).query + self.query_params = url_decode(self.query) + self.body_params = extract_params(body) or [] + + self.auth_params, self.realm = _parse_authorization_header(headers) + self.signature_type, self.oauth_params = _parse_oauth_params( + self.query_params, self.body_params, self.auth_params) + + params = [] + params.extend(self.query_params) + params.extend(self.body_params) + params.extend(self.auth_params) + self.params = params + + @property + def client_id(self): + return self.oauth_params.get('oauth_consumer_key') + + @property + def client_secret(self): + if self.client: + return self.client.get_client_secret() + + @property + def rsa_public_key(self): + if self.client: + return self.client.get_rsa_public_key() + + @property + def timestamp(self): + return self.oauth_params.get('oauth_timestamp') + + @property + def redirect_uri(self): + return self.oauth_params.get('oauth_callback') + + @property + def signature(self): + return self.oauth_params.get('oauth_signature') + + @property + def signature_method(self): + return self.oauth_params.get('oauth_signature_method') + + @property + def token(self): + return self.oauth_params.get('oauth_token') + + @property + def token_secret(self): + if self.credential: + return self.credential.get_oauth_token_secret() + + +def _filter_oauth(params): + for k, v in params: + if k.startswith('oauth_'): + yield (k, v) + + +def _parse_authorization_header(headers): + """Parse an OAuth authorization header into a list of 2-tuples""" + authorization_header = headers.get('Authorization') + if not authorization_header: + return [], None + + auth_scheme = 'oauth ' + if authorization_header.lower().startswith(auth_scheme): + items = parse_http_list(authorization_header[len(auth_scheme):]) + try: + items = parse_keqv_list(items).items() + auth_params = [(unescape(k), unescape(v)) for k, v in items] + realm = dict(auth_params).get('realm') + return auth_params, realm + except (IndexError, ValueError): + pass + raise ValueError('Malformed authorization header') + + +def _parse_oauth_params(query_params, body_params, auth_params): + oauth_params_set = [ + (SIGNATURE_TYPE_QUERY, list(_filter_oauth(query_params))), + (SIGNATURE_TYPE_BODY, list(_filter_oauth(body_params))), + (SIGNATURE_TYPE_HEADER, list(_filter_oauth(auth_params))) + ] + oauth_params_set = [params for params in oauth_params_set if params[1]] + if len(oauth_params_set) > 1: + found_types = [p[0] for p in oauth_params_set] + raise DuplicatedOAuthProtocolParameterError( + '"oauth_" params must come from only 1 signature type ' + 'but were found in {}'.format(','.join(found_types)) + ) + + if oauth_params_set: + signature_type = oauth_params_set[0][0] + oauth_params = dict(oauth_params_set[0][1]) + else: + signature_type = None + oauth_params = {} + return signature_type, oauth_params diff --git a/.venv/Lib/site-packages/authlib/oauth2/__init__.py b/.venv/Lib/site-packages/authlib/oauth2/__init__.py new file mode 100644 index 00000000..05fdf30b --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/__init__.py @@ -0,0 +1,16 @@ +from .base import OAuth2Error +from .auth import ClientAuth, TokenAuth +from .client import OAuth2Client +from .rfc6749 import ( + OAuth2Request, + JsonRequest, + AuthorizationServer, + ClientAuthentication, + ResourceProtector, +) + +__all__ = [ + 'OAuth2Error', 'ClientAuth', 'TokenAuth', 'OAuth2Client', + 'OAuth2Request', 'JsonRequest', 'AuthorizationServer', + 'ClientAuthentication', 'ResourceProtector', +] diff --git a/.venv/Lib/site-packages/authlib/oauth2/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b0f325d2ee68c77f76fb759f8e1b2131fbcd5d43 GIT binary patch literal 692 zcmbu6O>5gQ7{?{svEw)?d+D{XTk&Bnl+n^L24fp5rF0|hb`S>R$WK!d$?7C0u$}fT zcG+o{vJcSjkz>%cr``g+b(c!cLMd#gNe@5%kM+FCI`8#5$gbb-F5ny^bm^Ss^8SeH zz7^k5iAv0ozyxEbJ?;sg_#z-dnA3? zGCV?QbY(lD6r1Gzt8sn0^;RjVQqOc=a|TuIzM1$~j-YbV#&s8Qi{rFqdJDe~pU0qU zlk96*EuF_MM=JKUsF|#eKutiI)w{~J0i(^CdDsUn$BM!SC2OFy9U@k~9ZdxeEr-w{ za%elm4(`vX#NserF~OkF&}5mQu&wWMO-P&jG&M}5PU!Z|v)z9dGf|!woagy3bZu*+ zn@?|^XH=G~8fG8m$?;x6M>^|+05JdsnnFb(+n7K#$qv{c)2xQ4XEvx9g3jD1oDDXm z6I+{k&MH>t`Nr9ooAwJK%Q1(SYSp%JPoaNU%zcdU46RM?+YGHw|7J7vWP0D`UWmOp T`d>T<5?f`7Z;{*Tksa_BH88k) literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/__pycache__/auth.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/__pycache__/auth.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..94dd573848f5fbb8677ec4fdf4162ef3a97b9ffb GIT binary patch literal 5317 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 Pk*QyC`nNOIJo|qE+iJur literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/__pycache__/client.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/__pycache__/client.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ca39b199f541db2fca4fadb1184c532c3b539336 GIT binary patch literal 19946 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 QJN_D5GZ@UifKA%}1?>Ty*Z=?k literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/auth.py b/.venv/Lib/site-packages/authlib/oauth2/auth.py new file mode 100644 index 00000000..e4ad1804 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/auth.py @@ -0,0 +1,106 @@ +import base64 +from urllib.parse import quote +from authlib.common.urls import add_params_to_qs, add_params_to_uri +from authlib.common.encoding import to_bytes, to_native +from .rfc6749 import OAuth2Token +from .rfc6750 import add_bearer_token + + +def encode_client_secret_basic(client, method, uri, headers, body): + text = f'{quote(client.client_id)}:{quote(client.client_secret)}' + auth = to_native(base64.b64encode(to_bytes(text, 'latin1'))) + headers['Authorization'] = f'Basic {auth}' + return uri, headers, body + + +def encode_client_secret_post(client, method, uri, headers, body): + body = add_params_to_qs(body or '', [ + ('client_id', client.client_id), + ('client_secret', client.client_secret or '') + ]) + if 'Content-Length' in headers: + headers['Content-Length'] = str(len(body)) + return uri, headers, body + + +def encode_none(client, method, uri, headers, body): + if method == 'GET': + uri = add_params_to_uri(uri, [('client_id', client.client_id)]) + return uri, headers, body + body = add_params_to_qs(body, [('client_id', client.client_id)]) + if 'Content-Length' in headers: + headers['Content-Length'] = str(len(body)) + return uri, headers, body + + +class ClientAuth: + """Attaches OAuth Client Information to HTTP requests. + + :param client_id: Client ID, which you get from client registration. + :param client_secret: Client Secret, which you get from registration. + :param auth_method: Client auth method for token endpoint. The supported + methods for now: + + * client_secret_basic (default) + * client_secret_post + * none + """ + DEFAULT_AUTH_METHODS = { + 'client_secret_basic': encode_client_secret_basic, + 'client_secret_post': encode_client_secret_post, + 'none': encode_none, + } + + def __init__(self, client_id, client_secret, auth_method=None): + if auth_method is None: + auth_method = 'client_secret_basic' + + self.client_id = client_id + self.client_secret = client_secret + + if auth_method in self.DEFAULT_AUTH_METHODS: + auth_method = self.DEFAULT_AUTH_METHODS[auth_method] + + self.auth_method = auth_method + + def prepare(self, method, uri, headers, body): + return self.auth_method(self, method, uri, headers, body) + + +class TokenAuth: + """Attach token information to HTTP requests. + + :param token: A dict or OAuth2Token instance of an OAuth 2.0 token + :param token_placement: The placement of the token, default is ``header``, + available choices: + + * header (default) + * body + * uri + """ + DEFAULT_TOKEN_TYPE = 'bearer' + SIGN_METHODS = { + 'bearer': add_bearer_token + } + + def __init__(self, token, token_placement='header', client=None): + self.token = OAuth2Token.from_dict(token) + self.token_placement = token_placement + self.client = client + self.hooks = set() + + def set_token(self, token): + self.token = OAuth2Token.from_dict(token) + + def prepare(self, uri, headers, body): + token_type = self.token.get('token_type', self.DEFAULT_TOKEN_TYPE) + sign = self.SIGN_METHODS[token_type.lower()] + uri, headers, body = sign( + self.token['access_token'], + uri, headers, body, + self.token_placement) + + for hook in self.hooks: + uri, headers, body = hook(uri, headers, body) + + return uri, headers, body diff --git a/.venv/Lib/site-packages/authlib/oauth2/base.py b/.venv/Lib/site-packages/authlib/oauth2/base.py new file mode 100644 index 00000000..9bcb15f8 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/base.py @@ -0,0 +1,26 @@ +from authlib.common.errors import AuthlibHTTPError +from authlib.common.urls import add_params_to_uri + + +class OAuth2Error(AuthlibHTTPError): + def __init__(self, description=None, uri=None, + status_code=None, state=None, + redirect_uri=None, redirect_fragment=False, error=None): + super().__init__(error, description, uri, status_code) + self.state = state + self.redirect_uri = redirect_uri + self.redirect_fragment = redirect_fragment + + def get_body(self): + """Get a list of body.""" + error = super().get_body() + if self.state: + error.append(('state', self.state)) + return error + + def __call__(self, uri=None): + if self.redirect_uri: + params = self.get_body() + loc = add_params_to_uri(self.redirect_uri, params, self.redirect_fragment) + return 302, '', [('Location', loc)] + return super().__call__(uri=uri) diff --git a/.venv/Lib/site-packages/authlib/oauth2/client.py b/.venv/Lib/site-packages/authlib/oauth2/client.py new file mode 100644 index 00000000..7adb0c8e --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/client.py @@ -0,0 +1,438 @@ +from authlib.common.security import generate_token +from authlib.common.urls import url_decode +from .rfc6749.parameters import ( + prepare_grant_uri, + prepare_token_request, + parse_authorization_code_response, + parse_implicit_response, +) +from .rfc7009 import prepare_revoke_token_request +from .rfc7636 import create_s256_code_challenge +from .auth import TokenAuth, ClientAuth +from .base import OAuth2Error + +DEFAULT_HEADERS = { + 'Accept': 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' +} + + +class OAuth2Client: + """Construct a new OAuth 2 protocol client. + + :param session: Requests session object to communicate with + authorization server. + :param client_id: Client ID, which you get from client registration. + :param client_secret: Client Secret, which you get from registration. + :param token_endpoint_auth_method: client authentication method for + token endpoint. + :param revocation_endpoint_auth_method: client authentication method for + revocation endpoint. + :param scope: Scope that you needed to access user resources. + :param state: Shared secret to prevent CSRF attack. + :param redirect_uri: Redirect URI you registered as callback. + :param code_challenge_method: PKCE method name, only S256 is supported. + :param token: A dict of token attributes such as ``access_token``, + ``token_type`` and ``expires_at``. + :param token_placement: The place to put token in HTTP request. Available + values: "header", "body", "uri". + :param update_token: A function for you to update token. It accept a + :class:`OAuth2Token` as parameter. + """ + client_auth_class = ClientAuth + token_auth_class = TokenAuth + oauth_error_class = OAuth2Error + + EXTRA_AUTHORIZE_PARAMS = ( + 'response_mode', 'nonce', 'prompt', 'login_hint' + ) + SESSION_REQUEST_PARAMS = [] + + def __init__(self, session, client_id=None, client_secret=None, + token_endpoint_auth_method=None, + revocation_endpoint_auth_method=None, + scope=None, state=None, redirect_uri=None, code_challenge_method=None, + token=None, token_placement='header', update_token=None, **metadata): + + self.session = session + self.client_id = client_id + self.client_secret = client_secret + self.state = state + + if token_endpoint_auth_method is None: + if client_secret: + token_endpoint_auth_method = 'client_secret_basic' + else: + token_endpoint_auth_method = 'none' + + self.token_endpoint_auth_method = token_endpoint_auth_method + + if revocation_endpoint_auth_method is None: + if client_secret: + revocation_endpoint_auth_method = 'client_secret_basic' + else: + revocation_endpoint_auth_method = 'none' + + self.revocation_endpoint_auth_method = revocation_endpoint_auth_method + + self.scope = scope + self.redirect_uri = redirect_uri + self.code_challenge_method = code_challenge_method + + self.token_auth = self.token_auth_class(token, token_placement, self) + self.update_token = update_token + + token_updater = metadata.pop('token_updater', None) + if token_updater: + raise ValueError('update token has been redesigned, checkout the documentation') + + self.metadata = metadata + + self.compliance_hook = { + 'access_token_response': set(), + 'refresh_token_request': set(), + 'refresh_token_response': set(), + 'revoke_token_request': set(), + 'introspect_token_request': set(), + } + self._auth_methods = {} + + def register_client_auth_method(self, auth): + """Extend client authenticate for token endpoint. + + :param auth: an instance to sign the request + """ + if isinstance(auth, tuple): + self._auth_methods[auth[0]] = auth[1] + else: + self._auth_methods[auth.name] = auth + + def client_auth(self, auth_method): + if isinstance(auth_method, str) and auth_method in self._auth_methods: + auth_method = self._auth_methods[auth_method] + return self.client_auth_class( + client_id=self.client_id, + client_secret=self.client_secret, + auth_method=auth_method, + ) + + @property + def token(self): + return self.token_auth.token + + @token.setter + def token(self, token): + self.token_auth.set_token(token) + + def create_authorization_url(self, url, state=None, code_verifier=None, **kwargs): + """Generate an authorization URL and state. + + :param url: Authorization endpoint url, must be HTTPS. + :param state: An optional state string for CSRF protection. If not + given it will be generated for you. + :param code_verifier: An optional code_verifier for code challenge. + :param kwargs: Extra parameters to include. + :return: authorization_url, state + """ + if state is None: + state = generate_token() + + response_type = self.metadata.get('response_type', 'code') + response_type = kwargs.pop('response_type', response_type) + if 'redirect_uri' not in kwargs: + kwargs['redirect_uri'] = self.redirect_uri + if 'scope' not in kwargs: + kwargs['scope'] = self.scope + + if code_verifier and response_type == 'code' and self.code_challenge_method == 'S256': + kwargs['code_challenge'] = create_s256_code_challenge(code_verifier) + kwargs['code_challenge_method'] = self.code_challenge_method + + for k in self.EXTRA_AUTHORIZE_PARAMS: + if k not in kwargs and k in self.metadata: + kwargs[k] = self.metadata[k] + + uri = prepare_grant_uri( + url, client_id=self.client_id, response_type=response_type, + state=state, **kwargs) + return uri, state + + def fetch_token(self, url=None, body='', method='POST', headers=None, + auth=None, grant_type=None, state=None, **kwargs): + """Generic method for fetching an access token from the token endpoint. + + :param url: Access Token endpoint URL, if not configured, + ``authorization_response`` is used to extract token from + its fragment (implicit way). + :param body: Optional application/x-www-form-urlencoded body to add the + include in the token request. Prefer kwargs over body. + :param method: The HTTP method used to make the request. Defaults + to POST, but may also be GET. Other methods should + be added as needed. + :param headers: Dict to default request headers with. + :param auth: An auth tuple or method as accepted by requests. + :param grant_type: Use specified grant_type to fetch token + :return: A :class:`OAuth2Token` object (a dict too). + """ + state = state or self.state + # implicit grant_type + authorization_response = kwargs.pop('authorization_response', None) + if authorization_response and '#' in authorization_response: + return self.token_from_fragment(authorization_response, state) + + session_kwargs = self._extract_session_request_params(kwargs) + + if authorization_response and 'code=' in authorization_response: + grant_type = 'authorization_code' + params = parse_authorization_code_response( + authorization_response, + state=state, + ) + kwargs['code'] = params['code'] + + if grant_type is None: + grant_type = self.metadata.get('grant_type') + + if grant_type is None: + grant_type = _guess_grant_type(kwargs) + self.metadata['grant_type'] = grant_type + + body = self._prepare_token_endpoint_body(body, grant_type, **kwargs) + + if auth is None: + auth = self.client_auth(self.token_endpoint_auth_method) + + if headers is None: + headers = DEFAULT_HEADERS + + if url is None: + url = self.metadata.get('token_endpoint') + + return self._fetch_token( + url, body=body, auth=auth, method=method, + headers=headers, **session_kwargs + ) + + def token_from_fragment(self, authorization_response, state=None): + token = parse_implicit_response(authorization_response, state) + if 'error' in token: + raise self.oauth_error_class( + error=token['error'], + description=token.get('error_description') + ) + self.token = token + return token + + def refresh_token(self, url, refresh_token=None, body='', + auth=None, headers=None, **kwargs): + """Fetch a new access token using a refresh token. + + :param url: Refresh Token endpoint, must be HTTPS. + :param refresh_token: The refresh_token to use. + :param body: Optional application/x-www-form-urlencoded body to add the + include in the token request. Prefer kwargs over body. + :param auth: An auth tuple or method as accepted by requests. + :param headers: Dict to default request headers with. + :return: A :class:`OAuth2Token` object (a dict too). + """ + session_kwargs = self._extract_session_request_params(kwargs) + refresh_token = refresh_token or self.token.get('refresh_token') + if 'scope' not in kwargs and self.scope: + kwargs['scope'] = self.scope + body = prepare_token_request( + 'refresh_token', body, + refresh_token=refresh_token, **kwargs + ) + + if headers is None: + headers = DEFAULT_HEADERS.copy() + + for hook in self.compliance_hook['refresh_token_request']: + url, headers, body = hook(url, headers, body) + + if auth is None: + auth = self.client_auth(self.token_endpoint_auth_method) + + return self._refresh_token( + url, refresh_token=refresh_token, body=body, headers=headers, + auth=auth, **session_kwargs) + + def ensure_active_token(self, token): + if not token.is_expired(): + return True + refresh_token = token.get('refresh_token') + url = self.metadata.get('token_endpoint') + if refresh_token and url: + self.refresh_token(url, refresh_token=refresh_token) + return True + elif self.metadata.get('grant_type') == 'client_credentials': + access_token = token['access_token'] + new_token = self.fetch_token(url, grant_type='client_credentials') + if self.update_token: + self.update_token(new_token, access_token=access_token) + return True + + def revoke_token(self, url, token=None, token_type_hint=None, + body=None, auth=None, headers=None, **kwargs): + """Revoke token method defined via `RFC7009`_. + + :param url: Revoke Token endpoint, must be HTTPS. + :param token: The token to be revoked. + :param token_type_hint: The type of the token that to be revoked. + It can be "access_token" or "refresh_token". + :param body: Optional application/x-www-form-urlencoded body to add the + include in the token request. Prefer kwargs over body. + :param auth: An auth tuple or method as accepted by requests. + :param headers: Dict to default request headers with. + :return: Revocation Response + + .. _`RFC7009`: https://tools.ietf.org/html/rfc7009 + """ + return self._handle_token_hint( + 'revoke_token_request', url, + token=token, token_type_hint=token_type_hint, + body=body, auth=auth, headers=headers, **kwargs) + + def introspect_token(self, url, token=None, token_type_hint=None, + body=None, auth=None, headers=None, **kwargs): + """Implementation of OAuth 2.0 Token Introspection defined via `RFC7662`_. + + :param url: Introspection Endpoint, must be HTTPS. + :param token: The token to be introspected. + :param token_type_hint: The type of the token that to be revoked. + It can be "access_token" or "refresh_token". + :param body: Optional application/x-www-form-urlencoded body to add the + include in the token request. Prefer kwargs over body. + :param auth: An auth tuple or method as accepted by requests. + :param headers: Dict to default request headers with. + :return: Introspection Response + + .. _`RFC7662`: https://tools.ietf.org/html/rfc7662 + """ + return self._handle_token_hint( + 'introspect_token_request', url, + token=token, token_type_hint=token_type_hint, + body=body, auth=auth, headers=headers, **kwargs) + + def register_compliance_hook(self, hook_type, hook): + """Register a hook for request/response tweaking. + + Available hooks are: + + * access_token_response: invoked before token parsing. + * refresh_token_request: invoked before refreshing token. + * refresh_token_response: invoked before refresh token parsing. + * protected_request: invoked before making a request. + * revoke_token_request: invoked before revoking a token. + * introspect_token_request: invoked before introspecting a token. + """ + if hook_type == 'protected_request': + self.token_auth.hooks.add(hook) + return + + if hook_type not in self.compliance_hook: + raise ValueError('Hook type %s is not in %s.', + hook_type, self.compliance_hook) + self.compliance_hook[hook_type].add(hook) + + def parse_response_token(self, resp): + if resp.status_code >= 500: + resp.raise_for_status() + + token = resp.json() + if 'error' in token: + raise self.oauth_error_class( + error=token['error'], + description=token.get('error_description') + ) + self.token = token + return self.token + + def _fetch_token(self, url, body='', headers=None, auth=None, + method='POST', **kwargs): + + if method.upper() == 'POST': + resp = self.session.post( + url, data=dict(url_decode(body)), + headers=headers, auth=auth, **kwargs) + else: + if '?' in url: + url = '&'.join([url, body]) + else: + url = '?'.join([url, body]) + resp = self.session.request(method, url, headers=headers, auth=auth, **kwargs) + + for hook in self.compliance_hook['access_token_response']: + resp = hook(resp) + + return self.parse_response_token(resp) + + def _refresh_token(self, url, refresh_token=None, body='', headers=None, + auth=None, **kwargs): + resp = self._http_post(url, body=body, auth=auth, headers=headers, **kwargs) + + for hook in self.compliance_hook['refresh_token_response']: + resp = hook(resp) + + token = self.parse_response_token(resp) + if 'refresh_token' not in token: + self.token['refresh_token'] = refresh_token + + if callable(self.update_token): + self.update_token(self.token, refresh_token=refresh_token) + + return self.token + + def _handle_token_hint(self, hook, url, token=None, token_type_hint=None, + body=None, auth=None, headers=None, **kwargs): + if token is None and self.token: + token = self.token.get('refresh_token') or self.token.get('access_token') + + if body is None: + body = '' + + body, headers = prepare_revoke_token_request( + token, token_type_hint, body, headers) + + for hook in self.compliance_hook[hook]: + url, headers, body = hook(url, headers, body) + + if auth is None: + auth = self.client_auth(self.revocation_endpoint_auth_method) + + session_kwargs = self._extract_session_request_params(kwargs) + return self._http_post( + url, body, auth=auth, headers=headers, **session_kwargs) + + def _prepare_token_endpoint_body(self, body, grant_type, **kwargs): + if grant_type == 'authorization_code': + if 'redirect_uri' not in kwargs: + kwargs['redirect_uri'] = self.redirect_uri + return prepare_token_request(grant_type, body, **kwargs) + + if 'scope' not in kwargs and self.scope: + kwargs['scope'] = self.scope + return prepare_token_request(grant_type, body, **kwargs) + + def _extract_session_request_params(self, kwargs): + """Extract parameters for session object from the passing ``**kwargs``.""" + rv = {} + for k in self.SESSION_REQUEST_PARAMS: + if k in kwargs: + rv[k] = kwargs.pop(k) + return rv + + def _http_post(self, url, body=None, auth=None, headers=None, **kwargs): + return self.session.post( + url, data=dict(url_decode(body)), + headers=headers, auth=auth, **kwargs) + + +def _guess_grant_type(kwargs): + if 'code' in kwargs: + grant_type = 'authorization_code' + elif 'username' in kwargs and 'password' in kwargs: + grant_type = 'password' + else: + grant_type = 'client_credentials' + return grant_type diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/__init__.py b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/__init__.py new file mode 100644 index 00000000..e1748e3d --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/__init__.py @@ -0,0 +1,83 @@ +""" + authlib.oauth2.rfc6749 + ~~~~~~~~~~~~~~~~~~~~~~ + + This module represents a direct implementation of + The OAuth 2.0 Authorization Framework. + + https://tools.ietf.org/html/rfc6749 +""" + +from .requests import OAuth2Request, JsonRequest +from .wrappers import OAuth2Token +from .errors import ( + OAuth2Error, + AccessDeniedError, + MissingAuthorizationError, + InvalidGrantError, + InvalidClientError, + InvalidRequestError, + InvalidScopeError, + InsecureTransportError, + UnauthorizedClientError, + UnsupportedResponseTypeError, + UnsupportedGrantTypeError, + UnsupportedTokenTypeError, + # exceptions for clients + MissingCodeException, + MissingTokenException, + MissingTokenTypeException, + MismatchingStateException, +) +from .models import ClientMixin, AuthorizationCodeMixin, TokenMixin +from .authenticate_client import ClientAuthentication +from .authorization_server import AuthorizationServer +from .resource_protector import ResourceProtector, TokenValidator +from .token_endpoint import TokenEndpoint +from .grants import ( + BaseGrant, + AuthorizationEndpointMixin, + TokenEndpointMixin, + AuthorizationCodeGrant, + ImplicitGrant, + ResourceOwnerPasswordCredentialsGrant, + ClientCredentialsGrant, + RefreshTokenGrant, +) +from .util import scope_to_list, list_to_scope + +__all__ = [ + 'OAuth2Token', + 'OAuth2Request', 'JsonRequest', + 'OAuth2Error', + 'AccessDeniedError', + 'MissingAuthorizationError', + 'InvalidGrantError', + 'InvalidClientError', + 'InvalidRequestError', + 'InvalidScopeError', + 'InsecureTransportError', + 'UnauthorizedClientError', + 'UnsupportedResponseTypeError', + 'UnsupportedGrantTypeError', + 'UnsupportedTokenTypeError', + 'MissingCodeException', + 'MissingTokenException', + 'MissingTokenTypeException', + 'MismatchingStateException', + 'ClientMixin', 'AuthorizationCodeMixin', 'TokenMixin', + 'ClientAuthentication', + 'AuthorizationServer', + 'ResourceProtector', + 'TokenValidator', + 'TokenEndpoint', + 'BaseGrant', + 'AuthorizationEndpointMixin', + 'TokenEndpointMixin', + 'AuthorizationCodeGrant', + 'ImplicitGrant', + 'ResourceOwnerPasswordCredentialsGrant', + 'ClientCredentialsGrant', + 'RefreshTokenGrant', + 'scope_to_list', 'list_to_scope', +] diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b36d37af1db2f1a6d6f1c428a83be5481a3eef8a GIT binary patch literal 2425 zcmdUw%WfMt6hJwWtfwX0k}N;sIAc4qqdX+XXc{yq3b?kLx@elfk1hzIgYgV)5gyJ= z$&sC8QS>jm@22Pn^auI{S{k$Msyh_{x=1(S<&2`Jc7QJ0MMuN|d3kxs`ylmGv6x5l z`|I&9q>@AEHy8}QMBI7xr|kTIY=n`m*$GEu37lX_oYY{PbW&^#kEwpjNwW;juq@89 z9L}*k&a(n8uyH)jinz#1xWp##1e?T@Yzj}YGA^?UuCOYuvS~ccYPhECj5#xG7SFOd zJjdqoyppAzYit28sD8$|&KB{a>SvuBOvgG~!b@tLbC%f(UQzwLbCcC^ovq?kwuaZ( zEqseLaD&~(x7i(hhuy_@m0rQQ$C|jwTDYa56J(G7sNr?HxQ`m8m%rw9`I+6IbonyyqY`cP@yx=?m9&0#OFj1HxRn1+msV4&?)mB!lcX$sORe5 zalDG?PdDX8`bKkIhmObT%Sh!jZZdN2@zZ9sLnjD)@u<}bJkJqLN`m92$4^?FfH|$f zDSy{w0vn02sElsxk#D<11YzL|;kogkp@oHL_P{$OZewyV+~M5g;nb#O5h1pTONkwc z=AKX?sCzPUyjXkJJu@9@Kjx+zM51ym+H$D$Hj-6hS$u@iwfmOmlSowCbp^4yoE%7d z!uNQ*e&*1HY(Q*?{jTAKLsxWtP$c#qkt^i-gBJsHbMMTm6J9-~;xL@5#_n!;HraV@ z5g!s3PRCNEJQNRNGqmw`1xztBusSky`!elAV~u23h`e}0pHnxijYJmqjpTV{RrO`o zs?ieAm4T&}suC%$jI7=#{ETo}0#h;`UYA?s8TSHNfikxxW$$Z9m?_6{Z837kwSAAe zK_eUHJ~ahVu?pu$?C!)m(aFjq>)z)@WT&_*OP^Xah=%pSxt^Z8gg-NdkTq^^abkm4 zrXwP?TIB5|xpeDTUapQhfKr8W7f?e+;292;mllZD}Kg<}0?OBEqW_fg*#n6*5d(KVYCtN5O!!&_AEdFf=!?b+Zh$H^yXjn0a zwMYz0U3levScRFlPnjW9QL31PWtlxymxezm%we3uQUH&VLE>staSPKY@VtnB8ow~r z4X87WB81R%9K-k-y^=viufN%T)V4fZ-plr(cYN@ z?Jwz3ThM^q^QDq`LPQ%plm8E`=>K8x^0o|vx->A1rvKt~_T%V};1m8(ZU;}Y_(QUv z)HJQ1$ZDxR0#uQ9zlYW@w+pn?8*TkWSxfZM{|l=~+tzw$>wWD4J?M?Lt0bE}bVa*B kjoxVMCvp&?{}wW3tsZJ#ZvE79LGC`l_Zj%{2Qu|<0Cz&lCjbBd literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/authenticate_client.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/authenticate_client.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d114b4f31b8f6dde57dc8a8a03a6bb6d92126f04 GIT binary patch literal 5469 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 z⪻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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/parameters.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/parameters.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ac2657a5a8e6b7c92ec2bb4ae64df55114a735cc GIT binary patch literal 9604 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 Crc%-X literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/token_endpoint.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/__pycache__/token_endpoint.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..04342a6ef5c94995067b2840ebffc6f49d794d86 GIT binary patch literal 2063 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 OAuth2Request: + """This method MUST be implemented in framework integrations. It is + used to create an OAuth2Request instance. + + :param request: the "request" instance in framework + :return: OAuth2Request instance + """ + raise NotImplementedError() + + def create_json_request(self, request) -> JsonRequest: + """This method MUST be implemented in framework integrations. It is + used to create an HttpRequest instance. + + :param request: the "request" instance in framework + :return: HttpRequest instance + """ + raise NotImplementedError() + + def handle_response(self, status, body, headers): + """Return HTTP response. Framework MUST implement this function.""" + raise NotImplementedError() + + def validate_requested_scope(self, scope, state=None): + """Validate if requested scope is supported by Authorization Server. + Developers CAN re-write this method to meet your needs. + """ + if scope and self.scopes_supported: + scopes = set(scope_to_list(scope)) + if not set(self.scopes_supported).issuperset(scopes): + raise InvalidScopeError(state=state) + + def register_grant(self, grant_cls, extensions=None): + """Register a grant class into the endpoint registry. Developers + can implement the grants in ``authlib.oauth2.rfc6749.grants`` and + register with this method:: + + class AuthorizationCodeGrant(grants.AuthorizationCodeGrant): + def authenticate_user(self, credential): + # ... + + authorization_server.register_grant(AuthorizationCodeGrant) + + :param grant_cls: a grant class. + :param extensions: extensions for the grant class. + """ + if hasattr(grant_cls, 'check_authorization_endpoint'): + self._authorization_grants.append((grant_cls, extensions)) + if hasattr(grant_cls, 'check_token_endpoint'): + self._token_grants.append((grant_cls, extensions)) + + def register_endpoint(self, endpoint): + """Add extra endpoint to authorization server. e.g. + RevocationEndpoint:: + + authorization_server.register_endpoint(RevocationEndpoint) + + :param endpoint_cls: A endpoint class or instance. + """ + if isinstance(endpoint, type): + endpoint = endpoint(self) + else: + endpoint.server = self + + endpoints = self._endpoints.setdefault(endpoint.ENDPOINT_NAME, []) + endpoints.append(endpoint) + + def get_authorization_grant(self, request): + """Find the authorization grant for current request. + + :param request: OAuth2Request instance. + :return: grant instance + """ + for (grant_cls, extensions) in self._authorization_grants: + if grant_cls.check_authorization_endpoint(request): + return _create_grant(grant_cls, extensions, request, self) + raise UnsupportedResponseTypeError(request.response_type) + + def get_consent_grant(self, request=None, end_user=None): + """Validate current HTTP request for authorization page. This page + is designed for resource owner to grant or deny the authorization. + """ + request = self.create_oauth2_request(request) + request.user = end_user + + grant = self.get_authorization_grant(request) + grant.validate_consent_request() + return grant + + def get_token_grant(self, request): + """Find the token grant for current request. + + :param request: OAuth2Request instance. + :return: grant instance + """ + for (grant_cls, extensions) in self._token_grants: + if grant_cls.check_token_endpoint(request): + return _create_grant(grant_cls, extensions, request, self) + raise UnsupportedGrantTypeError(request.grant_type) + + def create_endpoint_response(self, name, request=None): + """Validate endpoint request and create endpoint response. + + :param name: Endpoint name + :param request: HTTP request instance. + :return: Response + """ + if name not in self._endpoints: + raise RuntimeError(f'There is no "{name}" endpoint.') + + endpoints = self._endpoints[name] + for endpoint in endpoints: + request = endpoint.create_endpoint_request(request) + try: + return self.handle_response(*endpoint(request)) + except ContinueIteration: + continue + except OAuth2Error as error: + return self.handle_error_response(request, error) + + def create_authorization_response(self, request=None, grant_user=None): + """Validate authorization request and create authorization response. + + :param request: HTTP request instance. + :param grant_user: if granted, it is resource owner. If denied, + it is None. + :returns: Response + """ + if not isinstance(request, OAuth2Request): + request = self.create_oauth2_request(request) + + try: + grant = self.get_authorization_grant(request) + except UnsupportedResponseTypeError as error: + return self.handle_error_response(request, error) + + try: + redirect_uri = grant.validate_authorization_request() + args = grant.create_authorization_response(redirect_uri, grant_user) + return self.handle_response(*args) + except OAuth2Error as error: + return self.handle_error_response(request, error) + + def create_token_response(self, request=None): + """Validate token request and create token response. + + :param request: HTTP request instance + """ + request = self.create_oauth2_request(request) + try: + grant = self.get_token_grant(request) + except UnsupportedGrantTypeError as error: + return self.handle_error_response(request, error) + + try: + grant.validate_token_request() + args = grant.create_token_response() + return self.handle_response(*args) + except OAuth2Error as error: + return self.handle_error_response(request, error) + + def handle_error_response(self, request, error): + return self.handle_response(*error(self.get_error_uri(request, error))) + + +def _create_grant(grant_cls, extensions, request, server): + grant = grant_cls(request, server) + if extensions: + for ext in extensions: + ext(grant) + return grant diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/errors.py b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/errors.py new file mode 100644 index 00000000..63ffb47e --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/errors.py @@ -0,0 +1,233 @@ +""" + authlib.oauth2.rfc6749.errors + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Implementation for OAuth 2 Error Response. A basic error has + parameters: + + error + REQUIRED. A single ASCII [USASCII] error code. + + error_description + OPTIONAL. Human-readable ASCII [USASCII] text providing + additional information, used to assist the client developer in + understanding the error that occurred. + + error_uri + OPTIONAL. A URI identifying a human-readable web page with + information about the error, used to provide the client + developer with additional information about the error. + Values for the "error_uri" parameter MUST conform to the + URI-reference syntax and thus MUST NOT include characters + outside the set %x21 / %x23-5B / %x5D-7E. + + state + REQUIRED if a "state" parameter was present in the client + authorization request. The exact value received from the + client. + + https://tools.ietf.org/html/rfc6749#section-5.2 + + :copyright: (c) 2017 by Hsiaoming Yang. +""" +from authlib.oauth2.base import OAuth2Error +from authlib.common.security import is_secure_transport + +__all__ = [ + 'OAuth2Error', + 'InsecureTransportError', 'InvalidRequestError', + 'InvalidClientError', 'UnauthorizedClientError', 'InvalidGrantError', + 'UnsupportedResponseTypeError', 'UnsupportedGrantTypeError', + 'InvalidScopeError', 'AccessDeniedError', + 'MissingAuthorizationError', 'UnsupportedTokenTypeError', + 'MissingCodeException', 'MissingTokenException', + 'MissingTokenTypeException', 'MismatchingStateException', +] + + +class InsecureTransportError(OAuth2Error): + error = 'insecure_transport' + description = 'OAuth 2 MUST utilize https.' + + @classmethod + def check(cls, uri): + """Check and raise InsecureTransportError with the given URI.""" + if not is_secure_transport(uri): + raise cls() + + +class InvalidRequestError(OAuth2Error): + """The request is missing a required parameter, includes an + unsupported parameter value (other than grant type), + repeats a parameter, includes multiple credentials, + utilizes more than one mechanism for authenticating the + client, or is otherwise malformed. + + https://tools.ietf.org/html/rfc6749#section-5.2 + """ + error = 'invalid_request' + + +class InvalidClientError(OAuth2Error): + """Client authentication failed (e.g., unknown client, no + client authentication included, or unsupported + authentication method). The authorization server MAY + return an HTTP 401 (Unauthorized) status code to indicate + which HTTP authentication schemes are supported. If the + client attempted to authenticate via the "Authorization" + request header field, the authorization server MUST + respond with an HTTP 401 (Unauthorized) status code and + include the "WWW-Authenticate" response header field + matching the authentication scheme used by the client. + + https://tools.ietf.org/html/rfc6749#section-5.2 + """ + error = 'invalid_client' + status_code = 400 + + def get_headers(self): + headers = super().get_headers() + if self.status_code == 401: + error_description = self.get_error_description() + # safe escape + error_description = error_description.replace('"', '|') + extras = [ + f'error="{self.error}"', + f'error_description="{error_description}"' + ] + headers.append( + ('WWW-Authenticate', 'Basic ' + ', '.join(extras)) + ) + return headers + + +class InvalidGrantError(OAuth2Error): + """The provided authorization grant (e.g., authorization + code, resource owner credentials) or refresh token is + invalid, expired, revoked, does not match the redirection + URI used in the authorization request, or was issued to + another client. + + https://tools.ietf.org/html/rfc6749#section-5.2 + """ + error = 'invalid_grant' + + +class UnauthorizedClientError(OAuth2Error): + """ The authenticated client is not authorized to use this + authorization grant type. + + https://tools.ietf.org/html/rfc6749#section-5.2 + """ + error = 'unauthorized_client' + + +class UnsupportedResponseTypeError(OAuth2Error): + """The authorization server does not support obtaining + an access token using this method.""" + error = 'unsupported_response_type' + + def __init__(self, response_type): + super().__init__() + self.response_type = response_type + + def get_error_description(self): + return f'response_type={self.response_type} is not supported' + + +class UnsupportedGrantTypeError(OAuth2Error): + """The authorization grant type is not supported by the + authorization server. + + https://tools.ietf.org/html/rfc6749#section-5.2 + """ + error = 'unsupported_grant_type' + + def __init__(self, grant_type): + super().__init__() + self.grant_type = grant_type + + def get_error_description(self): + return f'grant_type={self.grant_type} is not supported' + + +class InvalidScopeError(OAuth2Error): + """The requested scope is invalid, unknown, malformed, or + exceeds the scope granted by the resource owner. + + https://tools.ietf.org/html/rfc6749#section-5.2 + """ + error = 'invalid_scope' + description = 'The requested scope is invalid, unknown, or malformed.' + + +class AccessDeniedError(OAuth2Error): + """The resource owner or authorization server denied the request. + + Used in authorization endpoint for "code" and "implicit". Defined in + `Section 4.1.2.1`_. + + .. _`Section 4.1.2.1`: https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + """ + error = 'access_denied' + description = 'The resource owner or authorization server denied the request' + + +# -- below are extended errors -- # + + +class ForbiddenError(OAuth2Error): + status_code = 401 + + def __init__(self, auth_type=None, realm=None): + super().__init__() + self.auth_type = auth_type + self.realm = realm + + def get_headers(self): + headers = super().get_headers() + if not self.auth_type: + return headers + + extras = [] + if self.realm: + extras.append(f'realm="{self.realm}"') + extras.append(f'error="{self.error}"') + error_description = self.description + extras.append(f'error_description="{error_description}"') + headers.append( + ('WWW-Authenticate', f'{self.auth_type} ' + ', '.join(extras)) + ) + return headers + + +class MissingAuthorizationError(ForbiddenError): + error = 'missing_authorization' + description = 'Missing "Authorization" in headers.' + + +class UnsupportedTokenTypeError(ForbiddenError): + error = 'unsupported_token_type' + + +# -- exceptions for clients -- # + + +class MissingCodeException(OAuth2Error): + error = 'missing_code' + description = 'Missing "code" in response.' + + +class MissingTokenException(OAuth2Error): + error = 'missing_token' + description = 'Missing "access_token" in response.' + + +class MissingTokenTypeException(OAuth2Error): + error = 'missing_token_type' + description = 'Missing "token_type" in response.' + + +class MismatchingStateException(OAuth2Error): + error = 'mismatching_state' + description = 'CSRF Warning! State not equal in request and response.' diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__init__.py b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__init__.py new file mode 100644 index 00000000..b1797565 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__init__.py @@ -0,0 +1,37 @@ +""" + authlib.oauth2.rfc6749.grants + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Implementation for `Section 4`_ of "Obtaining Authorization". + + To request an access token, the client obtains authorization from the + resource owner. The authorization is expressed in the form of an + authorization grant, which the client uses to request the access + token. OAuth defines four grant types: + + 1. authorization code + 2. implicit + 3. resource owner password credentials + 4. client credentials. + + It also provides an extension mechanism for defining additional grant + types. Authlib defines refresh_token as a grant type too. + + .. _`Section 4`: https://tools.ietf.org/html/rfc6749#section-4 +""" + +# flake8: noqa + +from .base import BaseGrant, AuthorizationEndpointMixin, TokenEndpointMixin +from .authorization_code import AuthorizationCodeGrant +from .implicit import ImplicitGrant +from .resource_owner_password_credentials import ResourceOwnerPasswordCredentialsGrant +from .client_credentials import ClientCredentialsGrant +from .refresh_token import RefreshTokenGrant + +__all__ = [ + 'BaseGrant', 'AuthorizationEndpointMixin', 'TokenEndpointMixin', + 'AuthorizationCodeGrant', 'ImplicitGrant', + 'ResourceOwnerPasswordCredentialsGrant', + 'ClientCredentialsGrant', 'RefreshTokenGrant', +] diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9e38f0e20596c2430cf3e5045665d263f66ce62a GIT binary patch literal 1562 zcmaJ>&u`l{6sBw^cHFw#f+B~Vhy*(XNa?K$IxH9pbXn0A>zX3Xb`T7xv_#oN`9mY= zB;8@?f6?QBUWWYv`xAEeG0=6V-3;{BUG_*>iB)u?h=(Wf@$q}#`^4V{gFb@s&x1eM z_8LNe`ImaMmd=|oIImEKVw6Q$OGL62w`4nR%TC;h{I|APlk4$%@H?U_dvP!LYhpw8 z<9_hh#Wi_7z8?Ip7|0v(jR;Lp)_WbrA7mR((Qcpq2}kxZ3_5dD!N){<=Qc5UdgqJ% zFUiDE8GVC|6uf@I5$48~$?$ z-X>Lw6O9e~X~wL>RAHK?%v$X9bEfvNn=+gV4*9VTS!_UknFHrWOCJ@$7-sd%qzvmb z#SFnGu-n&m70xYY=LN)BmSL_!e!wg}PO2_hx!MrO*u!U2o=#WM%q;UDFOhqo74(oK zz$f^~7mPEOa|Pi!fWsjnb}tHM532eYH}t(J%jYVDae z8BPt$fF({v)wz9A^R}|GB>W)|Ev&|c(Wg8EU_d)NcT8E|Ldnu8Rou$Z%z)juj%FG6 zU8SNbp(@jtK|)(WNSB2gmIKad5?H_#4p=E0Skp@&gy3XFEeCk&TwxD}LkJO;aOQHN z&15)rQVf^!+_9CqZteH~j^LNsZI>HgQ_CKB)s`PO6n0-_h33kA&(FCkH&48#8sB!K za;vf95U3BCU}fO7?YXZ%d~&=b|H#Yh$&&iRE9UFKt-~PM_pE$$Tu~FCRN+0-hB8dY z8@L>hS@)*vP0yPRZ~Xo7c=yAynFT+O^gK)#hc_KjtQ2{1?>$_R;_V literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__pycache__/authorization_code.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__pycache__/authorization_code.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..de6235ef9ac60479009b6e4b2f826d6520449a0d GIT binary patch literal 17623 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__pycache__/client_credentials.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__pycache__/client_credentials.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8ecd110e3b9e3532d478157b9527099781ae68c6 GIT binary patch literal 5037 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__pycache__/refresh_token.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__pycache__/refresh_token.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aa7d35e557b4265203893b0e01a40505faad54c6 GIT binary patch literal 8489 zcmdT}-A^3X6~Ft*uq-UQ2776+GX_Ih+YJ7~ADh?;wlV(14&b<1Iob?61B^Ypvz-~R zLAXU$9#GUad5C1IN>v^z*O3#+iW;eZLLYb0RG^V8S*rTrw~d^>q%S?^&d2Vs;5bqH z(1ATWbLZT1zkc_e-?{te=H>{2>)#{ah-?QT|G)?53fng?KZ2VFL?9U=_yoV~%lL$V z5S0D-Kqin6W`aH-W=l8soc?H zM^13lDqqkwP8FwAQJcx?%5AYg^?&u+SA^;hv072gNxaNbldM<}ii%Xw*(pV3J?1Ti ztUg~9Id;rySSn1jyw&hfE+=XlJApl6i=xVYI4LKg@DgV;sk3Yl_qCjII~8 z^uU0wD6+;$qCUkb>h!>jo|gygp>}JQnf{}Z7dT0yFK{kXezWm3uZbf#4`zb4I&63S zigZ^hyzrxz&urFmN>PLf%F2?ar-J6T3xzpemV`0!m$Ra#538!8nsK{u9F@IAv<0hZ z$MpiPf}%dysW5 z=S&(-B5sBNd|v(q!~?QOR^Yq-dIUvJ+~Rva9T(ibR%-5@G6I`=(f0`6JaOOp$f9or z+p4=3$t`zNdN;7vqBm95y}h^(Ex;oAM;AKZLyYmd$kMF|JBgx=Ri@Y;H5E3y5J-R@ zDF-^%_RTt5FPo##G6S+QZH5GKa(3Em&CQ6p+gZ9t=@v92BV$9O6WNLPuMMl%A=nW? zO_Zn1uvJ~dQL^m!x6Y<-<`e;T>douQ)Wmr{cU!wTCg#QbqzJwvCl+$zO>Rys%-y^! zP2SWbUF4#^&{J(h*Nb*SaG((QtN zYvUl6NQEJZ?Q8MltMTLIc-n}km&4DPrcW9_ZY(7ZJnbzrCk*C9i8=8+*1i_&U5)jw z=zsckId;s59jg#uu!Kn|3^LsS_A7sVFRaK9W#SNPG0*e8)eKD{Ss?~Dt0msm{YES`8 zHaqVKsl#LdFc}zCTR>%@`--G#=(f8&tJlR!1qY;Ds=;iq*Ut<>9LSr2X;D`hsBiwv z16+>{Girgx(Hx*Rd;Y;0)0^2u3bU$b~3Fryb9ay-d9t%`$A@w@2p{g9%(TX6J z$a=E#^Qe(bttIB#APFKxfH$pytQqubzrr1 z;AwNY^_0zd**(1=Ru)DqEL#84(b$%r)ThzQ6C&8=abj)Vip}fEO&@C$zf~ zuGXyHZE0@yK~#{>^g7UZZ30a?5&bXB}Mr+0prj4<4T??@Svz)8&r0jE=Xc;##b4 zHP-jlwy!?;>tMNm$mky`r%oHG)8*J1BX*|FOeFx=q@@=0TrUOPbG_Nu@bLPva}oSf z)!SuVID)rAi*?sV{{vutO}_>a7j$dda{Ze?BPZVr1sA4R2#%EcBG=+6i_}DQ4p=2Z zKonTs;ih(c)fHOBay|R;p0ZnXF;*Fy=WmNzO+68KSHrh(ed!D}2H0lqe4s zixB#yyXo+O)7aMeiHU2jF=s4DDD?UMNky37 zPffcNJZ%whoR2DpaO-0+J2w38^$TOeXE~My@-i#3SFVpwu#+MS+YM%UW5BQ}J=XL@ zfh~V7aHu+kK(1YhPTRrNHRCnnZ4>6x zeSHp6I`J-_FUlg_BHpcmb65p9;>#ff7Q|gMI^&uxvSl7gfaL7gqmszpT;s{>aG@_ecWo{%HrR_ULVmE7&Ll_FM$fN;BZ z6>teDBPN>I&4Gj5LAP_La9+{$G;|9c24@eL%PDz}(vY3W(cPM6A(@nNY;GZQh94Ol z=MSGdaAl!bxN-Je{@py>AG&zMQ~Qik&|$arPe3-DW`A(sdk0Y6fhRp%r`PjzQXg5E zJACo#?Q;iyF*5k>-9r=dr5hK9+-{7f!fFy+GYy^=!`h9HeJGG?rGP==y-U6{bmlNW z7U|mVa&;@v**jpNZ_LW=CvbvCFu&$D*Bl0G+6@pu)X(}TQ|DIWTseNgh#y!EukYHk z9Q;kxVBP>iww64ynmqFKy>jwxBl$LPF($gkbgeR7D<{j$L4!G1Vh*nN9I`5Ol^Fc5 z4{sPOa11X$eHF7plI?~t&~~p)!j@n267~(m8VP$%LV&E5Ucj2j7S!CoG0D6a)ZNn{ zLRM-RoMR0Wg~cH7G#J|x93Q>xQ0Y99Eb?!9LEAN4&nbl@BIspbV1caAbFZq7bteQC zgI@;gl3}t^liF76Y@9bd`-1+G>M7S0rWj$q5taplH-!uJb(kzz$0e4-ah~f#I)vte z?ZRDzTU*@Y$RYYUzI%{62)^6q3Xa#G;w4!WTnpd;q$xWhgPR723;vvT?-l(~MSWH+ z&<=@sI^mZj4jfYU8AZ8mwyWYCZ2YVu3)!413P>q<*=(Ponqf zz%gOU$F8=rD{U+H%B_P&>)>+8Jy+;^-1BsMnK^DS$4kud=bfzOlRCg-eG>aP_Apdt zb{WjB60?i?u#Q!x)bwqhb_}aOat2%{hK>DZ%Rm=RBa1j*Sdi3g9EFcaDD0Xx}JN%#UMS$f)GNNwHxZ0 z?KTyHvz?k#XTShvZ!`&0_n={##WHM-uZG?4h7Z%Hs7`3}W$s1hNq?VBa}7+`R2U+x0&fao<@n0FQK`%*ss zYj{0EX*7}+sbH~xJRGN#$ups>rmK)*aO_!ePL$z18gdL|qpo9-kig|(V*VwuT1qvYhcr>wuqw z9KFwD#mi(;b=86O+U^`EFp_4=0eWlzu+aAi^^Ic(EVpdctMaKd&BVODPt)YUHf=Y% zS+3!BGHuyT+s3gqyuR?6+eQ`rf-~QuKz|4L!e8}z_9-i6R4PJYVgFbiee$?z&xn5q zHMCX`OXOck66-3rbQ>+*C8oRnRO!b7t_uJ+RCB~kvk`RtFjF$kF=%Q5@Tofa|0UwE zX&Y$O27&fl6J3?|B3}n}im|FPhbFR;kov*3r-^|wc?*6wa_ze-j8@!I^(~ls^&~C= zPOlxSR1WSJx_@9D(a`5u(_X%||K{?^uzZ-{ZpxRg480Glh&zR@Dnx1r{x;V6DL6WC z2Z_kXBMY7_h<7$9*1>3jce>jc$`g%#A`a6nq{|r0t=o;ovohgIFPB)L{8K9 z)8MfM5Dp^{HaR2QbZC!jz_7gz45O)-$z-zyI5o;<%}6$zSA_st%0%Ia|Iux-g_Vx=xJ%{Cw@HYV!1s<|%-+)+h|0@1q zh^Y`15t7)wbg>d9yL(H)ot0oDw7o)Hkz_*c72=AvrVt!Hy5eWOp~Ds8ifg`YAvh;@ z#oh>3c11E8+EXE}=#1c_E0Rt4STC#*;W$#Q>KXVl8{n5QIP0A@gOl(Zuo{Fi73mYO zTV0Z^!{RXI?wZAjF;2TPh>1>_FM?BG|Gx$C8wzW*B)QeCC zo04dM2LVU0K3~Pp_<}GqAlis8w$y@u>tvv`+5b9WOWyyAKjiaQ$WIed(vV!5Ho`j| jGUf1YBfNVlPzm4k`(XYymk%3D-GkrKm)~unLWlhyxrB~& literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__pycache__/resource_owner_password_credentials.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/__pycache__/resource_owner_password_credentials.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cf1b76d7e6ecd6588f1ff63a7773adc592f5a5dd GIT binary patch literal 7163 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 | + | User- | | Authorization | + | Agent -+----(B)-- User authenticates --->| Server | + | | | | + | -+----(C)-- Authorization Code ---<| | + +-|----|---+ +---------------+ + | | ^ v + (A) (C) | | + | | | | + ^ v | | + +---------+ | | + | |>---(D)-- Authorization Code ---------' | + | Client | & Redirection URI | + | | | + | |<---(E)----- Access Token -------------------' + +---------+ (w/ Optional Refresh Token) + """ + #: Allowed client auth methods for token endpoint + TOKEN_ENDPOINT_AUTH_METHODS = ['client_secret_basic', 'client_secret_post'] + + #: Generated "code" length + AUTHORIZATION_CODE_LENGTH = 48 + + RESPONSE_TYPES = {'code'} + GRANT_TYPE = 'authorization_code' + + def validate_authorization_request(self): + """The client constructs the request URI by adding the following + parameters to the query component of the authorization endpoint URI + using the "application/x-www-form-urlencoded" format. + Per `Section 4.1.1`_. + + response_type + REQUIRED. Value MUST be set to "code". + + client_id + REQUIRED. The client identifier as described in Section 2.2. + + redirect_uri + OPTIONAL. As described in Section 3.1.2. + + scope + OPTIONAL. The scope of the access request as described by + Section 3.3. + + state + RECOMMENDED. An opaque value used by the client to maintain + state between the request and callback. The authorization + server includes this value when redirecting the user-agent back + to the client. The parameter SHOULD be used for preventing + cross-site request forgery as described in Section 10.12. + + The client directs the resource owner to the constructed URI using an + HTTP redirection response, or by other means available to it via the + user-agent. + + For example, the client directs the user-agent to make the following + HTTP request using TLS (with extra line breaks for display purposes + only): + + .. code-block:: http + + GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz + &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1 + Host: server.example.com + + The authorization server validates the request to ensure that all + required parameters are present and valid. If the request is valid, + the authorization server authenticates the resource owner and obtains + an authorization decision (by asking the resource owner or by + establishing approval via other means). + + .. _`Section 4.1.1`: https://tools.ietf.org/html/rfc6749#section-4.1.1 + """ + return validate_code_authorization_request(self) + + def create_authorization_response(self, redirect_uri: str, grant_user): + """If the resource owner grants the access request, the authorization + server issues an authorization code and delivers it to the client by + adding the following parameters to the query component of the + redirection URI using the "application/x-www-form-urlencoded" format. + Per `Section 4.1.2`_. + + code + REQUIRED. The authorization code generated by the + authorization server. The authorization code MUST expire + shortly after it is issued to mitigate the risk of leaks. A + maximum authorization code lifetime of 10 minutes is + RECOMMENDED. The client MUST NOT use the authorization code + more than once. If an authorization code is used more than + once, the authorization server MUST deny the request and SHOULD + revoke (when possible) all tokens previously issued based on + that authorization code. The authorization code is bound to + the client identifier and redirection URI. + state + REQUIRED if the "state" parameter was present in the client + authorization request. The exact value received from the + client. + + For example, the authorization server redirects the user-agent by + sending the following HTTP response. + + .. code-block:: http + + HTTP/1.1 302 Found + Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA + &state=xyz + + .. _`Section 4.1.2`: https://tools.ietf.org/html/rfc6749#section-4.1.2 + + :param redirect_uri: Redirect to the given URI for the authorization + :param grant_user: if resource owner granted the request, pass this + resource owner, otherwise pass None. + :returns: (status_code, body, headers) + """ + if not grant_user: + raise AccessDeniedError(state=self.request.state, redirect_uri=redirect_uri) + + self.request.user = grant_user + + code = self.generate_authorization_code() + self.save_authorization_code(code, self.request) + + params = [('code', code)] + if self.request.state: + params.append(('state', self.request.state)) + uri = add_params_to_uri(redirect_uri, params) + headers = [('Location', uri)] + return 302, '', headers + + def validate_token_request(self): + """The client makes a request to the token endpoint by sending the + following parameters using the "application/x-www-form-urlencoded" + format per `Section 4.1.3`_: + + grant_type + REQUIRED. Value MUST be set to "authorization_code". + + code + REQUIRED. The authorization code received from the + authorization server. + + redirect_uri + REQUIRED, if the "redirect_uri" parameter was included in the + authorization request as described in Section 4.1.1, and their + values MUST be identical. + + client_id + REQUIRED, if the client is not authenticating with the + authorization server as described in Section 3.2.1. + + If the client type is confidential or the client was issued client + credentials (or assigned other authentication requirements), the + client MUST authenticate with the authorization server as described + in Section 3.2.1. + + For example, the client makes the following HTTP request using TLS: + + .. code-block:: http + + POST /token HTTP/1.1 + Host: server.example.com + Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW + Content-Type: application/x-www-form-urlencoded + + grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA + &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb + + .. _`Section 4.1.3`: https://tools.ietf.org/html/rfc6749#section-4.1.3 + """ + # ignore validate for grant_type, since it is validated by + # check_token_endpoint + + # authenticate the client if client authentication is included + client = self.authenticate_token_endpoint_client() + + log.debug('Validate token request of %r', client) + if not client.check_grant_type(self.GRANT_TYPE): + raise UnauthorizedClientError( + f'The client is not authorized to use "grant_type={self.GRANT_TYPE}"') + + code = self.request.form.get('code') + if code is None: + raise InvalidRequestError('Missing "code" in request.') + + # ensure that the authorization code was issued to the authenticated + # confidential client, or if the client is public, ensure that the + # code was issued to "client_id" in the request + authorization_code = self.query_authorization_code(code, client) + if not authorization_code: + raise InvalidGrantError('Invalid "code" in request.') + + # validate redirect_uri parameter + log.debug('Validate token redirect_uri of %r', client) + redirect_uri = self.request.redirect_uri + original_redirect_uri = authorization_code.get_redirect_uri() + if original_redirect_uri and redirect_uri != original_redirect_uri: + raise InvalidGrantError('Invalid "redirect_uri" in request.') + + # save for create_token_response + self.request.client = client + self.request.authorization_code = authorization_code + self.execute_hook('after_validate_token_request') + + def create_token_response(self): + """If the access token request is valid and authorized, the + authorization server issues an access token and optional refresh + token as described in Section 5.1. If the request client + authentication failed or is invalid, the authorization server returns + an error response as described in Section 5.2. Per `Section 4.1.4`_. + + An example successful response: + + .. code-block:: http + + HTTP/1.1 200 OK + Content-Type: application/json + Cache-Control: no-store + Pragma: no-cache + + { + "access_token":"2YotnFZFEjr1zCsicMWpAA", + "token_type":"example", + "expires_in":3600, + "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", + "example_parameter":"example_value" + } + + :returns: (status_code, body, headers) + + .. _`Section 4.1.4`: https://tools.ietf.org/html/rfc6749#section-4.1.4 + """ + client = self.request.client + authorization_code = self.request.authorization_code + + user = self.authenticate_user(authorization_code) + if not user: + raise InvalidGrantError('There is no "user" for this code.') + self.request.user = user + + scope = authorization_code.get_scope() + token = self.generate_token( + user=user, + scope=scope, + include_refresh_token=client.check_grant_type('refresh_token'), + ) + log.debug('Issue token %r to %r', token, client) + + self.save_token(token) + self.execute_hook('process_token', token=token) + self.delete_authorization_code(authorization_code) + return 200, token, self.TOKEN_RESPONSE_HEADER + + def generate_authorization_code(self): + """"The method to generate "code" value for authorization code data. + Developers may rewrite this method, or customize the code length with:: + + class MyAuthorizationCodeGrant(AuthorizationCodeGrant): + AUTHORIZATION_CODE_LENGTH = 32 # default is 48 + """ + return generate_token(self.AUTHORIZATION_CODE_LENGTH) + + def save_authorization_code(self, code, request): + """Save authorization_code for later use. Developers MUST implement + it in subclass. Here is an example:: + + def save_authorization_code(self, code, request): + client = request.client + item = AuthorizationCode( + code=code, + client_id=client.client_id, + redirect_uri=request.redirect_uri, + scope=request.scope, + user_id=request.user.id, + ) + item.save() + """ + raise NotImplementedError() + + def query_authorization_code(self, code, client): # pragma: no cover + """Get authorization_code from previously savings. Developers MUST + implement it in subclass:: + + def query_authorization_code(self, code, client): + return Authorization.get(code=code, client_id=client.client_id) + + :param code: a string represent the code. + :param client: client related to this code. + :return: authorization_code object + """ + raise NotImplementedError() + + def delete_authorization_code(self, authorization_code): + """Delete authorization code from database or cache. Developers MUST + implement it in subclass, e.g.:: + + def delete_authorization_code(self, authorization_code): + authorization_code.delete() + + :param authorization_code: the instance of authorization_code + """ + raise NotImplementedError() + + def authenticate_user(self, authorization_code): + """Authenticate the user related to this authorization_code. Developers + MUST implement this method in subclass, e.g.:: + + def authenticate_user(self, authorization_code): + return User.get(authorization_code.user_id) + + :param authorization_code: AuthorizationCode object + :return: user + """ + raise NotImplementedError() + + +def validate_code_authorization_request(grant): + request = grant.request + client_id = request.client_id + log.debug('Validate authorization request of %r', client_id) + + if client_id is None: + raise InvalidClientError(state=request.state) + + client = grant.server.query_client(client_id) + if not client: + raise InvalidClientError(state=request.state) + + redirect_uri = grant.validate_authorization_redirect_uri(request, client) + response_type = request.response_type + if not client.check_response_type(response_type): + raise UnauthorizedClientError( + f'The client is not authorized to use "response_type={response_type}"', + state=grant.request.state, + redirect_uri=redirect_uri, + ) + + try: + grant.request.client = client + grant.validate_requested_scope() + grant.execute_hook('after_validate_authorization_request') + except OAuth2Error as error: + error.redirect_uri = redirect_uri + raise error + return redirect_uri diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/base.py b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/base.py new file mode 100644 index 00000000..0d2bf453 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/base.py @@ -0,0 +1,148 @@ +from authlib.consts import default_json_headers +from ..requests import OAuth2Request +from ..errors import InvalidRequestError + + +class BaseGrant: + #: Allowed client auth methods for token endpoint + TOKEN_ENDPOINT_AUTH_METHODS = ['client_secret_basic'] + + #: Designed for which "grant_type" + GRANT_TYPE = None + + # NOTE: there is no charset for application/json, since + # application/json should always in UTF-8. + # The example on RFC is incorrect. + # https://tools.ietf.org/html/rfc4627 + TOKEN_RESPONSE_HEADER = default_json_headers + + def __init__(self, request: OAuth2Request, server): + self.prompt = None + self.redirect_uri = None + self.request = request + self.server = server + self._hooks = { + 'after_validate_authorization_request': set(), + 'after_validate_consent_request': set(), + 'after_validate_token_request': set(), + 'process_token': set(), + } + + @property + def client(self): + return self.request.client + + def generate_token(self, user=None, scope=None, grant_type=None, + expires_in=None, include_refresh_token=True): + if grant_type is None: + grant_type = self.GRANT_TYPE + return self.server.generate_token( + client=self.request.client, + grant_type=grant_type, + user=user, + scope=scope, + expires_in=expires_in, + include_refresh_token=include_refresh_token, + ) + + def authenticate_token_endpoint_client(self): + """Authenticate client with the given methods for token endpoint. + + For example, the client makes the following HTTP request using TLS: + + .. code-block:: http + + POST /token HTTP/1.1 + Host: server.example.com + Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW + Content-Type: application/x-www-form-urlencoded + + grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA + &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb + + Default available methods are: "none", "client_secret_basic" and + "client_secret_post". + + :return: client + """ + client = self.server.authenticate_client( + self.request, self.TOKEN_ENDPOINT_AUTH_METHODS) + self.server.send_signal( + 'after_authenticate_client', + client=client, grant=self) + return client + + def save_token(self, token): + """A method to save token into database.""" + return self.server.save_token(token, self.request) + + def validate_requested_scope(self): + """Validate if requested scope is supported by Authorization Server.""" + scope = self.request.scope + state = self.request.state + return self.server.validate_requested_scope(scope, state) + + def register_hook(self, hook_type, hook): + if hook_type not in self._hooks: + raise ValueError('Hook type %s is not in %s.', + hook_type, self._hooks) + self._hooks[hook_type].add(hook) + + def execute_hook(self, hook_type, *args, **kwargs): + for hook in self._hooks[hook_type]: + hook(self, *args, **kwargs) + + +class TokenEndpointMixin: + #: Allowed HTTP methods of this token endpoint + TOKEN_ENDPOINT_HTTP_METHODS = ['POST'] + + #: Designed for which "grant_type" + GRANT_TYPE = None + + @classmethod + def check_token_endpoint(cls, request: OAuth2Request): + return request.grant_type == cls.GRANT_TYPE and \ + request.method in cls.TOKEN_ENDPOINT_HTTP_METHODS + + def validate_token_request(self): + raise NotImplementedError() + + def create_token_response(self): + raise NotImplementedError() + + +class AuthorizationEndpointMixin: + RESPONSE_TYPES = set() + ERROR_RESPONSE_FRAGMENT = False + + @classmethod + def check_authorization_endpoint(cls, request: OAuth2Request): + return request.response_type in cls.RESPONSE_TYPES + + @staticmethod + def validate_authorization_redirect_uri(request: OAuth2Request, client): + if request.redirect_uri: + if not client.check_redirect_uri(request.redirect_uri): + raise InvalidRequestError( + f'Redirect URI {request.redirect_uri} is not supported by client.', + state=request.state) + return request.redirect_uri + else: + redirect_uri = client.get_default_redirect_uri() + if not redirect_uri: + raise InvalidRequestError( + 'Missing "redirect_uri" in request.', + state=request.state) + return redirect_uri + + def validate_consent_request(self): + redirect_uri = self.validate_authorization_request() + self.execute_hook('after_validate_consent_request', redirect_uri) + self.redirect_uri = redirect_uri + + def validate_authorization_request(self): + raise NotImplementedError() + + def create_authorization_response(self, redirect_uri: str, grant_user): + raise NotImplementedError() diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/client_credentials.py b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/client_credentials.py new file mode 100644 index 00000000..57249cba --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/client_credentials.py @@ -0,0 +1,102 @@ +import logging +from .base import BaseGrant, TokenEndpointMixin +from ..errors import UnauthorizedClientError + +log = logging.getLogger(__name__) + + +class ClientCredentialsGrant(BaseGrant, TokenEndpointMixin): + """The client can request an access token using only its client + credentials (or other supported means of authentication) when the + client is requesting access to the protected resources under its + control, or those of another resource owner that have been previously + arranged with the authorization server. + + The client credentials grant type MUST only be used by confidential + clients:: + + +---------+ +---------------+ + | | | | + | |>--(A)- Client Authentication --->| Authorization | + | Client | | Server | + | |<--(B)---- Access Token ---------<| | + | | | | + +---------+ +---------------+ + + https://tools.ietf.org/html/rfc6749#section-4.4 + """ + GRANT_TYPE = 'client_credentials' + + def validate_token_request(self): + """The client makes a request to the token endpoint by adding the + following parameters using the "application/x-www-form-urlencoded" + format per Appendix B with a character encoding of UTF-8 in the HTTP + request entity-body: + + grant_type + REQUIRED. Value MUST be set to "client_credentials". + + scope + OPTIONAL. The scope of the access request as described by + Section 3.3. + + The client MUST authenticate with the authorization server as + described in Section 3.2.1. + + For example, the client makes the following HTTP request using + transport-layer security (with extra line breaks for display purposes + only): + + .. code-block:: http + + POST /token HTTP/1.1 + Host: server.example.com + Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW + Content-Type: application/x-www-form-urlencoded + + grant_type=client_credentials + + The authorization server MUST authenticate the client. + """ + + # ignore validate for grant_type, since it is validated by + # check_token_endpoint + client = self.authenticate_token_endpoint_client() + log.debug('Validate token request of %r', client) + + if not client.check_grant_type(self.GRANT_TYPE): + raise UnauthorizedClientError() + + self.request.client = client + self.validate_requested_scope() + + def create_token_response(self): + """If the access token request is valid and authorized, the + authorization server issues an access token as described in + Section 5.1. A refresh token SHOULD NOT be included. If the request + failed client authentication or is invalid, the authorization server + returns an error response as described in Section 5.2. + + An example successful response: + + .. code-block:: http + + HTTP/1.1 200 OK + Content-Type: application/json + Cache-Control: no-store + Pragma: no-cache + + { + "access_token":"2YotnFZFEjr1zCsicMWpAA", + "token_type":"example", + "expires_in":3600, + "example_parameter":"example_value" + } + + :returns: (status_code, body, headers) + """ + token = self.generate_token(scope=self.request.scope, include_refresh_token=False) + log.debug('Issue token %r to %r', token, self.client) + self.save_token(token) + self.execute_hook('process_token', self, token=token) + return 200, token, self.TOKEN_RESPONSE_HEADER diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/implicit.py b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/implicit.py new file mode 100644 index 00000000..75b12be4 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/implicit.py @@ -0,0 +1,229 @@ +import logging +from authlib.common.urls import add_params_to_uri +from .base import BaseGrant, AuthorizationEndpointMixin +from ..errors import ( + OAuth2Error, + UnauthorizedClientError, + AccessDeniedError, +) + +log = logging.getLogger(__name__) + + +class ImplicitGrant(BaseGrant, AuthorizationEndpointMixin): + """The implicit grant type is used to obtain access tokens (it does not + support the issuance of refresh tokens) and is optimized for public + clients known to operate a particular redirection URI. These clients + are typically implemented in a browser using a scripting language + such as JavaScript. + + Since this is a redirection-based flow, the client must be capable of + interacting with the resource owner's user-agent (typically a web + browser) and capable of receiving incoming requests (via redirection) + from the authorization server. + + Unlike the authorization code grant type, in which the client makes + separate requests for authorization and for an access token, the + client receives the access token as the result of the authorization + request. + + The implicit grant type does not include client authentication, and + relies on the presence of the resource owner and the registration of + the redirection URI. Because the access token is encoded into the + redirection URI, it may be exposed to the resource owner and other + applications residing on the same device:: + + +----------+ + | Resource | + | Owner | + | | + +----------+ + ^ + | + (B) + +----|-----+ Client Identifier +---------------+ + | -+----(A)-- & Redirection URI --->| | + | User- | | Authorization | + | Agent -|----(B)-- User authenticates -->| Server | + | | | | + | |<---(C)--- Redirection URI ----<| | + | | with Access Token +---------------+ + | | in Fragment + | | +---------------+ + | |----(D)--- Redirection URI ---->| Web-Hosted | + | | without Fragment | Client | + | | | Resource | + | (F) |<---(E)------- Script ---------<| | + | | +---------------+ + +-|--------+ + | | + (A) (G) Access Token + | | + ^ v + +---------+ + | | + | Client | + | | + +---------+ + """ + #: authorization_code grant type has authorization endpoint + AUTHORIZATION_ENDPOINT = True + #: Allowed client auth methods for token endpoint + TOKEN_ENDPOINT_AUTH_METHODS = ['none'] + + RESPONSE_TYPES = {'token'} + GRANT_TYPE = 'implicit' + ERROR_RESPONSE_FRAGMENT = True + + def validate_authorization_request(self): + """The client constructs the request URI by adding the following + parameters to the query component of the authorization endpoint URI + using the "application/x-www-form-urlencoded" format. + Per `Section 4.2.1`_. + + response_type + REQUIRED. Value MUST be set to "token". + + client_id + REQUIRED. The client identifier as described in Section 2.2. + + redirect_uri + OPTIONAL. As described in Section 3.1.2. + + scope + OPTIONAL. The scope of the access request as described by + Section 3.3. + + state + RECOMMENDED. An opaque value used by the client to maintain + state between the request and callback. The authorization + server includes this value when redirecting the user-agent back + to the client. The parameter SHOULD be used for preventing + cross-site request forgery as described in Section 10.12. + + The client directs the resource owner to the constructed URI using an + HTTP redirection response, or by other means available to it via the + user-agent. + + For example, the client directs the user-agent to make the following + HTTP request using TLS: + + .. code-block:: http + + GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz + &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1 + Host: server.example.com + + .. _`Section 4.2.1`: https://tools.ietf.org/html/rfc6749#section-4.2.1 + """ + # ignore validate for response_type, since it is validated by + # check_authorization_endpoint + + # The implicit grant type is optimized for public clients + client = self.authenticate_token_endpoint_client() + log.debug('Validate authorization request of %r', client) + + redirect_uri = self.validate_authorization_redirect_uri( + self.request, client) + + response_type = self.request.response_type + if not client.check_response_type(response_type): + raise UnauthorizedClientError( + 'The client is not authorized to use ' + '"response_type={}"'.format(response_type), + state=self.request.state, + redirect_uri=redirect_uri, + redirect_fragment=True, + ) + + try: + self.request.client = client + self.validate_requested_scope() + self.execute_hook('after_validate_authorization_request') + except OAuth2Error as error: + error.redirect_uri = redirect_uri + error.redirect_fragment = True + raise error + return redirect_uri + + def create_authorization_response(self, redirect_uri, grant_user): + """If the resource owner grants the access request, the authorization + server issues an access token and delivers it to the client by adding + the following parameters to the fragment component of the redirection + URI using the "application/x-www-form-urlencoded" format. + Per `Section 4.2.2`_. + + access_token + REQUIRED. The access token issued by the authorization server. + + token_type + REQUIRED. The type of the token issued as described in + Section 7.1. Value is case insensitive. + + expires_in + RECOMMENDED. The lifetime in seconds of the access token. For + example, the value "3600" denotes that the access token will + expire in one hour from the time the response was generated. + If omitted, the authorization server SHOULD provide the + expiration time via other means or document the default value. + + scope + OPTIONAL, if identical to the scope requested by the client; + otherwise, REQUIRED. The scope of the access token as + described by Section 3.3. + + state + REQUIRED if the "state" parameter was present in the client + authorization request. The exact value received from the + client. + + The authorization server MUST NOT issue a refresh token. + + For example, the authorization server redirects the user-agent by + sending the following HTTP response: + + .. code-block:: http + + HTTP/1.1 302 Found + Location: http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA + &state=xyz&token_type=example&expires_in=3600 + + Developers should note that some user-agents do not support the + inclusion of a fragment component in the HTTP "Location" response + header field. Such clients will require using other methods for + redirecting the client than a 3xx redirection response -- for + example, returning an HTML page that includes a 'continue' button + with an action linked to the redirection URI. + + .. _`Section 4.2.2`: https://tools.ietf.org/html/rfc6749#section-4.2.2 + + :param redirect_uri: Redirect to the given URI for the authorization + :param grant_user: if resource owner granted the request, pass this + resource owner, otherwise pass None. + :returns: (status_code, body, headers) + """ + state = self.request.state + if grant_user: + self.request.user = grant_user + token = self.generate_token( + user=grant_user, + scope=self.request.scope, + include_refresh_token=False, + ) + log.debug('Grant token %r to %r', token, self.request.client) + + self.save_token(token) + self.execute_hook('process_token', token=token) + params = [(k, token[k]) for k in token] + if state: + params.append(('state', state)) + + uri = add_params_to_uri(redirect_uri, params, fragment=True) + headers = [('Location', uri)] + return 302, '', headers + else: + raise AccessDeniedError( + state=state, + redirect_uri=redirect_uri, + redirect_fragment=True + ) diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/refresh_token.py b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/refresh_token.py new file mode 100644 index 00000000..4df5b70e --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/refresh_token.py @@ -0,0 +1,179 @@ +""" + authlib.oauth2.rfc6749.grants.refresh_token + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + A special grant endpoint for refresh_token grant_type. Refreshing an + Access Token per `Section 6`_. + + .. _`Section 6`: https://tools.ietf.org/html/rfc6749#section-6 +""" + +import logging +from .base import BaseGrant, TokenEndpointMixin +from ..util import scope_to_list +from ..errors import ( + InvalidRequestError, + InvalidScopeError, + InvalidGrantError, + UnauthorizedClientError, +) +log = logging.getLogger(__name__) + + +class RefreshTokenGrant(BaseGrant, TokenEndpointMixin): + """A special grant endpoint for refresh_token grant_type. Refreshing an + Access Token per `Section 6`_. + + .. _`Section 6`: https://tools.ietf.org/html/rfc6749#section-6 + """ + GRANT_TYPE = 'refresh_token' + + #: The authorization server MAY issue a new refresh token + INCLUDE_NEW_REFRESH_TOKEN = False + + def _validate_request_client(self): + # require client authentication for confidential clients or for any + # client that was issued client credentials (or with other + # authentication requirements) + client = self.authenticate_token_endpoint_client() + log.debug('Validate token request of %r', client) + + if not client.check_grant_type(self.GRANT_TYPE): + raise UnauthorizedClientError() + + return client + + def _validate_request_token(self, client): + refresh_token = self.request.form.get('refresh_token') + if refresh_token is None: + raise InvalidRequestError('Missing "refresh_token" in request.') + + token = self.authenticate_refresh_token(refresh_token) + if not token or not token.check_client(client): + raise InvalidGrantError() + return token + + def _validate_token_scope(self, token): + scope = self.request.scope + if not scope: + return + + original_scope = token.get_scope() + if not original_scope: + raise InvalidScopeError() + + original_scope = set(scope_to_list(original_scope)) + if not original_scope.issuperset(set(scope_to_list(scope))): + raise InvalidScopeError() + + def validate_token_request(self): + """If the authorization server issued a refresh token to the client, the + client makes a refresh request to the token endpoint by adding the + following parameters using the "application/x-www-form-urlencoded" + format per Appendix B with a character encoding of UTF-8 in the HTTP + request entity-body, per Section 6: + + grant_type + REQUIRED. Value MUST be set to "refresh_token". + + refresh_token + REQUIRED. The refresh token issued to the client. + + scope + OPTIONAL. The scope of the access request as described by + Section 3.3. The requested scope MUST NOT include any scope + not originally granted by the resource owner, and if omitted is + treated as equal to the scope originally granted by the + resource owner. + + + For example, the client makes the following HTTP request using + transport-layer security (with extra line breaks for display purposes + only): + + .. code-block:: http + + POST /token HTTP/1.1 + Host: server.example.com + Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW + Content-Type: application/x-www-form-urlencoded + + grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA + """ + client = self._validate_request_client() + self.request.client = client + refresh_token = self._validate_request_token(client) + self._validate_token_scope(refresh_token) + self.request.refresh_token = refresh_token + + def create_token_response(self): + """If valid and authorized, the authorization server issues an access + token as described in Section 5.1. If the request failed + verification or is invalid, the authorization server returns an error + response as described in Section 5.2. + """ + refresh_token = self.request.refresh_token + user = self.authenticate_user(refresh_token) + if not user: + raise InvalidRequestError('There is no "user" for this token.') + + client = self.request.client + token = self.issue_token(user, refresh_token) + log.debug('Issue token %r to %r', token, client) + + self.request.user = user + self.save_token(token) + self.execute_hook('process_token', token=token) + self.revoke_old_credential(refresh_token) + return 200, token, self.TOKEN_RESPONSE_HEADER + + def issue_token(self, user, refresh_token): + scope = self.request.scope + if not scope: + scope = refresh_token.get_scope() + + token = self.generate_token( + user=user, + scope=scope, + include_refresh_token=self.INCLUDE_NEW_REFRESH_TOKEN, + ) + return token + + def authenticate_refresh_token(self, refresh_token): + """Get token information with refresh_token string. Developers MUST + implement this method in subclass:: + + def authenticate_refresh_token(self, refresh_token): + token = Token.get(refresh_token=refresh_token) + if token and not token.refresh_token_revoked: + return token + + :param refresh_token: The refresh token issued to the client + :return: token + """ + raise NotImplementedError() + + def authenticate_user(self, refresh_token): + """Authenticate the user related to this credential. Developers MUST + implement this method in subclass:: + + def authenticate_user(self, credential): + return User.get(credential.user_id) + + :param refresh_token: Token object + :return: user + """ + raise NotImplementedError() + + def revoke_old_credential(self, refresh_token): + """The authorization server MAY revoke the old refresh token after + issuing a new refresh token to the client. Developers MUST implement + this method in subclass:: + + def revoke_old_credential(self, refresh_token): + credential.revoked = True + credential.save() + + :param refresh_token: Token object + """ + raise NotImplementedError() diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/resource_owner_password_credentials.py b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/resource_owner_password_credentials.py new file mode 100644 index 00000000..41cabb62 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/grants/resource_owner_password_credentials.py @@ -0,0 +1,154 @@ +import logging +from .base import BaseGrant, TokenEndpointMixin +from ..errors import ( + UnauthorizedClientError, + InvalidRequestError, +) + +log = logging.getLogger(__name__) + + +class ResourceOwnerPasswordCredentialsGrant(BaseGrant, TokenEndpointMixin): + """The resource owner password credentials grant type is suitable in + cases where the resource owner has a trust relationship with the + client, such as the device operating system or a highly privileged + + application. The authorization server should take special care when + enabling this grant type and only allow it when other flows are not + viable. + + This grant type is suitable for clients capable of obtaining the + resource owner's credentials (username and password, typically using + an interactive form). It is also used to migrate existing clients + using direct authentication schemes such as HTTP Basic or Digest + authentication to OAuth by converting the stored credentials to an + access token:: + + +----------+ + | Resource | + | Owner | + | | + +----------+ + v + | Resource Owner + (A) Password Credentials + | + v + +---------+ +---------------+ + | |>--(B)---- Resource Owner ------->| | + | | Password Credentials | Authorization | + | Client | | Server | + | |<--(C)---- Access Token ---------<| | + | | (w/ Optional Refresh Token) | | + +---------+ +---------------+ + """ + GRANT_TYPE = 'password' + + def validate_token_request(self): + """The client makes a request to the token endpoint by adding the + following parameters using the "application/x-www-form-urlencoded" + format per Appendix B with a character encoding of UTF-8 in the HTTP + request entity-body: + + grant_type + REQUIRED. Value MUST be set to "password". + + username + REQUIRED. The resource owner username. + + password + REQUIRED. The resource owner password. + + scope + OPTIONAL. The scope of the access request as described by + Section 3.3. + + If the client type is confidential or the client was issued client + credentials (or assigned other authentication requirements), the + client MUST authenticate with the authorization server as described + in Section 3.2.1. + + For example, the client makes the following HTTP request using + transport-layer security (with extra line breaks for display purposes + only): + + .. code-block:: http + + POST /token HTTP/1.1 + Host: server.example.com + Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW + Content-Type: application/x-www-form-urlencoded + + grant_type=password&username=johndoe&password=A3ddj3w + """ + # ignore validate for grant_type, since it is validated by + # check_token_endpoint + client = self.authenticate_token_endpoint_client() + log.debug('Validate token request of %r', client) + + if not client.check_grant_type(self.GRANT_TYPE): + raise UnauthorizedClientError() + + params = self.request.form + if 'username' not in params: + raise InvalidRequestError('Missing "username" in request.') + if 'password' not in params: + raise InvalidRequestError('Missing "password" in request.') + + log.debug('Authenticate user of %r', params['username']) + user = self.authenticate_user( + params['username'], + params['password'] + ) + if not user: + raise InvalidRequestError( + 'Invalid "username" or "password" in request.', + ) + self.request.client = client + self.request.user = user + self.validate_requested_scope() + + def create_token_response(self): + """If the access token request is valid and authorized, the + authorization server issues an access token and optional refresh + token as described in Section 5.1. If the request failed client + authentication or is invalid, the authorization server returns an + error response as described in Section 5.2. + + An example successful response: + + .. code-block:: http + + HTTP/1.1 200 OK + Content-Type: application/json + Cache-Control: no-store + Pragma: no-cache + + { + "access_token":"2YotnFZFEjr1zCsicMWpAA", + "token_type":"example", + "expires_in":3600, + "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", + "example_parameter":"example_value" + } + + :returns: (status_code, body, headers) + """ + user = self.request.user + scope = self.request.scope + token = self.generate_token(user=user, scope=scope) + log.debug('Issue token %r to %r', token, self.client) + self.save_token(token) + self.execute_hook('process_token', token=token) + return 200, token, self.TOKEN_RESPONSE_HEADER + + def authenticate_user(self, username, password): + """validate the resource owner password credentials using its + existing password validation algorithm:: + + def authenticate_user(self, username, password): + user = get_user_by_username(username) + if user.check_password(password): + return user + """ + raise NotImplementedError() diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/models.py b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/models.py new file mode 100644 index 00000000..fe4922bb --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/models.py @@ -0,0 +1,228 @@ +""" + authlib.oauth2.rfc6749.models + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + This module defines how to construct Client, AuthorizationCode and Token. +""" +from authlib.deprecate import deprecate + + +class ClientMixin: + """Implementation of OAuth 2 Client described in `Section 2`_ with + some methods to help validation. A client has at least these information: + + * client_id: A string represents client identifier. + * client_secret: A string represents client password. + * token_endpoint_auth_method: A way to authenticate client at token + endpoint. + + .. _`Section 2`: https://tools.ietf.org/html/rfc6749#section-2 + """ + + def get_client_id(self): + """A method to return client_id of the client. For instance, the value + in database is saved in a column called ``client_id``:: + + def get_client_id(self): + return self.client_id + + :return: string + """ + raise NotImplementedError() + + def get_default_redirect_uri(self): + """A method to get client default redirect_uri. For instance, the + database table for client has a column called ``default_redirect_uri``:: + + def get_default_redirect_uri(self): + return self.default_redirect_uri + + :return: A URL string + """ + raise NotImplementedError() + + def get_allowed_scope(self, scope): + """A method to return a list of requested scopes which are supported by + this client. For instance, there is a ``scope`` column:: + + def get_allowed_scope(self, scope): + if not scope: + return '' + allowed = set(scope_to_list(self.scope)) + return list_to_scope([s for s in scope.split() if s in allowed]) + + :param scope: the requested scope. + :return: string of scope + """ + raise NotImplementedError() + + def check_redirect_uri(self, redirect_uri): + """Validate redirect_uri parameter in Authorization Endpoints. For + instance, in the client table, there is an ``allowed_redirect_uris`` + column:: + + def check_redirect_uri(self, redirect_uri): + return redirect_uri in self.allowed_redirect_uris + + :param redirect_uri: A URL string for redirecting. + :return: bool + """ + raise NotImplementedError() + + def check_client_secret(self, client_secret): + """Check client_secret matching with the client. For instance, in + the client table, the column is called ``client_secret``:: + + import secrets + + def check_client_secret(self, client_secret): + return secrets.compare_digest(self.client_secret, client_secret) + + :param client_secret: A string of client secret + :return: bool + """ + raise NotImplementedError() + + def check_endpoint_auth_method(self, method, endpoint): + """Check if client support the given method for the given endpoint. + There is a ``token_endpoint_auth_method`` defined via `RFC7591`_. + Developers MAY re-implement this method with:: + + def check_endpoint_auth_method(self, method, endpoint): + if endpoint == 'token': + # if client table has ``token_endpoint_auth_method`` + return self.token_endpoint_auth_method == method + return True + + Method values defined by this specification are: + + * "none": The client is a public client as defined in OAuth 2.0, + and does not have a client secret. + + * "client_secret_post": The client uses the HTTP POST parameters + as defined in OAuth 2.0 + + * "client_secret_basic": The client uses HTTP Basic as defined in + OAuth 2.0 + + .. _`RFC7591`: https://tools.ietf.org/html/rfc7591 + """ + raise NotImplementedError() + + def check_token_endpoint_auth_method(self, method): + deprecate('Please implement ``check_endpoint_auth_method`` instead.') + return self.check_endpoint_auth_method(method, 'token') + + def check_response_type(self, response_type): + """Validate if the client can handle the given response_type. There + are two response types defined by RFC6749: code and token. For + instance, there is a ``allowed_response_types`` column in your client:: + + def check_response_type(self, response_type): + return response_type in self.response_types + + :param response_type: the requested response_type string. + :return: bool + """ + raise NotImplementedError() + + def check_grant_type(self, grant_type): + """Validate if the client can handle the given grant_type. There are + four grant types defined by RFC6749: + + * authorization_code + * implicit + * client_credentials + * password + + For instance, there is a ``allowed_grant_types`` column in your client:: + + def check_grant_type(self, grant_type): + return grant_type in self.grant_types + + :param grant_type: the requested grant_type string. + :return: bool + """ + raise NotImplementedError() + + +class AuthorizationCodeMixin: + def get_redirect_uri(self): + """A method to get authorization code's ``redirect_uri``. + For instance, the database table for authorization code has a + column called ``redirect_uri``:: + + def get_redirect_uri(self): + return self.redirect_uri + + :return: A URL string + """ + raise NotImplementedError() + + def get_scope(self): + """A method to get scope of the authorization code. For instance, + the column is called ``scope``:: + + def get_scope(self): + return self.scope + + :return: scope string + """ + raise NotImplementedError() + + +class TokenMixin: + def check_client(self, client): + """A method to check if this token is issued to the given client. + For instance, ``client_id`` is saved on token table:: + + def check_client(self, client): + return self.client_id == client.client_id + + :return: bool + """ + raise NotImplementedError() + + def get_scope(self): + """A method to get scope of the authorization code. For instance, + the column is called ``scope``:: + + def get_scope(self): + return self.scope + + :return: scope string + """ + raise NotImplementedError() + + def get_expires_in(self): + """A method to get the ``expires_in`` value of the token. e.g. + the column is called ``expires_in``:: + + def get_expires_in(self): + return self.expires_in + + :return: timestamp int + """ + raise NotImplementedError() + + def is_expired(self): + """A method to define if this token is expired. For instance, + there is a column ``expired_at`` in the table:: + + def is_expired(self): + return self.expired_at < now + + :return: boolean + """ + raise NotImplementedError() + + def is_revoked(self): + """A method to define if this token is revoked. For instance, + there is a boolean column ``revoked`` in the table:: + + def is_revoked(self): + return self.revoked + + :return: boolean + """ + raise NotImplementedError() diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/parameters.py b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/parameters.py new file mode 100644 index 00000000..8c3a5aa6 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/parameters.py @@ -0,0 +1,214 @@ +from authlib.common.urls import ( + urlparse, + add_params_to_uri, + add_params_to_qs, +) +from authlib.common.encoding import to_unicode +from .errors import ( + MissingCodeException, + MissingTokenException, + MissingTokenTypeException, + MismatchingStateException, +) +from .util import list_to_scope + + +def prepare_grant_uri(uri, client_id, response_type, redirect_uri=None, + scope=None, state=None, **kwargs): + """Prepare the authorization grant request URI. + + The client constructs the request URI by adding the following + parameters to the query component of the authorization endpoint URI + using the ``application/x-www-form-urlencoded`` format: + + :param uri: The authorize endpoint to fetch "code" or "token". + :param client_id: The client identifier as described in `Section 2.2`_. + :param response_type: To indicate which OAuth 2 grant/flow is required, + "code" and "token". + :param redirect_uri: The client provided URI to redirect back to after + authorization as described in `Section 3.1.2`_. + :param scope: The scope of the access request as described by + `Section 3.3`_. + :param state: An opaque value used by the client to maintain + state between the request and callback. The authorization + server includes this value when redirecting the user-agent + back to the client. The parameter SHOULD be used for + preventing cross-site request forgery as described in + `Section 10.12`_. + :param kwargs: Extra arguments to embed in the grant/authorization URL. + + An example of an authorization code grant authorization URL:: + + /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz + &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb + + .. _`Section 2.2`: https://tools.ietf.org/html/rfc6749#section-2.2 + .. _`Section 3.1.2`: https://tools.ietf.org/html/rfc6749#section-3.1.2 + .. _`Section 3.3`: https://tools.ietf.org/html/rfc6749#section-3.3 + .. _`section 10.12`: https://tools.ietf.org/html/rfc6749#section-10.12 + """ + params = [ + ('response_type', response_type), + ('client_id', client_id) + ] + + if redirect_uri: + params.append(('redirect_uri', redirect_uri)) + if scope: + params.append(('scope', list_to_scope(scope))) + if state: + params.append(('state', state)) + + for k in kwargs: + if kwargs[k] is not None: + params.append((to_unicode(k), kwargs[k])) + + return add_params_to_uri(uri, params) + + +def prepare_token_request(grant_type, body='', redirect_uri=None, **kwargs): + """Prepare the access token request. Per `Section 4.1.3`_. + + The client makes a request to the token endpoint by adding the + following parameters using the ``application/x-www-form-urlencoded`` + format in the HTTP request entity-body: + + :param grant_type: To indicate grant type being used, i.e. "password", + "authorization_code" or "client_credentials". + :param body: Existing request body to embed parameters in. + :param redirect_uri: If the "redirect_uri" parameter was included in the + authorization request as described in + `Section 4.1.1`_, and their values MUST be identical. + :param kwargs: Extra arguments to embed in the request body. + + An example of an authorization code token request body:: + + grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA + &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb + + .. _`Section 4.1.1`: https://tools.ietf.org/html/rfc6749#section-4.1.1 + .. _`Section 4.1.3`: https://tools.ietf.org/html/rfc6749#section-4.1.3 + """ + params = [('grant_type', grant_type)] + + if redirect_uri: + params.append(('redirect_uri', redirect_uri)) + + if 'scope' in kwargs: + kwargs['scope'] = list_to_scope(kwargs['scope']) + + if grant_type == 'authorization_code' and 'code' not in kwargs: + raise MissingCodeException() + + for k in kwargs: + if kwargs[k]: + params.append((to_unicode(k), kwargs[k])) + + return add_params_to_qs(body, params) + + +def parse_authorization_code_response(uri, state=None): + """Parse authorization grant response URI into a dict. + + If the resource owner grants the access request, the authorization + server issues an authorization code and delivers it to the client by + adding the following parameters to the query component of the + redirection URI using the ``application/x-www-form-urlencoded`` format: + + **code** + REQUIRED. The authorization code generated by the + authorization server. The authorization code MUST expire + shortly after it is issued to mitigate the risk of leaks. A + maximum authorization code lifetime of 10 minutes is + RECOMMENDED. The client MUST NOT use the authorization code + more than once. If an authorization code is used more than + once, the authorization server MUST deny the request and SHOULD + revoke (when possible) all tokens previously issued based on + that authorization code. The authorization code is bound to + the client identifier and redirection URI. + + **state** + REQUIRED if the "state" parameter was present in the client + authorization request. The exact value received from the + client. + + :param uri: The full redirect URL back to the client. + :param state: The state parameter from the authorization request. + + For example, the authorization server redirects the user-agent by + sending the following HTTP response: + + .. code-block:: http + + HTTP/1.1 302 Found + Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA + &state=xyz + + """ + query = urlparse.urlparse(uri).query + params = dict(urlparse.parse_qsl(query)) + + if 'code' not in params: + raise MissingCodeException() + + params_state = params.get('state') + if state and params_state != state: + raise MismatchingStateException() + + return params + + +def parse_implicit_response(uri, state=None): + """Parse the implicit token response URI into a dict. + + If the resource owner grants the access request, the authorization + server issues an access token and delivers it to the client by adding + the following parameters to the fragment component of the redirection + URI using the ``application/x-www-form-urlencoded`` format: + + **access_token** + REQUIRED. The access token issued by the authorization server. + + **token_type** + REQUIRED. The type of the token issued as described in + Section 7.1. Value is case insensitive. + + **expires_in** + RECOMMENDED. The lifetime in seconds of the access token. For + example, the value "3600" denotes that the access token will + expire in one hour from the time the response was generated. + If omitted, the authorization server SHOULD provide the + expiration time via other means or document the default value. + + **scope** + OPTIONAL, if identical to the scope requested by the client, + otherwise REQUIRED. The scope of the access token as described + by Section 3.3. + + **state** + REQUIRED if the "state" parameter was present in the client + authorization request. The exact value received from the + client. + + Similar to the authorization code response, but with a full token provided + in the URL fragment: + + .. code-block:: http + + HTTP/1.1 302 Found + Location: http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA + &state=xyz&token_type=example&expires_in=3600 + """ + fragment = urlparse.urlparse(uri).fragment + params = dict(urlparse.parse_qsl(fragment, keep_blank_values=True)) + + if 'access_token' not in params: + raise MissingTokenException() + + if 'token_type' not in params: + raise MissingTokenTypeException() + + if state and params.get('state', None) != state: + raise MismatchingStateException() + + return params diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/requests.py b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/requests.py new file mode 100644 index 00000000..1c0e4859 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/requests.py @@ -0,0 +1,84 @@ +from authlib.common.encoding import json_loads +from authlib.common.urls import urlparse, url_decode +from .errors import InsecureTransportError + + +class OAuth2Request: + def __init__(self, method: str, uri: str, body=None, headers=None): + InsecureTransportError.check(uri) + #: HTTP method + self.method = method + self.uri = uri + self.body = body + #: HTTP headers + self.headers = headers or {} + + self.client = None + self.auth_method = None + self.user = None + self.authorization_code = None + self.refresh_token = None + self.credential = None + + @property + def args(self): + query = urlparse.urlparse(self.uri).query + return dict(url_decode(query)) + + @property + def form(self): + return self.body or {} + + @property + def data(self): + data = {} + data.update(self.args) + data.update(self.form) + return data + + @property + def client_id(self) -> str: + """The authorization server issues the registered client a client + identifier -- a unique string representing the registration + information provided by the client. The value is extracted from + request. + + :return: string + """ + return self.data.get('client_id') + + @property + def response_type(self) -> str: + rt = self.data.get('response_type') + if rt and ' ' in rt: + # sort multiple response types + return ' '.join(sorted(rt.split())) + return rt + + @property + def grant_type(self) -> str: + return self.form.get('grant_type') + + @property + def redirect_uri(self): + return self.data.get('redirect_uri') + + @property + def scope(self) -> str: + return self.data.get('scope') + + @property + def state(self): + return self.data.get('state') + + +class JsonRequest: + def __init__(self, method, uri, body=None, headers=None): + self.method = method + self.uri = uri + self.body = body + self.headers = headers or {} + + @property + def data(self): + return json_loads(self.body) diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/resource_protector.py b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/resource_protector.py new file mode 100644 index 00000000..60a85d80 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/resource_protector.py @@ -0,0 +1,140 @@ +""" + authlib.oauth2.rfc6749.resource_protector + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Implementation of Accessing Protected Resources per `Section 7`_. + + .. _`Section 7`: https://tools.ietf.org/html/rfc6749#section-7 +""" +from .util import scope_to_list +from .errors import MissingAuthorizationError, UnsupportedTokenTypeError + + +class TokenValidator: + """Base token validator class. Subclass this validator to register + into ResourceProtector instance. + """ + TOKEN_TYPE = 'bearer' + + def __init__(self, realm=None, **extra_attributes): + self.realm = realm + self.extra_attributes = extra_attributes + + @staticmethod + def scope_insufficient(token_scopes, required_scopes): + if not required_scopes: + return False + + token_scopes = scope_to_list(token_scopes) + if not token_scopes: + return True + + token_scopes = set(token_scopes) + for scope in required_scopes: + resource_scopes = set(scope_to_list(scope)) + if token_scopes.issuperset(resource_scopes): + return False + + return True + + def authenticate_token(self, token_string): + """A method to query token from database with the given token string. + Developers MUST re-implement this method. For instance:: + + def authenticate_token(self, token_string): + return get_token_from_database(token_string) + + :param token_string: A string to represent the access_token. + :return: token + """ + raise NotImplementedError() + + def validate_request(self, request): + """A method to validate if the HTTP request is valid or not. Developers MUST + re-implement this method. For instance, your server requires a + "X-Device-Version" in the header:: + + def validate_request(self, request): + if 'X-Device-Version' not in request.headers: + raise InvalidRequestError() + + Usually, you don't have to detect if the request is valid or not. If you have + to, you MUST re-implement this method. + + :param request: instance of HttpRequest + :raise: InvalidRequestError + """ + + def validate_token(self, token, scopes, request): + """A method to validate if the authorized token is valid, if it has the + permission on the given scopes. Developers MUST re-implement this method. + e.g, check if token is expired, revoked:: + + def validate_token(self, token, scopes, request): + if not token: + raise InvalidTokenError() + if token.is_expired() or token.is_revoked(): + raise InvalidTokenError() + if not match_token_scopes(token, scopes): + raise InsufficientScopeError() + """ + raise NotImplementedError() + + +class ResourceProtector: + def __init__(self): + self._token_validators = {} + self._default_realm = None + self._default_auth_type = None + + def register_token_validator(self, validator: TokenValidator): + """Register a token validator for a given Authorization type. + Authlib has a built-in BearerTokenValidator per rfc6750. + """ + if not self._default_auth_type: + self._default_realm = validator.realm + self._default_auth_type = validator.TOKEN_TYPE + + if validator.TOKEN_TYPE not in self._token_validators: + self._token_validators[validator.TOKEN_TYPE] = validator + + def get_token_validator(self, token_type): + """Get token validator from registry for the given token type.""" + validator = self._token_validators.get(token_type.lower()) + if not validator: + raise UnsupportedTokenTypeError(self._default_auth_type, self._default_realm) + return validator + + def parse_request_authorization(self, request): + """Parse the token and token validator from request Authorization header. + Here is an example of Authorization header:: + + Authorization: Bearer a-token-string + + This method will parse this header, if it can find the validator for + ``Bearer``, it will return the validator and ``a-token-string``. + + :return: validator, token_string + :raise: MissingAuthorizationError + :raise: UnsupportedTokenTypeError + """ + auth = request.headers.get('Authorization') + if not auth: + raise MissingAuthorizationError(self._default_auth_type, self._default_realm) + + # https://tools.ietf.org/html/rfc6749#section-7.1 + token_parts = auth.split(None, 1) + if len(token_parts) != 2: + raise UnsupportedTokenTypeError(self._default_auth_type, self._default_realm) + + token_type, token_string = token_parts + validator = self.get_token_validator(token_type) + return validator, token_string + + def validate_request(self, scopes, request, **kwargs): + """Validate the request and return a token.""" + validator, token_string = self.parse_request_authorization(request) + validator.validate_request(request) + token = validator.authenticate_token(token_string) + validator.validate_token(token, scopes, request, **kwargs) + return token diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/token_endpoint.py b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/token_endpoint.py new file mode 100644 index 00000000..0ede557f --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/token_endpoint.py @@ -0,0 +1,32 @@ +class TokenEndpoint: + #: Endpoint name to be registered + ENDPOINT_NAME = None + #: Supported token types + SUPPORTED_TOKEN_TYPES = ('access_token', 'refresh_token') + #: Allowed client authenticate methods + CLIENT_AUTH_METHODS = ['client_secret_basic'] + + def __init__(self, server): + self.server = server + + def __call__(self, request): + # make it callable for authorization server + # ``create_endpoint_response`` + return self.create_endpoint_response(request) + + def create_endpoint_request(self, request): + return self.server.create_oauth2_request(request) + + def authenticate_endpoint_client(self, request): + """Authentication client for endpoint with ``CLIENT_AUTH_METHODS``. + """ + client = self.server.authenticate_client( + request, self.CLIENT_AUTH_METHODS, self.ENDPOINT_NAME) + request.client = client + return client + + def authenticate_token(self, request, client): + raise NotImplementedError() + + def create_endpoint_response(self, request): + raise NotImplementedError() diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/util.py b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/util.py new file mode 100644 index 00000000..a216fbf3 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/util.py @@ -0,0 +1,40 @@ +import base64 +import binascii +from authlib.common.encoding import to_unicode + + +def list_to_scope(scope): + """Convert a list of scopes to a space separated string.""" + if isinstance(scope, (set, tuple, list)): + return " ".join([to_unicode(s) for s in scope]) + if scope is None: + return scope + return to_unicode(scope) + + +def scope_to_list(scope): + """Convert a space separated string to a list of scopes.""" + if isinstance(scope, (tuple, list, set)): + return [to_unicode(s) for s in scope] + elif scope is None: + return None + return scope.strip().split() + + +def extract_basic_authorization(headers): + auth = headers.get('Authorization') + if not auth or ' ' not in auth: + return None, None + + auth_type, auth_token = auth.split(None, 1) + if auth_type.lower() != 'basic': + return None, None + + try: + query = to_unicode(base64.b64decode(auth_token)) + except (binascii.Error, TypeError): + return None, None + if ':' in query: + username, password = query.split(':', 1) + return username, password + return query, None diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6749/wrappers.py b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/wrappers.py new file mode 100644 index 00000000..2ecf8248 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc6749/wrappers.py @@ -0,0 +1,23 @@ +import time + + +class OAuth2Token(dict): + def __init__(self, params): + if params.get('expires_at'): + params['expires_at'] = int(params['expires_at']) + elif params.get('expires_in'): + params['expires_at'] = int(time.time()) + \ + int(params['expires_in']) + super().__init__(params) + + def is_expired(self): + expires_at = self.get('expires_at') + if not expires_at: + return None + return expires_at < time.time() + + @classmethod + def from_dict(cls, token): + if isinstance(token, dict) and not isinstance(token, cls): + token = cls(token) + return token diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6750/__init__.py b/.venv/Lib/site-packages/authlib/oauth2/rfc6750/__init__.py new file mode 100644 index 00000000..ef3880ba --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc6750/__init__.py @@ -0,0 +1,26 @@ +""" + authlib.oauth2.rfc6750 + ~~~~~~~~~~~~~~~~~~~~~~ + + This module represents a direct implementation of + The OAuth 2.0 Authorization Framework: Bearer Token Usage. + + https://tools.ietf.org/html/rfc6750 +""" + +from .errors import InvalidTokenError, InsufficientScopeError +from .parameters import add_bearer_token +from .token import BearerTokenGenerator +from .validator import BearerTokenValidator + +# TODO: add deprecation +BearerToken = BearerTokenGenerator + + +__all__ = [ + 'InvalidTokenError', 'InsufficientScopeError', + 'add_bearer_token', + 'BearerToken', + 'BearerTokenGenerator', + 'BearerTokenValidator', +] diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6750/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc6750/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0dd8b5a046f094ea764d822cdab57e3f991234b5 GIT binary patch literal 836 zcmZuvPm9w)6rZGR(myV)vUncwphZlU1r>@eDC)W*3U1d!2o7oT(hi+u!em-;7i7PM zcQ4`x@O$(mC09@00()C8&P=!HsxOZ>@BL=p`@OuG&l?+Eq~zz`S2(s2`mTeusMyHq zbG3X#2?|hRB{s7%JFv4x(6DseV9l%*w2a?mPUZ%#@ms8&b%KtCzzw=%lsKQPpqID@ zsNX*N*2PMqnVc{>^0;<(JdwtC@7>upTOa-_U9&fw&=O}nnK8fu3IQeLvcwTisDM~v zniUK(g+-F`9P{)%3-GIliU{v`+gLkX(4*Cnry|PW9T(F9egu&KfroqwIX*0-F?cK1 ziIhb-@O{ZSD?JJ_^|%=O6PYo8-T4no4XSTfSN8LH#AsrwJQ0G6>e_x@&eD{|R5f-G z^8yUsx2nx3Nyy015~*nwwzX=*1Z26se5@rtH4EoG|SAL+u;u&d0= z{-w$#B;he3l>@r1@^@y{Eh0Sz2?{k;TBaM5Uv=j-sNWWiz{)jjA_@%bWgu#PGDyh50V z3%X^qQL)@B66j`bg&G7iLKg|;?Xv5b3|E-tEMPuGFPEuXrk3szd}4O?XJRe$bg#m& z;hHePF|p+scEuzNyAHu_K`bn|w(VZ!Y{Y%UnXb!sgXy@Pm-Yq-bhpGe zzo0t{YWkltC?+TQ86mVOAt`^$NoP^FEpyhrLY$y$;H1MUg@R>R#PQAob0YeUP_g_s z)biRiG=2&8K~P=-8<9;ZA2a2A+>GTDW;~zlLS4vImQg`6lQ+BaDN#$^RPxYwP0DwH z6?D-!Fwu{KDa>+V8wOzvd;CBcJ>o0!CV&NMGMn-g)psqpsX`SlAA)i@H$`!TC;(CDSd@Jm=cx;PNk6QB;kFcEL#~HB;eg=HipjMeXlOL;4%g+QF*0@UpL-21x`ITrEh~K4Y zhOINEX-t7O2Q4T|&*zREoP!nMXLIM=!t4p%xWeW>B_&dtC!k(~I0l(h7m2et_pvoU z$1IPGm0^;;K-gRx_QqXanF@V;T%ZM0!L2z!R|hvZsT$sMH;l6*K)zc-|4_PbrS7C2 zE88C_+nd>K_xtZ(`S!i1F{x|n83NMc zYkz~@FD35c-&djQm3~87KsV%D=yIe=y0a#)M5^Q`2#YCo&if5A<*#E8;2aO56G{kX zL`Fj21x{hW3Ymys0XMOmO6TljX#L4v=Dg{t;=qNQxhR{RYK2Q~Ls`G$jo7ApBx=4r+K5j8R6+1GU5Idw>xJP? z1a1I9%Migox>Lilb$Q>v%c@KOMeKp!bTphl!)l+rU2Mdae}7h zL}v;EH^ixSpn;p276%hJKf_mvZMT7(@A`cL``&1iYD$3Ek>Tgk@H+40R@e{!Yx{w4 zuw6hkbaCqqsV0H-pj+}~=nqOw+7VU}j7eX|@5y%tK;v>%J~B)PU@#{Mgv-TzS)K5u zE3_Lr8TU-UH_G>Uo<3|tLS?w6@^p1_BN{CbPYZ;{)Wf!GfYzs>5-vH!`Aq=oBT>|{Z}cD@?|OT$nQX8|LQ~i+wYD1dgO86?niyQ zSNld9eIv`MCtLcLlg-Qh;l^xNFqxI1v^?{?ox2nuEl$p9R(^THL+jG08+5Ps)j&EoG zaN+kC{a%mps9lb;#%%?T2 zj9v|=dH+fq>fz|yHFAN;tvYorxRBqm#E zGtx7V*w#Y-8xc}4;22Q}1L7LLf zS+r~d*$JR4z;u*?!;=C~Q-D(^bib5Yw_j1ONU#N1N6)8y6MONVpSX11G9gf`%dW+9 z3XGyW184z>@oIgz*vzG4*eZvJ-Ad7AA;@dXw~0Zl9qlkV3^wEL`%N0KIX zubzAju|}um&mPtK6)5RUE=7L`8lybNqwjJu!pVAj{v8rl5g062u+Z{xsIVN6&{~(! zdV76m>3Fm6;?k*R-`1s5{7-N>14hF4@ZP19+$7mOAg!1rNi8`m#aoDzK_tChM>{*eRuUz)*LO^|Vsb`aO108s5;(&~azFEw c_da_ubV-uvtoL*mH)0SCj6-2eap literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6750/__pycache__/parameters.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc6750/__pycache__/parameters.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7adc265d6aa0af7b648dc6b2bbf88f98037a6cd4 GIT binary patch literal 1807 zcmb7E&2Jk;6rb5$d*hGTiSwbVB<-k;2v)$cpoJ1#P@yQGA|s{kC9)JYJLA~IyX($u z5)wI*4>|b2p|@B?4XOt|136V@F%oFrwNXTGr_hHTLkb0b>Nl z2#rw_#wgVvqHO$6xkXkBM=VNL>K3;gvEq9xPeeF6xU#{k_UU=jCjwoEe)0y0edJ>p z`mKQ}ZlJQZhJOH$pU=GDJZ zik=UPw&ys^rHsBwHUuM{TiYhpGO=q_=K938+*w~KtPQ{7@#>D{S3Q?hm_^|LkCRo8 zZs+1^!;0_M7v|@;wzhKY8_TKJSPpiduUmfQBg?j#ke7#u?pAKy$^!dpS@KFBWsO`lDtH%x;pR4$=mb1Y`^>7?L0&X%rKvEk*jZqaY+rZ1c!2& z9WoX%1)_=mN}}X+`{68?&cBZ-5y`FzI z5nRv1*IaCU*)gWNiA=M|6JR(1-q{1lgGPea)Tp+LFFXYOUmk+7^WeYXJeRrWv+vdH zEQW|jAq>b%$>%8)hTLEPheRI-so>*adIh?89Rz?7M?=YGqnjRW8AplN+V?L>A_YSj z?ZIeE2u_;;6O~Kf!UW(jDBeVTbN~(jX|N*fVs{QKHDxKi`>lZ*+67C^odipLT~!l4 z;-5Pktn~}ldILAKhF+F6&M0PeJ_I|63(1i`6iMr-UFg_QU@;gdhX-^#J zoz%=>YNn;P^lmH@OwI){`5k4*!NfDOlgS@u@-4Gvg7Rtkd2A|(O&z7Lwr?NIbkehj z>DiXiO{AWh?eQQn9T?M!oh&Xw8pz9K&2X$=Ph^>MJU0gb2$dqLeqFe+ikGLrQ*ESf z^tcyy!2KIF2%$SN;5h+`dN+(n-Rmwm_4D874)&O~Mij~$~yF=qK)s>ACd?=T?Gkq6Bp4ecOJ*z+Lt3VzO*N1Ep$iim1; zfqf-+@=gQfIU;CY(9pa`6Xr$DGw;;^!cWw^fAP*st*8}gLCv=#%=@&K9W>uU{F;9U z?SbqoR}n(^D6iR5?ctWzXBul7b8B}>AAmk9R#VB~W zO2W@pbae%*N*1e>C>Fui3c)#LBV#BUUNWdFK#7?%vL*>&7>gVDUNUd3;0bIJx=v^e zC$Y7W(^Vz&9zT9&)NCA?dX-dkfN@TC=;bd zCV{g?)C6BR7BHpvsj|GLaDvKM>&N&*O$Xx}R8*Cirp!Gzm>68UE&nohV|pn%6}vR| z^w)!9&D@+#25%7Hb)5b_3;8yugF|IKJD8ZfJU;%O21=HIx>DQFn%!KVoV)kr_V_om z)4%z4BAvPW^_}EkZQCu5=^dvK(osBwB3}E90@q_ueUp1hW-hn=`Wo|_ZrT2vVw%qk zs@Z4Mj1G>K;qEo~>Pp5;snwWgQO6=&gx|Yy0MAiDC?FXyXB0dzgV1tkBFt(Tp`nN9 zdm$AO?e0eZ$+gI{dz$QQAe^rHr^X8wc}e=Om zN5)e6OGSNRE<7M>WNndvFIAFN$wF+MWY-tI(iay@-6GK(Fe%H#TwuP+=!+E~6d|`rp z2M+lEJK#bpb8K}mQ@Er52M9PCtyU>$`vS~rZr-iAxW)hoyNcDCzUJbzC1%rBYn{7M z_a5kdRntv-3TU^^*nq*sdroMLSnMj?(Wup8x8sgxDe7iD0N*<)TU;iVedgB8?c}4c(v1W^6rqf=m?3sRH}$M( zDRB3;sAsK+mqK|*w$BNAJFrX@h<%o-cAy$_AW@Af3JHbmc8E+%u9G(}emDr4xrRa1 z+yStS%5CkXwhISsk#e}d6rMT`UpWe2DR=a}xK%ng`BoJArhh^JigU%e|Ae}}(@NcA zhoNXG6s;hs^%4jjhvP@#_`dIT;4pl%6u!wg{}t+a;Vt#Xeh?2sQ>D;U1&N%u6pl0U z8@APWajx7RKJbTW2OLCgj2jjyJlduJVQEdfK7RAfF|s8Tgz6m$_GxA|INW$fG}%;* z9Eo^nFDSJoJ~P>_7;{(Be!w?JKIpy^YAykYOajl-oOtL2h1JZ2^hu@BzZ@^FnO1Y}&0-n!b=V-sbq+@&a!y9~zl~S15=D@85(y z2#{ASNch-lDM;JhAl2yKDv{;odryTeNfQe#(DXf9{(?lMf>iKp(p8Ws_~=k$HqdjR zwU*O0m5lQvX8}z*Ro1YRO$q*RaBx5s3$H0ppdRyON}lG439_tMv*C)?6EK0*Jf+Zr zu**v{T&JE8%)`5*E>b-&$S}eQ?t1bju)c(I)L7RwqKz?bIG=9fbtRJrr4%Bv>d%Gne% z65Gzv)b&A2=@2m35tnzW`D5p8%k#_M+2W#~mX_9V5Hz zFY|{T)1{8-qEzlVd)zZ|)H6~3EWEqAZ~Zu35mE2tTO{<(2~b)A7K3lvx(?dlay(QvZd)Bp1G*Hb^{VegR}0&G5#Vw(d5@%UkI(5+%a<^Dlf z8U16bUb~t~mmh59rRy>vpD10>kXbo`^5NTqa`%drJU(j0nU2C7`Y3C9AH6=xI~A*) z?ghEmBg?Fhe&WsJkbet;=6L|y=uP`)f8P4j){FU<-TR&U`PZulbMj&P<5K(M1OH=Q zqa&VFD&kG0Qt3#Ly{fXx8j)o?Aj@lpmd`LeD9catO2(zM$g*arvP?Uf31=8+XMhE# z9fa0y>FOGRm#*eSE;E=$0DO=5hECgI-lPn$x^Dg*z;^Ag;^~n56~w>@>Ki!lc0)Lv zA1-(HLboXoT&%Q813qZP1HJ=qU!?l)50I zq^`FjOm`NXg#fyi6v|hwR>XcrZU)zDM31Bh5M`f$j*ZN+R7Btw(l|`&rvL1}>Uj1# hW$$-x|6M>Tq96zr&)0&$w)ptxtwa0i6D)kQ{{!Q1(F_0p literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc6750/__pycache__/validator.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc6750/__pycache__/validator.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..230577d383caf76388143223909d9f5ff89189bb GIT binary patch literal 2285 zcmb_d-D?|15Z^m}Se6voQA|lODU0P&%T44`oQ8@fA!%GUP3xB0DOAWkPIoKoYMoBm zUAc)dtucZA3GSomgVW+X^d;~86RaReI0zK_ls6T(FX>BX_D-^e4S|xeZ*FgPc0PVP zGkS39RFVMwJO7B8F+%>tj~>CdqJ!)3+9ozB5nHqMy5{O7T_bkHj@Bb?v=nt?rI1DR{Vex4^5`dzUW0Q&=&)bg(%x*me>4@ z(hrSz{JDl=-9LS^p@LDnbDVqJf9+;Nw5nCda#%wyqCF+I!VJ|5Pa_??0c@KvQqll3 z-PTGGTfa|AQ9A-WW=8>wm_HVTJQ#r=uc$;U46sMIMl3_SvgZdxyYTG66VR5H*GvPp zuThuDnuqyPz<}Qi5~o$}xfC!qE2d!dJ4e>2tTDRctO05Y8!9As8Y=~bE?(9Rw#Mp^ zE*JE(+lxy8>IKJb)|m@9z+p#(t_t)cg}RVt!(zo^a6f1P$!1k`?QqDkOvw!8Y)Y_t z^?cyi2ps2&eb2#33La&PH|PqJ!6^f?FnU=`DNDW6hhB?Klbh~`$ut%?CECyE*Q>7y|Tygo`_7&nS#%d-L8 z@@=oW^s#BJit?9$qg!DRh{XW5ase)4t^BD|DGNuk3r$cmSC}Y=Ei)6e%uLuaGyRq+ zH1GLYR2l?${jHOVtZ-a03o(jOV4LKhF)}jI&g43o+zp@QfTeJT<7h1rrzMMP$ABVU1a<)Tsu=NTKsgOG4+W!RDIMsxhJ3 zIh=dU4hEknKw-u>GwZHD%I->T8m5FUue2l+3;6`cOgL5mKLgB9I>KOgn+|8TT64Ar zQ`7ddYK$7rkwNGWV^=CU$Gr1Vo<(U|aJHYGuOm4X43+?!;mp zRKn3J9s%1Ve~gTEi8lO=_AHzGW%A+l@3J#r-p?+#v&)_A@_u^xX=?OIYW#6(yq!AN zNu7J8$|Fxw6OU69I~N~Z{rPG;H`~e0{#I?LE_YIw(a+n@vQzEsbSFE#pPueUK%k@? zTWld8_Y;QEFkNOCe$p^p&u-Omoi>a+EwkR+S^E6e+=8+6^%rv-%Y%;t`;{mg3P7Gf zDKgv^mw;{d|DK+Hee;uUG#Q)hl0G{-9D_iPv%n@=TF4LiLxy2{7Q{28=FIH-9Q)Ld zGyEkKLAl^<2mUFpFfSF;i^K;(I#>84$Z!;hAAkV{n%320TC_`$Wr+6XKAAlF-_;|U Z-X$+*>9ZPSah&~hAwS|_YsnS3I6&}` zNHQdn%0$yT874I1j_%ayFh!iook=p>k-M)*ulw$6#?Zt(Otl*2HiE<4jjQ|p{)0C3 z{=b&BvB6Y%R$DpOz#KFVJec5_U{X1#0#kLPp~gEAlr_wb+pL!-ScDzseKxQ&FzgH# zwrUyqMs^xPj3Q z=}}o(sm!E&ZO4OWqMG^g3>&UTfU~H;R8Zy%FpKiJ8kJrJxYHm>Ou&~{BQG{1-}Y5- zu8azt=gs-$-owpokKJ`F7aR7c=++%d={nh?>6%1$lhAuha`*53jT|ih-QTbEmbV`* Nv&SF0ak==Hegoj(wg~_L literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7009/__pycache__/parameters.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc7009/__pycache__/parameters.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9cf459b8f3d479897d66180f9eab676295636bdf GIT binary patch literal 1147 zcmZ`&&1=*^6rV}<%hs*mR#9riiwka2MNqe`pcWO86|{Pgh23ms(hW^A>C9|vCB;2> zC|>ktkDmO%v;W5yJS;g0;=$WOZ+h`fHbqPEC3*9aH^29O@4fj@E{`FQ-*>*yCptpk z)nZ4qY_dHCledTGs@Q@tQU*e}4(H@~n{--jo;N+l9NHemz9f+o6&1F${ zav6>q)ExYv?HCkb;uyKwB3{qMm`}#Jcd)xxh!$g4dyf(N4BtpFk_so2Sc@>x=p}! zTo^9n@Nj!Eh&_NDx2}EHD7B0CKROcn7IpgZD&a|9@2mY zZ3;DWz$0y#D>Phb-1piI;YnJJz{p;tqG5Ms$M@P6QgM@;~Ww9j}MB2l+Nv_bXI@B}(IxtZ@zO!doWdbbC~<3oh=vxCya>+-8|fAaiC ztAD(aviMDh1py09NU%s#m`3#p@d+^I`$7FG%?6BgeR`cA lf~C5CVh+?$#~2ULbbt3dETC(1gUeTk`Z0WRi2kEe_&->NOsxO_ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7009/__pycache__/revocation.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc7009/__pycache__/revocation.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bb048821ad4184ae18233eea793f2f9855e0484e GIT binary patch literal 5186 zcmbtY&2JM)7B7FsNu0z91cH{2f-pFS#D>5^CbNtLBtRHQGKsUycp^3J?sDA3?)Fr- zlSyPGw3;1p7-_h{VYSL(#e&$wTvpn{{sDV*BJU<@32CK0ar20o%j{*}>vp&8#E3!L zv7f7}UcL9K>b>84l|OfNbr5*|d*iR{RSzNm!58NV)EaMYLE{OLiR{UdyeH-H5ZNpH za^Acz<+Iv;X!}$Cd>|F@5HGnw^}A0aQ{Yd@)=+%`{Qq1X5t^O*Z(mJy3N zL%6SNs*q)(%((vAYY%oMwPmJGs&YY7R3qj!_f4rQVos6g*q2478cv7q z;|7zh3CXnrvxX#Fr%gSzmp2!n@q{pv^2j9Rl|3n+>`nP)-`6A+ko`b|XnLwm4gw9y zZ9v=Q5E$KV_RX;sO%e@7bFEtcW-4FEu{=`^tDkBa%3UtXYR1#mtRiKpqEnga5?9hp zri$7@;kh?={o19oXFt3r#5=5xc$^BgzHyp0jDkL%NEn)y)8h&=GI5PBC9+07m*5!* zCt8!tj=EOK-ELTF5We{S#^uqX;O-%KWFUG-p@Vyum%HF<5^ zK5mN*9o^NBJ#&+vE=RB?40U1Emib<0eyIgu+>Fd!U+ zECf)K{F&M0)Xemi+aUi6#ZfAzwW2K@XP_UWCR?#yOy?B?0t}bfB&Y6makt+LShLI? z>!)tObSz+or7V+{1#63SvlHT&uL(B0AGgo+!CD+Hdzml%re9~djM-K@Lo;X(@G!WC zj?RLs{rTR+_#zwx9N6N5mPy_erDc6_4ni}ZW*njpj)^VCSD3o8cw0#?>WaZe3cw^T zF?~@i8rhtZPH5N|bwVrAu)M;W*@uI8g5UArl>qAQ)0C`BN1Ejrc zJ9KC(bm(bxsj&eZlfWNpF!`-+880fYvSE-5y54E#_o7`BD_TIyK+HG z#AvV2+O0(<5asZV`KGM{=Uu=X3-Ad1a6~uW3&iZ7UznYpnM+Pi2+5gGCZ~nu=d+XZ zybYQCd_VH_BRPP~e)M?PbNE3V=mxTWti@?Idh8%D>1iMj$xdhA)94?D%blm-^Q!NI z&Aw=*FIo;q|J`%o+tPN=v8|qCWqNM2XSC8Y`pCc2*@FiWe>}0_uh8-Ge*C=ZJG0q0 zQt2BhhezPOicxWTD>CGTIn&6NOD4L*e!R_$Rc$N-cBjQ<2M{#(rQ5Mzz0)B$i& zm8rxTjv_!oWETMG86r~ydmW9gLqGdU#4J5bMF%?b;u>&UWkgMkli3mZL>S9}6)e*05~I9(~Q%1rl6*|R{*RuuB=;i$vC|#>WW0A_0%=-#@xJk{`%QF>jm}h#P$5A zd1#N`x?9gjXrBejmoNN!DXSEhbMk#LE34UcSuC!f+J)wVqMBOXGW2$`ZyiZ zp*kw+0_MqKipg)7){4EDYcs%W29mCTn7dqq*O=Fid5qfE{{RvTnunX<)v2(AT22@M zCNtb9!wlM+YAs5EcZ(wh95tJW%1hx%EzL+;uJVXM7YWYOs>3*Ch1vWf~PFiRrrSzR|t2 zaHj3bG>Nn0wjt>?p>g7nE!j4v?$tOMpSP%P3Z3`T-8AzZ%HP*|3YgjI*|q#%V!{iL zxo=uC+*=Zpt-D#wXXRuw+_-C2YS+;%LAjlk;YLc5dXy2x z4binCmss82sru?6yGcck+eGuYjgIB@jcgU>_8RPHY>e|^C)c(JZ0iPd*41tC+5Lp#f2f!rK^$DyZXQQUY)pW(Dx{0;4izv)B5H`3witMg4YwvZl1svmi*R& zeh&S{-lmWFDD+`=*1rP+mjsVzha}3)pB*w-ZvIrgK99Fb-c7=i#{&y$O`jh5!5aDT JE#sEK{{zi*U6ud< literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7009/parameters.py b/.venv/Lib/site-packages/authlib/oauth2/rfc7009/parameters.py new file mode 100644 index 00000000..2a829a75 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc7009/parameters.py @@ -0,0 +1,25 @@ +from authlib.common.urls import add_params_to_qs + + +def prepare_revoke_token_request(token, token_type_hint=None, + body=None, headers=None): + """Construct request body and headers for revocation endpoint. + + :param token: access_token or refresh_token string. + :param token_type_hint: Optional, `access_token` or `refresh_token`. + :param body: current request body. + :param headers: current request headers. + :return: tuple of (body, headers) + + https://tools.ietf.org/html/rfc7009#section-2.1 + """ + params = [('token', token)] + if token_type_hint: + params.append(('token_type_hint', token_type_hint)) + + body = add_params_to_qs(body or '', params) + if headers is None: + headers = {} + + headers['Content-Type'] = 'application/x-www-form-urlencoded' + return body, headers diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7009/revocation.py b/.venv/Lib/site-packages/authlib/oauth2/rfc7009/revocation.py new file mode 100644 index 00000000..f0984789 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc7009/revocation.py @@ -0,0 +1,108 @@ +from authlib.consts import default_json_headers +from ..rfc6749 import TokenEndpoint +from ..rfc6749 import ( + InvalidRequestError, + UnsupportedTokenTypeError, +) + + +class RevocationEndpoint(TokenEndpoint): + """Implementation of revocation endpoint which is described in + `RFC7009`_. + + .. _RFC7009: https://tools.ietf.org/html/rfc7009 + """ + #: Endpoint name to be registered + ENDPOINT_NAME = 'revocation' + + def authenticate_token(self, request, client): + """The client constructs the request by including the following + parameters using the "application/x-www-form-urlencoded" format in + the HTTP request entity-body: + + token + REQUIRED. The token that the client wants to get revoked. + + token_type_hint + OPTIONAL. A hint about the type of the token submitted for + revocation. + """ + self.check_params(request, client) + token = self.query_token(request.form['token'], request.form.get('token_type_hint')) + if token and token.check_client(client): + return token + + def check_params(self, request, client): + if 'token' not in request.form: + raise InvalidRequestError() + + hint = request.form.get('token_type_hint') + if hint and hint not in self.SUPPORTED_TOKEN_TYPES: + raise UnsupportedTokenTypeError() + + def create_endpoint_response(self, request): + """Validate revocation request and create the response for revocation. + For example, a client may request the revocation of a refresh token + with the following request:: + + POST /revoke HTTP/1.1 + Host: server.example.com + Content-Type: application/x-www-form-urlencoded + Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW + + token=45ghiukldjahdnhzdauz&token_type_hint=refresh_token + + :returns: (status_code, body, headers) + """ + # The authorization server first validates the client credentials + client = self.authenticate_endpoint_client(request) + + # then verifies whether the token was issued to the client making + # the revocation request + token = self.authenticate_token(request, client) + + # the authorization server invalidates the token + if token: + self.revoke_token(token, request) + self.server.send_signal( + 'after_revoke_token', + token=token, + client=client, + ) + return 200, {}, default_json_headers + + def query_token(self, token_string, token_type_hint): + """Get the token from database/storage by the given token string. + Developers should implement this method:: + + def query_token(self, token_string, token_type_hint): + if token_type_hint == 'access_token': + return Token.query_by_access_token(token_string) + if token_type_hint == 'refresh_token': + return Token.query_by_refresh_token(token_string) + return Token.query_by_access_token(token_string) or \ + Token.query_by_refresh_token(token_string) + """ + raise NotImplementedError() + + def revoke_token(self, token, request): + """Mark token as revoked. Since token MUST be unique, it would be + dangerous to delete it. Consider this situation: + + 1. Jane obtained a token XYZ + 2. Jane revoked (deleted) token XYZ + 3. Bob generated a new token XYZ + 4. Jane can use XYZ to access Bob's resource + + It would be secure to mark a token as revoked:: + + def revoke_token(self, token, request): + hint = request.form.get('token_type_hint') + if hint == 'access_token': + token.access_token_revoked = True + else: + token.access_token_revoked = True + token.refresh_token_revoked = True + token.save() + """ + raise NotImplementedError() diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7521/__init__.py b/.venv/Lib/site-packages/authlib/oauth2/rfc7521/__init__.py new file mode 100644 index 00000000..0dbe0b30 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc7521/__init__.py @@ -0,0 +1,3 @@ +from .client import AssertionClient + +__all__ = ['AssertionClient'] diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7521/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc7521/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..98eeef93127e3a22047b887afc040f8093e344fa GIT binary patch literal 289 zcmZ3^%ge<81i#(4raA-Z#~=<2FhLogC4h|S3@HpLj5!Rsj8Tk?3@J?Mj8RM}%)tzr zEH4>>(wdC7_#KOjQ;SM6^Yff@GE?(PikN}oewxg;*pdilbNKS4`LYU7o{ben;IGF$H!;pWtPOp>lIY~;;_lhPbtkwwJYKT kS_g7!u`-bOz|6?Vc!NRt0xEjIEpvfOwt*c4i`aqc0NW%`RR910 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7521/__pycache__/client.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc7521/__pycache__/client.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3f8c34eb15b8cb9e6b38f85731140973467007d3 GIT binary patch literal 3928 zcma)9T}&I<6}~f`F}BBG2h2aX!%q_2E+)xl)rM|crGb#FvJeH*AB$?%crIXKJl=bU zM4^M0R#c)=RHYSCwyQ|XLzV6-`_PBBYTx?UM}sUenkS_8rBWXpC4Jex^qd)cz=X8D zz`6IFd+wcc?>*-`hu=0gM+mfkPyK=Z7)F0XrrxC5;N>@9@Pz0@7Ybxm$Or(lnI4NnCKB*+7dEh8qwt~@(k8I_jk)E zR9T7ESv~mryxz1$GR=AjXp0^O8q-BES#e@lIj79b8^vpdJT02*JJ*aNH`!Xw=^hlSNkQcTYBgRuJX`{(Jzqx;qd{ z0uI08HcJLB=yR}-*5q?x;6gq}R>Jl1Px>sf>vMG}_Bydb7I_BWetz_QqWLGZBCsc( z&uu!HC7%n^si@P$Dd%v}PK#;WqeYDt^^%b&ikJ?TW2 z@HI5^VTn4yJm+ha!3Jv!D>P?1q3oItkDi06Tp^oZ<&MmA2582;owM++8q9F+M2;j* zlXmYxmMw8`ABoe#B14lITFP3G#E`_1G$T0!#EE(9ONDHXu7aPjR+I+4jX17Ff2p-E z=O@PJbB3NTF3sOH7UyncbNBfC9ay-!KpEvZw0S;#pBC@W-^wq{^Snt%OQ4ipqI@2$ zF60-+3>;jl`_Wj=_3w1)p%c=yd@*lo+IpAo+n)EQ>oaIQ{~3@?QVo%=uWU^=1h}$4iMU0i7eePmmH=2XGvC2KrKuJ4U_*@IvC>KcB8PJ z|G|`W5_k}EQlb+E=<>3g2So@vpOaL?IdgS(cJj{L&6#QK{mHo-GZV9(!U_DsZCE=J zd`%CtTD021YrZMDzUj0s(IRD8lWIrb9DqfRq-V`6M-RYLyAkI!H*B%qe=_zOrZ2%# z{%atBMNyI*tn>p`{C=j=KT!_#*okxH#JMU7wnyx?&Yf@CiLRYnc6;~Ek6gAIh6#7J z8X*wCg{o2)Y={39Cp|;ESN6I`E8U}ZPx9$lRSv{K9muu>xEGB-8m|%|eBSO;pT4&} z@woHn?*j}R#0K|cgS(gaVk4CphSKYJfKGiph=e12(uI3&2(W}DoQ@5R#f<>LwR;?E zU~8{6>TQTRB>ek?T>zK&gRicOy#*RaVQY!IepnvY(oY1&7bmK{p9*eC;fFBX_~jEmzV=f)O3L{74RHUf}kvUP>HwT`&^=wWw0mCLWM^??_D20>3XMW-GqJk zM?f}-o40yD=KIQESsApW@q_5Veso|jI#h`cm7_z4@x+txufo4nc9d<|R$3oZ$eEZn zTRRR~NA_Ds?2g`#r*?{V-@vCgKe<^xcV(|{ywW#bl}TIb1qrmZyg~v#*xUjx+tKSL zOYq$Fa;W>i_!$H18o~N>-_oH-JO7a#w9~0LR!K!D_chIlXxgfwuN80{)wB=SvW41AlcwoLPSY6v z^TCFYv?0OEWMfFMK5;@N22~|9AG&Vo1R=4T;KS!p0q?>+EgQrURu*1Wf)K)xV07_6 z1KIR{s-h%^ssu@d^d!qthuzgvmfG#k-m;XiyM|y42fgww`{FxQxl2w~Nh7&Tf-O~1 zkk10V$!A{#fZh6mCkT?DvNez66i%javb8P8RXOB|hns?`6Ktz5}~salk2% kYCsSKn~atle{J%$a^r6`_&q@Yb5Ex)T=}av%(|!g5AEKGCjbBd literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7521/client.py b/.venv/Lib/site-packages/authlib/oauth2/rfc7521/client.py new file mode 100644 index 00000000..e7ce2c3c --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc7521/client.py @@ -0,0 +1,91 @@ +from authlib.common.encoding import to_native +from authlib.oauth2.base import OAuth2Error + + +class AssertionClient: + """Constructs a new Assertion Framework for OAuth 2.0 Authorization Grants + per RFC7521_. + + .. _RFC7521: https://tools.ietf.org/html/rfc7521 + """ + DEFAULT_GRANT_TYPE = None + ASSERTION_METHODS = {} + token_auth_class = None + oauth_error_class = OAuth2Error + + def __init__(self, session, token_endpoint, issuer, subject, + audience=None, grant_type=None, claims=None, + token_placement='header', scope=None, **kwargs): + + self.session = session + + if audience is None: + audience = token_endpoint + + self.token_endpoint = token_endpoint + + if grant_type is None: + grant_type = self.DEFAULT_GRANT_TYPE + + self.grant_type = grant_type + + # https://tools.ietf.org/html/rfc7521#section-5.1 + self.issuer = issuer + self.subject = subject + self.audience = audience + self.claims = claims + self.scope = scope + if self.token_auth_class is not None: + self.token_auth = self.token_auth_class(None, token_placement, self) + self._kwargs = kwargs + + @property + def token(self): + return self.token_auth.token + + @token.setter + def token(self, token): + self.token_auth.set_token(token) + + def refresh_token(self): + """Using Assertions as Authorization Grants to refresh token as + described in `Section 4.1`_. + + .. _`Section 4.1`: https://tools.ietf.org/html/rfc7521#section-4.1 + """ + generate_assertion = self.ASSERTION_METHODS[self.grant_type] + assertion = generate_assertion( + issuer=self.issuer, + subject=self.subject, + audience=self.audience, + claims=self.claims, + **self._kwargs + ) + data = { + 'assertion': to_native(assertion), + 'grant_type': self.grant_type, + } + if self.scope: + data['scope'] = self.scope + + return self._refresh_token(data) + + def parse_response_token(self, resp): + if resp.status_code >= 500: + resp.raise_for_status() + + token = resp.json() + if 'error' in token: + raise self.oauth_error_class( + error=token['error'], + description=token.get('error_description') + ) + + self.token = token + return self.token + + def _refresh_token(self, data): + resp = self.session.request( + 'POST', self.token_endpoint, data=data, withhold_token=True) + + return self.parse_response_token(resp) diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7523/__init__.py b/.venv/Lib/site-packages/authlib/oauth2/rfc7523/__init__.py new file mode 100644 index 00000000..ec9d3d32 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc7523/__init__.py @@ -0,0 +1,37 @@ +""" + authlib.oauth2.rfc7523 + ~~~~~~~~~~~~~~~~~~~~~~ + + This module represents a direct implementation of + JSON Web Token (JWT) Profile for OAuth 2.0 Client + Authentication and Authorization Grants. + + https://tools.ietf.org/html/rfc7523 +""" + +from .jwt_bearer import JWTBearerGrant +from .client import ( + JWTBearerClientAssertion, +) +from .assertion import ( + client_secret_jwt_sign, + private_key_jwt_sign, +) +from .auth import ( + ClientSecretJWT, PrivateKeyJWT, +) +from .token import JWTBearerTokenGenerator +from .validator import JWTBearerToken, JWTBearerTokenValidator + +__all__ = [ + 'JWTBearerGrant', + 'JWTBearerClientAssertion', + 'client_secret_jwt_sign', + 'private_key_jwt_sign', + 'ClientSecretJWT', + 'PrivateKeyJWT', + + 'JWTBearerToken', + 'JWTBearerTokenGenerator', + 'JWTBearerTokenValidator', +] diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7523/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc7523/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..379a23fd211c99f9947a3025704bfa670a1181b3 GIT binary patch literal 1111 zcmah{Piqu06i;Sn|IBQ+RnXRBPU``YRFK+B)?@1$P?;Fr0~#QCQj zWm@?RQV@a^rVfML2_0zk8mn3&1~qr0%2*9|-&u_V$`Xv>WgOVz+yQ4ncH=sM+MVtc{`NhDGD{Rf2$ zI?T&!V@W5mB6yeVpICMLLPfD-!!>W&*{%X#kbN^bESFBI*&nh_aw20Tq)t9<&AQHq zzKI!4ZKx;pIsxe#s2gY)Xc}l4Fl#4018ohP-K%92<5VOVm%bTcVCT0aWuuzVl9gUO zoBfoxbj_NavX^ybUefZH-elHPRn*io#bU-V{sxZp6&$~Nwh|>GrTH*=EwcXeIN2?t zS9(?WfaonsNS=@=n2>xDy`+Pvpo-iZ>!5f@ipUh#%i61!b@rS+jA>34#=&_1xb?W& z%2m0f%b9mBerTB1AcRxLgYFaFms#w{L#l z`{w=p;`b{E+TRPmkv}Db{$M}t<~d+qF9GueX-LCqw9IBt8fQGq9?WUS}~g#*#`N9Tg=@u7L30O~V@60RVe#5UA+2yi~BfmZaf}a6rSBw1H`# z$sL~7JUejv9*kD|23y$jXxvjzQL#8U%~=4Dowj%*Y%-e;nhB5BZfl(zcR;k)7Ng#~ zi~L({7c}vR?W!dhg2h|v1GufoI7O3OI|SflmlJ8wQYw5$T^D1Cy}B_n*;^j8HL=ZE zlBHN^2khVLU;syX7acBkSmntC@f}8hd1>Mal}Gig8-mRy(2;l zjTjSfr1kwDiPNt%w=UDD#9q@x;mF_}*28N(4cREs z$5%*#5*qKU(hwNKY&8A?QbJ7`$$`>W_Q0{SXe<4Xryosk-QB)iQ%=>DQ>9OANogW1 zoUliZm&J17q2HE#TUV>n81xr`k?QDtEfB2-qE$KC7&=k;q8gZmURr31NbX}NPuZj4 zva}^U3^de1CV20~;P6lUQ}2)JQ?)iYSs$D%dm978PsV;2+rF_oSsR$E56qRW+iH;Q zK4S+%m9biIrmQrAq0&P6%GZl_aJP%gosq!ky*hLADi21!x^@pAC1YfiweHF1*F@;Qh@H#X=fXrae}7|ac= zu%IV_b%uH_a^1&N(9^KUh7kr*LNC?+t&7THJw=)a zkBgQJ#frB$D9&Qr=Me!4)taflVnGrS=`on-AR|FWh8S@@%U>|!;nG5*?_}v3%eYP=cO~h_RE5?? zrt2fqtpt9lPBxLpH*Nd+w#D6%{quHTa68%*K;+6B6Q>VCtEeEy8EwjUIQ8JgwKy88?DNxT|ODU+m_Wy7t4y%=rD)rQxQ8>{{-;w3^oJtWxMaAe2z0NJ>gxQ3#FEcrjLr=i?~k z7Nm7(%|*bp%wmyIePLnUp%)g$^&3mJwWPzeif22E?O8TmSP+6tXWiO`1>JHT&*v4( z2gx^V&FDgHSt=Kq?iOHA*50vg43IBm&ai70 z=J}pJ%RCQ|$mOIkJYRvkC2{VeeK~78K3n7hEicQPs|=}tZkNg~_a$^wO-XGzzI&B9 z26JfH1u6OoeQe41%U*7BvZ-g*a!ZpgB0MSPj*0W23ZB#o)(Eq-WFLqo;H0r-x56i+ zDibyx8}A&EhaMa6SktMKfqNU$o+rlE8L_QTCKA%r44_!FJ)iL=6l*0NIMeBP2Rb*+ ztQS^bzO@AR2=MBjEaA+Fs|H@M7SWu3S_e---}-ds6Er&bww$B4P#1bPS6fBXE_pfq z+)baG!mH%S+Br+iq>Oh=Y7VWPWfm86;9c+nf4XiKD{Ne+tYB7(K6>JX*{LH(#r$yN zI#5GRu&1q7^uoK2HyvZm>IXm`kg8H82J~dB#^4LXi)ht2e6=D2sj6S~R8<(k)uK@{ z3y}~afHIv?!~Ral!h}3>m~5UZjKd)^TBv%gSl|#~3GYWTfMgJehiam?=`ZtVbMux< z0q^-w-NM`j)4J--&#)3JU4|>@S-q~eL?Tw)85^|mL2z|peyjV33 zZ}Kogw8h0Y_;^?Ty`A(UB!RD$6{^sfzh=h*Wc6yY5L=9OX71Y>+zPd-72@Fc>U2oL zx0*njp2s+*I>TQsvv9C`IHO97>;#QCo`olYWKsfTJ`DXZA>(5huW(!3i%`An(q*|$ zhZ!FF6Bs}=X$5d+%#E*hXURE)D;W@Q=k2?mZXd7p2LrnrMClm~cImb0Ux!D&JNC`7 zhjWil{xY0w57M}ov#RoUMKvGj1 zDKfbE-ubWR>I0+o)Tl5XKm!d*15nQ~OUy9Bv|*H7S}9_`*D$VC%wm(1Gz{umFs$N$ z@KU}R)a3%Iz0i9?gj8{2-h(V8XfAIa$V&9rhz)6}20?O=^p32Y4bmG|&NNg_8*Y$J z(x1}6+afZQ*7h{WdLlQ*?JRhr)^fB}9ftm*U{aw(N>B|PB@y;rl116aY#9qAyx^zd zTKxkBQdjl&8s*WNm49<_v_>*kr2nJRsCn`UsKsBSKI+2jO{=3zYkjV}-1*PfMlF?5HuhWV*umZk-Q@P@*TkF$haaN-rCe*)hwpl&v0fd-M;;1>2^Ak z3&aqJ;E0grbK$X~_cT~REKLT)?wVoyp%S(rCA zH>)`O$ED;t*$OXuB5Q^{QKA)vi~tdfP5fV2q*R$8gl3)EzDymL8R#TG4BKD`_r3+v zh%1T`kVEy(UqH^(U-b*fo_go6k$6{uc}${{4sCQcj3cI(m|2G0d1@dv## zkU-4}RgvmcS+!d2ifWbB^0L`f=|dj2QXkv@z($s0jTEWUKK0F2x>D7B*>moA#x?}) zRyz#G_xt1AbAIP{=kIN8tpuKbU;L6De2$QRV#a>NTH@(4BsPdjR3S~0`0Gjw8CTLJ zVA`E_XT+okX;Jm0JsEG(3u$k%#YHH&?z0D@{`&$U58>Z>lC3Usk*F=ViR!!Wf*Sa* z)dW=kZITSC!X$~beussLh+w*}-!$OI|9VcRV~pk4ci00;_D*D%m9(agrZt*1c-88u zC6DcDon}fv7EAGEW}d0$uULODKoTO_L#AkWERsj13OW0g;H)#x~6N{c?o*x(p-*7Ru3r-8-i9^inkk< zZZ2r41xeFeC3sXir)8-s&8|pSFO0tO@=GV9yxi=tR3JMlkYV>zDR;xhao?DK+Ryi$ z7xF}Qs`D<$Iftkc*o}~gxJ!i}%Ul8wx zD!q|{SoZZ4`TG>ANRzhENw~HWpp^}hcU{LO{8@A7-J6cC>{9$yg=S}16L)Rt+SbyO z7Y*AnVWb<}O4)ec!!G2>X5%?J6T%6)nq6$o3vC-lahj66C+}@;D-dYwskf-7V6R>~ z*SyL}Vub7(LN*-`sF#5b+<9`{ZDX<1XGLrj`e zv@}&Ct)>W$lQG@%)G$Nw$;q*+QxjJb^3*$Tj+y&YjH0cAq2PzVU%y@Ixm@nKTzI1rY=0b#Yy~3^B9GoJ z1>@ylycmpE!uubGhql5)4=#R@D230I!)J=YGf#YhPy8SIi+iJw#PacrCEs}2H(s<~ z20@9W8l4DDkvp6U35ZI90l)U6y6(ADw<>6Y3b1wE>8FZLx#ym^hIKZ)6V}GtI9e7f4Z=brF8*VBpmd2wMANP5y6M)JW=*%Uq?&GeYY{>y;IY^U(9nnjGYi5P41E>` z;`Z56n^s3X+2*yc<}1xwSdH$AtIuqI07ld?q^y%_kn|t^@@z32hquzvx7kq)AFdoY z^ho?is2Khgymn#L?+Le735Y@q^a{3@1HDxu_}>&NLnB{JmCq)My;tBZT>NzGP67V{KRl9gfv(S0w#c-VmInHM?P;FpLqT<~iN6zX3OC6u z_dDdKkavSci;4mpAG>8R1q^Jb@w?wmdUQQ=FunjGma0 zqpePb#kwS?U#y9JiUC#F=Ug!c-#SV`wv`SEWFMC_4ceb_4~+X!Zh%UKD5%5f67z zHh={OL15(JVM(Amf+L=c6%JT8WLHn@>Ycjt%I|Wl|2syji}0cpkQ@)*Hd~1 z*|>m1L_t944m|fbFuWBQelS%&cK+-6QXo+dBoG;UD&g+J3Z3$Q*>x+dc#|01Q`RhlY_VKfMj&Pj1w)Dxk4h&zj3c?ubA- z0c0LJ2#Z7Mp+>~ruG75xj;DUPxZ`~`0_TA^HlNlc`P`LYLoj*7%~j2HYWy#Tj3Lr4u3UR3ZE;7&lQ8`_<4U0aBm?-eM1Lv zJ`u#s%uEd`x*)fD{O9iG4IJnd5a6b;beG>hDpbk;AUjC=^KhlwX_4s2+#=C$HktzT zc5{gc${bkNukrE^3|`XactDuf;HD_e%mCSe-PPiZE-mSJAEs~-pwA{|*CwYV&Axm$ zGP78$9vu){;c|_`@=5WEdj#*d!!^=3EFsB?IWYh`-~;C`os|ZmGWNmRu@BY;qj)7z zj3X9!zdHz2ZSXy-_m0l6Ge%WSkHQ7!2-@$?@o^3-@JScIyy%WGtO0aufMMyxutaa2 zJ$dT*@yIipVgQw<*iwC%&jmA_$Qcv1f~d;l7dRYx2YVR>B9eWnw|oQ{PO_)J6dEXp28zCc|JO$FVt&=S+;RJ`++4EIfS(I~Rk2t+erQ2L0xOn~ zSSX+fYJECE1;^o#@gtLzQC6e{Wtl=EyV5X}K5S7MVD%|Qr|?yVLL!SN!!)=INSfhj z8}FzyGdDD~ZlzhNhDwbVDqa3rmTAMv4$yPV6n8Le&-4sas+o~BK(vmU&dS*+9Fu+W z7|z&hczEcxXobi|*;x>)FYS8ryRMSrNHsHP-(d#uA#f_P2d}wVB|~M|Y?b9qPF+f4 zIw;HUFDdC-O^Yn6xs)t3yyu$x?3;Mg<=+a~7^#6*56;=5sS%;J62 z+98s6h5|Xe{soA2=dbE=d3->3K=?@SP*LpuwtJ)~c2-4~=O~sp3ZKt20jSv^JK8+^ ztHcp6c6d6g#1X@8&p?$pqBY=ozDgX?6Yw0wY)$m|Ftt-y8^Pr_MRo^%kq|&!hx>Is zuIB~obJHYYcsb?@f%_u&{i9IO#A-&c1&T$iLA7zR^68H4j*|fPRzfx*hNu_AAWUCi_I4J)OYHYU!1lgK0jqY;NvA23z{KC zvY0bJC%&5I1N_PNs%1K_vA3WxpajwX2BPW~1ffDg>-?`mUMM!d6%r{nzZG(%*!+I` y+{AjQ;@!VKU-s_*%vbUrD0>gAyQ|)mAi!}vTYk^We`u_|1Z$BX=Jw?@UU9(Fk(F$9(b5t&EwA7Ja(g&XqAM-YIn8DTO%@3H2bpW-1_Ub zO@?I4?$cGb&b{~CbI;FrZvS(0bBMt8zhnPO@4Z9Ff8v96`OKTw_u=LNk%=tiNE*Lg zIU(;#yYlX|TOhJq_T)TyZ`zyprG5O_3(x+vKOaa3^1*a4A4-Ry-6#8VP5E#-ED#r= zWWL#&h_*Zy2>A{^#+8o9fpn{jj1f6_kH{hFrM|}=;DC?G5tW6jB;NErK2F44x_f?E z(}Nd^Dors~WZ%1>9h!ruC6$gbsi5hxsp2hKNEPITqEgTLIwoOOjC(b zmXTDIGEFHKR`)NmLQKA2#UGCcruz>a09?pGJ5=V=y9fWMM6lBS1Xa)nV9?|s>vq~ulIcWYTy2gO;$`)~K}vHogmjsE2^8lRx`NYrGnc zeB1f3>(Q~z@oKp9p|9q3weG7CATPTIoCjzL?t2a0NER*Ky1a1XhR^FCfjj_Z*XwuQ z)-~vv%-j9o9{cd?iSQWizq6n3xYk^cESs~K_;;fv38ZkkhiE*O7;L?S9l7Jy!cM10 z^>$!4%dq2*L6+}qc?6z! zz*1AUH6~>>5tJ@2NGrLbB#VX>h%>C17n$MMVz=#;-Gkx+Wg*KhZe9h00%sKuB@W)q zBtrHJ!)HaiU(&f1RgHlii4Zy#si+i0ZH`(qIsF;c(Em}iGu$rgUP+2dlj62G6`9^aB;AA?ZVB!eF?g)>dWLktZ>_sJC8hUzhJl45R&W)>Ewb4oUYF4}VD;^_FL ztC`DJrp7N%T-5_Sm`WODXid61SDe+oGM!$WWoR_47YKx7k4kehdeBxa+l|};Rk0Ut z4BLYZT??$3g_z?+)Qqu?)&4C$_9n(|7)JdykabdP_XkhC=;*qiuC~7O@Nnhbk?Q+B zmG?)$+d2=wB0zpXvT?5FBh78!T>k2EIs9HF{9cLw|M()(h2D6|Auqy_Z^pkGFLmzU z{Inb%u7rn6;o%pto~Od^n@h2i<=Dwe>|`l?@<+H}lHe))2IueGXjVHwq`OD{mi!?! zdd&St*MZRy_a8^RaG$k(5;$x>pMi%55IG;g_x5YeB@2+$&8yLO?zo|s9T6-Z{Due& ze$*HTz^hynECz2OsdiZVZG>S^J*G{^42)+qgSdz7hd#Q0j!H6Rs_r*E5d$)IYTQ@0 z7noN+*s_JzY>ssu1vd2{kabdxc07;ne-_=pIrcR5WTG7XuoC@n!&i;8J&){t7TNn~ zX><7x{&M8wO622G;A192uWbFYZB=eU076yH1BY=r0rQa^oUC{FEel&zDy#`=M5_yP zva6BfE(G44!|B@Av0T83vTeIyQ{8Xg)VBz@p6vm5&HV^7;{@P78(q|`n-(}0y2|F5ocuQj`PB5oCF6leBiv7gWF{Q093C(I~~fQ zs{n_=8Jnb65D%sxxfp&V=A~Oy6(uXzh+2`S9t|yo#f zS{jGjdG2hnph=L$B@va8qnNSl#!|DzEo(5+-RQ+SCfp=P!SuG2Ux0yRnul}?2t~tf zgBh}z&tR3fUluf3Ro8z!}dl?-mPWZ_#Pa(&k67Z3vO%FuMKn7x%W;DMukRP~k1 zpjdzlFj>L?uHyNrsVl<=>%al>oiC~yqML*%b|PEM+oB-D8Bh>}@u4X!S;W6;Cyi1# zc5nhVv+vL-A{Y2FN+P)7qQUp9T^7NEQy4W!ve(|&6LjUm-1JyhxvX3`cWrh2;Dj=+ zj_0+7^qKLa6!VIvQ5m+3iPMZODcTCO{;ILVh2y!Q z^xX25pXlH$wE?i9FZ?{f20d(H*&xJ?)jgLW@uG9qL080@rrGc`y}BD*NRh$3w%Am0 zM(l&?4ClGe@(x%s?~Hr^eB{^C$vfV~8`?ps2;>)xk47 zr;Br7q=n)ZF4MplfmsBxq=|S;_nQ*y9*iftdzNYp^9@TNIe;XNWFHW{HH%_oxGnJD zp@+sMM<=E-Q=eZ+F-%|VF!FU-NHb%OPUQ@DR6UBd8kVUL%4h~9;n-8}1c8llfz??X z!?dM)kT34zIEJgALsC8!!!*oJ0a1NG&>t*-+Gz{Hoy-ztwQmcy*_kbgLrw!q0dRVf zbi8x_Vx_(Bd3*d>dwg?$x&3IR{pd!pinvnu@FTZZ!~o9_V`(=qm^MD}nw}p#Np8 z>%qR??0a~v9P6pXdN%ykrdW*xgMHPuUC-O%&)VXf{pGfiO54cBS!jZ>oBvLD(b-=* z{8_2p+13ejWc>OGBWc=CzdenhViwgkI7ElRia2`IUJ@*dw- z_zb$gB10;IkC|PlJjg+W^=xDtaEB%EVUGRlQkNa0jI3fmo`VA+FZVz0DSC%e$mSMh z3NA4N$bK%v`B&S=@kqyvRecQON+0|FPq3DFP;Z%~1&XQCU}ndlnVm+0&gaAkBLIX{ z32IS3tllwo`IFQ{W-@j43RIz~%=y&l+0dl1%cwmO$fzzrnx?D0 zTl{uME)~X6zXSqq8zA6wtv%0Ld#bU{`-7EOFF4`--IZu}wY$IOC(+(l#1jqufMmn_ z=MV{o4PPAC?0ee&``wj;XUl<9C6FowQs89YM81kV^p*pADuF$vz@BO(_H7DF)gz_I zky7A@Va4^38SmZjd5!gQ<2hR+*uE>o1?eCd?K!Gt=PWq6q)1{nY;iZ{6+0i8=O+pA zEM1~Gz&-#I5u@3gtsu6^Lx=^tQB*Nc;bc|DAt1p(fv&29B2CODl67DOW2Q`JAbA;Q z2;8oiSyK++aloKqYb>6$=fO^R83!q%k#`bsP|H>_(<>PmW55_E?xbP!)W&E}nyUk& zH_mD7HQI9|ty3B^t0@52BsdAQ8Q@r?ZK9}+TWh8=KQS?li|qo%*P9m4XWI;E$7QeM z#0L&0_u=`OeQR9bpUfgWR@J@Cf5e%?MW0{f()XltjTN=Iiij&ka@8gumjW1|z| zIRH?W&UhSQa3BT&!`5H-{PHa@uxv56m@kNcCCpMrlcsa@uN#WNji(Hzl^6|!qIuQ; zhk3@S-wt-uV;ljRXSa!Y_}M@N+buFUE>w$!>vZ}Py5g9QVQiuZb7im=IZ?-zF#4e! z_-??EB7tj*+e@_uFzwakP0T0-8SV9!A`h5Sf6)&Q{lD67x5l_hTcsiZxyz#vsV%kT z0rKbU8BJ?9M+L-b9Kc|Kr(stBLJf6=$#1GGY3c6G{FZmzyjics1nBMNO>kKICgAqviSmH zAl%jAeq$~6p4kBq2Y%C*8kv+M;f7#$0=E$@tnO!`#I~jV6L7IhNJJnFN1Q(|u>BkC zno*`GhHV>`!b=ec(PN;q3T=BYaew<&o_`iumO6#rmL!J(!c1;&yOlfF6Iazj1AN3*wZOWbkBOz<*_%G+$?mxURewJ|iItm2lC zWQB}r_?f~M(TEIgqrSod&M2r5yMXlkxSySbhi#?P&dU84V71~x*S5G2_e{VQZ`A{t zOhL-iOhyl7G9cz+4)4R6%$JK&&V17W)|)w<8l6l{X6h=<4^hT`AbJ=80Th!4%3<$g zJ1<=K;@!tc#*y$k7Q-4tr{IhEoni3C>M)8iB=}MP1IW7lSB>snzfcR2=+Asq8|)`(38T;5Ru zN+^d0j(MRpvI!HKyhm%qCVvz1_ST3^x?1tkCcX9x&e9dex7!JKcfMvk1%TgzX5lzP z57%cB{u7h&W04ZC32wt|D|u&`fSCw>tUem`=H|cVBKBqN|i`Q%{Su`K*u}NZ$B@IBd_?& KAKt*i74d%q1Iyn4 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7523/__pycache__/token.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc7523/__pycache__/token.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f335590edf0d13b6a9c208297afd021e88e3dca7 GIT binary patch literal 4519 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%0AQE=DI4zm{UjNzDj9IYk{QS(% z3v<)&8Rnup^9jw-+$?3(HEG_YGh?@D{`Smudv?aPJ$hyd1{w3zoiU2u=Z-x)Uck!4 zIGZ!yK0k4G{C3NSV@r2~xcNCX7n_Q#40k(YtW&rTG;)ssl!@Ql_xQtlZ?byz->J!` zsmaaMR6RBIw0EkePHmy-W-B7tXnQe?PKi{pcSo^=ZpMW^Q(UvKM8RJY`0Go7C19S5 zUr)0AfPsc?ze|}j;OkV0yh2gl$=%J+G;p@;**Utyj+pH>&9GJmU$J3ZgpPI( z1GM%3^Yr@7Kiyit^>hylP)EMZFq=UV!*n5LuCifh?y3Z%w;@67szg(S|97JRs6>CI z$laDntAVQPc_T-4J&5Ugu3!}%tjBfzmqo(~B@83L@C)p9gi(Z}2wWlL3+EogWXS<5 zt`1OcUky=Ee$pUqhzQD2Y&HR!X>2xOXY(LRUj=Rj|Dy>%YZvq#maQ>>FS-(7R-!Vb zJ*7hC1W17zBtIFGUxh3SSrz;o2@ZEhvYlar$Slvh8B^w84?%$!W`eEz0Dlx#VcY2B zSU0m4+UzSybAnAu@?V7C3j(Ch64Bd<))Fky7P?Scm+mPgk*Stg5-oXMEP)Nk?~(#D zTlT^>hZaC$rLGH!)i#{zw8S~g;xIUf%`*e?t#=nPh{)2|r9k#8Qdp_3o0bE`EiO@p zq_Fe0hoo34&N{ZKFVed~!sMHhURd(%Lf%bBdGcZ7_?ZaIFTzZPQNzgv`{}aB4BhZN zX3rKq>asU+l%_*sHC$KMITw?>ltc1htX7hH_0$xRu?I_*U0uqUzlHji)GcztxjA0A!52uwPZcuoLbAXKgboqGBn-FR?gGd@y}kJREL ze&1l_qnFQm2O31wI^bFSz@zIAuGa=9|9N6FeyJY6REuBo`wl-o*ScOpX(%uW-h3PU z&4qW!SFy|E(l^@hrV5WCJ1Aukcy8PD$%OCjrkCfkU$T8(igX{$Z z`xG$whagPk_@i_$!!uP7#n5AX;}{k=wT&&n0hv>XbA#cU2%>O?d+Y6UKW4bKHCyN3 zWXN)U61vX$6S`#zIzumTtGf5D@6`+8=68`@gK?Or-G2czBtZ~-vaif9pCros^2tPP z@7pKITKDafQ?>5Szbx|S+O8j*wm8{AHKoUIN%$Nm@F!ehe%xO6Af Pj!Znq?iahrxRd`6NkSZJ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7523/assertion.py b/.venv/Lib/site-packages/authlib/oauth2/rfc7523/assertion.py new file mode 100644 index 00000000..0bb9fe7b --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc7523/assertion.py @@ -0,0 +1,66 @@ +import time +from authlib.jose import jwt +from authlib.common.security import generate_token + + +def sign_jwt_bearer_assertion( + key, issuer, audience, subject=None, issued_at=None, + expires_at=None, claims=None, header=None, **kwargs): + + if header is None: + header = {} + alg = kwargs.pop('alg', None) + if alg: + header['alg'] = alg + if 'alg' not in header: + raise ValueError('Missing "alg" in header') + + payload = {'iss': issuer, 'aud': audience} + + # subject is not required in Google service + if subject: + payload['sub'] = subject + + if not issued_at: + issued_at = int(time.time()) + + expires_in = kwargs.pop('expires_in', 3600) + if not expires_at: + expires_at = issued_at + expires_in + + payload['iat'] = issued_at + payload['exp'] = expires_at + + if claims: + payload.update(claims) + + return jwt.encode(header, payload, key) + + +def client_secret_jwt_sign(client_secret, client_id, token_endpoint, alg='HS256', + claims=None, **kwargs): + return _sign(client_secret, client_id, token_endpoint, alg, claims, **kwargs) + + +def private_key_jwt_sign(private_key, client_id, token_endpoint, alg='RS256', + claims=None, **kwargs): + return _sign(private_key, client_id, token_endpoint, alg, claims, **kwargs) + + +def _sign(key, client_id, token_endpoint, alg, claims=None, **kwargs): + # REQUIRED. Issuer. This MUST contain the client_id of the OAuth Client. + issuer = client_id + # REQUIRED. Subject. This MUST contain the client_id of the OAuth Client. + subject = client_id + # The Audience SHOULD be the URL of the Authorization Server's Token Endpoint. + audience = token_endpoint + + # jti is required + if claims is None: + claims = {} + if 'jti' not in claims: + claims['jti'] = generate_token(36) + + return sign_jwt_bearer_assertion( + key=key, issuer=issuer, audience=audience, subject=subject, + claims=claims, alg=alg, **kwargs) diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7523/auth.py b/.venv/Lib/site-packages/authlib/oauth2/rfc7523/auth.py new file mode 100644 index 00000000..77644667 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc7523/auth.py @@ -0,0 +1,94 @@ +from authlib.common.urls import add_params_to_qs +from .assertion import client_secret_jwt_sign, private_key_jwt_sign +from .client import ASSERTION_TYPE + + +class ClientSecretJWT: + """Authentication method for OAuth 2.0 Client. This authentication + method is called ``client_secret_jwt``, which is using ``client_id`` + and ``client_secret`` constructed with JWT to identify a client. + + Here is an example of use ``client_secret_jwt`` with Requests Session:: + + from authlib.integrations.requests_client import OAuth2Session + + token_endpoint = 'https://example.com/oauth/token' + session = OAuth2Session( + 'your-client-id', 'your-client-secret', + token_endpoint_auth_method='client_secret_jwt' + ) + session.register_client_auth_method(ClientSecretJWT(token_endpoint)) + session.fetch_token(token_endpoint) + + :param token_endpoint: A string URL of the token endpoint + :param claims: Extra JWT claims + :param headers: Extra JWT headers + :param alg: ``alg`` value, default is HS256 + """ + name = 'client_secret_jwt' + alg = 'HS256' + + def __init__(self, token_endpoint=None, claims=None, headers=None, alg=None): + self.token_endpoint = token_endpoint + self.claims = claims + self.headers = headers + if alg is not None: + self.alg = alg + + def sign(self, auth, token_endpoint): + return client_secret_jwt_sign( + auth.client_secret, + client_id=auth.client_id, + token_endpoint=token_endpoint, + claims=self.claims, + header=self.headers, + alg=self.alg, + ) + + def __call__(self, auth, method, uri, headers, body): + token_endpoint = self.token_endpoint + if not token_endpoint: + token_endpoint = uri + + client_assertion = self.sign(auth, token_endpoint) + body = add_params_to_qs(body or '', [ + ('client_assertion_type', ASSERTION_TYPE), + ('client_assertion', client_assertion) + ]) + return uri, headers, body + + +class PrivateKeyJWT(ClientSecretJWT): + """Authentication method for OAuth 2.0 Client. This authentication + method is called ``private_key_jwt``, which is using ``client_id`` + and ``private_key`` constructed with JWT to identify a client. + + Here is an example of use ``private_key_jwt`` with Requests Session:: + + from authlib.integrations.requests_client import OAuth2Session + + token_endpoint = 'https://example.com/oauth/token' + session = OAuth2Session( + 'your-client-id', 'your-client-private-key', + token_endpoint_auth_method='private_key_jwt' + ) + session.register_client_auth_method(PrivateKeyJWT(token_endpoint)) + session.fetch_token(token_endpoint) + + :param token_endpoint: A string URL of the token endpoint + :param claims: Extra JWT claims + :param headers: Extra JWT headers + :param alg: ``alg`` value, default is RS256 + """ + name = 'private_key_jwt' + alg = 'RS256' + + def sign(self, auth, token_endpoint): + return private_key_jwt_sign( + auth.client_secret, + client_id=auth.client_id, + token_endpoint=token_endpoint, + claims=self.claims, + header=self.headers, + alg=self.alg, + ) diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7523/client.py b/.venv/Lib/site-packages/authlib/oauth2/rfc7523/client.py new file mode 100644 index 00000000..2a6a1bfc --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc7523/client.py @@ -0,0 +1,113 @@ +import logging +from authlib.jose import jwt +from authlib.jose.errors import JoseError +from ..rfc6749 import InvalidClientError + +ASSERTION_TYPE = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer' +log = logging.getLogger(__name__) + + +class JWTBearerClientAssertion: + """Implementation of Using JWTs for Client Authentication, which is + defined by RFC7523. + """ + #: Value of ``client_assertion_type`` of JWTs + CLIENT_ASSERTION_TYPE = ASSERTION_TYPE + #: Name of the client authentication method + CLIENT_AUTH_METHOD = 'client_assertion_jwt' + + def __init__(self, token_url, validate_jti=True): + self.token_url = token_url + self._validate_jti = validate_jti + + def __call__(self, query_client, request): + data = request.form + assertion_type = data.get('client_assertion_type') + assertion = data.get('client_assertion') + if assertion_type == ASSERTION_TYPE and assertion: + resolve_key = self.create_resolve_key_func(query_client, request) + self.process_assertion_claims(assertion, resolve_key) + return self.authenticate_client(request.client) + log.debug('Authenticate via %r failed', self.CLIENT_AUTH_METHOD) + + def create_claims_options(self): + """Create a claims_options for verify JWT payload claims. Developers + MAY overwrite this method to create a more strict options.""" + # https://tools.ietf.org/html/rfc7523#section-3 + # The Audience SHOULD be the URL of the Authorization Server's Token Endpoint + options = { + 'iss': {'essential': True, 'validate': _validate_iss}, + 'sub': {'essential': True}, + 'aud': {'essential': True, 'value': self.token_url}, + 'exp': {'essential': True}, + } + if self._validate_jti: + options['jti'] = {'essential': True, 'validate': self.validate_jti} + return options + + def process_assertion_claims(self, assertion, resolve_key): + """Extract JWT payload claims from request "assertion", per + `Section 3.1`_. + + :param assertion: assertion string value in the request + :param resolve_key: function to resolve the sign key + :return: JWTClaims + :raise: InvalidClientError + + .. _`Section 3.1`: https://tools.ietf.org/html/rfc7523#section-3.1 + """ + try: + claims = jwt.decode( + assertion, resolve_key, + claims_options=self.create_claims_options() + ) + claims.validate() + except JoseError as e: + log.debug('Assertion Error: %r', e) + raise InvalidClientError() + return claims + + def authenticate_client(self, client): + if client.check_endpoint_auth_method(self.CLIENT_AUTH_METHOD, 'token'): + return client + raise InvalidClientError() + + def create_resolve_key_func(self, query_client, request): + def resolve_key(headers, payload): + # https://tools.ietf.org/html/rfc7523#section-3 + # For client authentication, the subject MUST be the + # "client_id" of the OAuth client + client_id = payload['sub'] + client = query_client(client_id) + if not client: + raise InvalidClientError() + request.client = client + return self.resolve_client_public_key(client, headers) + return resolve_key + + def validate_jti(self, claims, jti): + """Validate if the given ``jti`` value is used before. Developers + MUST implement this method:: + + def validate_jti(self, claims, jti): + key = 'jti:{}-{}'.format(claims['sub'], jti) + if redis.get(key): + return False + redis.set(key, 1, ex=3600) + return True + """ + raise NotImplementedError() + + def resolve_client_public_key(self, client, headers): + """Resolve the client public key for verifying the JWT signature. + A client may have many public keys, in this case, we can retrieve it + via ``kid`` value in headers. Developers MUST implement this method:: + + def resolve_client_public_key(self, client, headers): + return client.public_key + """ + raise NotImplementedError() + + +def _validate_iss(claims, iss): + return claims['sub'] == iss diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7523/jwt_bearer.py b/.venv/Lib/site-packages/authlib/oauth2/rfc7523/jwt_bearer.py new file mode 100644 index 00000000..fb672a92 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc7523/jwt_bearer.py @@ -0,0 +1,182 @@ +import logging +from authlib.jose import jwt, JoseError +from ..rfc6749 import BaseGrant, TokenEndpointMixin +from ..rfc6749 import ( + UnauthorizedClientError, + InvalidRequestError, + InvalidGrantError, + InvalidClientError, +) +from .assertion import sign_jwt_bearer_assertion + +log = logging.getLogger(__name__) +JWT_BEARER_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:jwt-bearer' + + +class JWTBearerGrant(BaseGrant, TokenEndpointMixin): + GRANT_TYPE = JWT_BEARER_GRANT_TYPE + + #: Options for verifying JWT payload claims. Developers MAY + #: overwrite this constant to create a more strict options. + CLAIMS_OPTIONS = { + 'iss': {'essential': True}, + 'aud': {'essential': True}, + 'exp': {'essential': True}, + } + + @staticmethod + def sign(key, issuer, audience, subject=None, + issued_at=None, expires_at=None, claims=None, **kwargs): + return sign_jwt_bearer_assertion( + key, issuer, audience, subject, issued_at, + expires_at, claims, **kwargs) + + def process_assertion_claims(self, assertion): + """Extract JWT payload claims from request "assertion", per + `Section 3.1`_. + + :param assertion: assertion string value in the request + :return: JWTClaims + :raise: InvalidGrantError + + .. _`Section 3.1`: https://tools.ietf.org/html/rfc7523#section-3.1 + """ + try: + claims = jwt.decode( + assertion, self.resolve_public_key, + claims_options=self.CLAIMS_OPTIONS) + claims.validate() + except JoseError as e: + log.debug('Assertion Error: %r', e) + raise InvalidGrantError(description=e.description) + return claims + + def resolve_public_key(self, headers, payload): + client = self.resolve_issuer_client(payload['iss']) + return self.resolve_client_key(client, headers, payload) + + def validate_token_request(self): + """The client makes a request to the token endpoint by sending the + following parameters using the "application/x-www-form-urlencoded" + format per `Section 2.1`_: + + grant_type + REQUIRED. Value MUST be set to + "urn:ietf:params:oauth:grant-type:jwt-bearer". + + assertion + REQUIRED. Value MUST contain a single JWT. + + scope + OPTIONAL. + + The following example demonstrates an access token request with a JWT + as an authorization grant: + + .. code-block:: http + + POST /token.oauth2 HTTP/1.1 + Host: as.example.com + Content-Type: application/x-www-form-urlencoded + + grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer + &assertion=eyJhbGciOiJFUzI1NiIsImtpZCI6IjE2In0. + eyJpc3Mi[...omitted for brevity...]. + J9l-ZhwP[...omitted for brevity...] + + .. _`Section 2.1`: https://tools.ietf.org/html/rfc7523#section-2.1 + """ + assertion = self.request.form.get('assertion') + if not assertion: + raise InvalidRequestError('Missing "assertion" in request') + + claims = self.process_assertion_claims(assertion) + client = self.resolve_issuer_client(claims['iss']) + log.debug('Validate token request of %s', client) + + if not client.check_grant_type(self.GRANT_TYPE): + raise UnauthorizedClientError() + + self.request.client = client + self.validate_requested_scope() + + subject = claims.get('sub') + if subject: + user = self.authenticate_user(subject) + if not user: + raise InvalidGrantError(description='Invalid "sub" value in assertion') + + log.debug('Check client(%s) permission to User(%s)', client, user) + if not self.has_granted_permission(client, user): + raise InvalidClientError( + description='Client has no permission to access user data') + self.request.user = user + + def create_token_response(self): + """If valid and authorized, the authorization server issues an access + token. + """ + token = self.generate_token( + scope=self.request.scope, + user=self.request.user, + include_refresh_token=False, + ) + log.debug('Issue token %r to %r', token, self.request.client) + self.save_token(token) + return 200, token, self.TOKEN_RESPONSE_HEADER + + def resolve_issuer_client(self, issuer): + """Fetch client via "iss" in assertion claims. Developers MUST + implement this method in subclass, e.g.:: + + def resolve_issuer_client(self, issuer): + return Client.query_by_iss(issuer) + + :param issuer: "iss" value in assertion + :return: Client instance + """ + raise NotImplementedError() + + def resolve_client_key(self, client, headers, payload): + """Resolve client key to decode assertion data. Developers MUST + implement this method in subclass. For instance, there is a + "jwks" column on client table, e.g.:: + + def resolve_client_key(self, client, headers, payload): + # from authlib.jose import JsonWebKey + + key_set = JsonWebKey.import_key_set(client.jwks) + return key_set.find_by_kid(headers['kid']) + + :param client: instance of OAuth client model + :param headers: headers part of the JWT + :param payload: payload part of the JWT + :return: ``authlib.jose.Key`` instance + """ + raise NotImplementedError() + + def authenticate_user(self, subject): + """Authenticate user with the given assertion claims. Developers MUST + implement it in subclass, e.g.:: + + def authenticate_user(self, subject): + return User.get_by_sub(subject) + + :param subject: "sub" value in claims + :return: User instance + """ + raise NotImplementedError() + + def has_granted_permission(self, client, user): + """Check if the client has permission to access the given user's resource. + Developers MUST implement it in subclass, e.g.:: + + def has_granted_permission(self, client, user): + permission = ClientUserGrant.query(client=client, user=user) + return permission.granted + + :param client: instance of OAuth client model + :param user: instance of User model + :return: bool + """ + raise NotImplementedError() diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7523/token.py b/.venv/Lib/site-packages/authlib/oauth2/rfc7523/token.py new file mode 100644 index 00000000..27fab5f4 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc7523/token.py @@ -0,0 +1,93 @@ +import time +from authlib.common.encoding import to_native +from authlib.jose import jwt + + +class JWTBearerTokenGenerator: + """A JSON Web Token formatted bearer token generator for jwt-bearer grant type. + This token generator can be registered into authorization server:: + + authorization_server.register_token_generator( + 'urn:ietf:params:oauth:grant-type:jwt-bearer', + JWTBearerTokenGenerator(private_rsa_key), + ) + + In this way, we can generate the token into JWT format. And we don't have to + save this token into database, since it will be short time valid. Consider to + rewrite ``JWTBearerGrant.save_token``:: + + class MyJWTBearerGrant(JWTBearerGrant): + def save_token(self, token): + pass + + :param secret_key: private RSA key in bytes, JWK or JWK Set. + :param issuer: a string or URI of the issuer + :param alg: ``alg`` to use in JWT + """ + DEFAULT_EXPIRES_IN = 3600 + + def __init__(self, secret_key, issuer=None, alg='RS256'): + self.secret_key = secret_key + self.issuer = issuer + self.alg = alg + + @staticmethod + def get_allowed_scope(client, scope): + if scope: + scope = client.get_allowed_scope(scope) + return scope + + @staticmethod + def get_sub_value(user): + """Return user's ID as ``sub`` value in token payload. For instance:: + + @staticmethod + def get_sub_value(user): + return str(user.id) + """ + return user.get_user_id() + + def get_token_data(self, grant_type, client, expires_in, user=None, scope=None): + scope = self.get_allowed_scope(client, scope) + issued_at = int(time.time()) + data = { + 'scope': scope, + 'grant_type': grant_type, + 'iat': issued_at, + 'exp': issued_at + expires_in, + 'client_id': client.get_client_id(), + } + if self.issuer: + data['iss'] = self.issuer + if user: + data['sub'] = self.get_sub_value(user) + return data + + def generate(self, grant_type, client, user=None, scope=None, expires_in=None): + """Generate a bearer token for OAuth 2.0 authorization token endpoint. + + :param client: the client that making the request. + :param grant_type: current requested grant_type. + :param user: current authorized user. + :param expires_in: if provided, use this value as expires_in. + :param scope: current requested scope. + :return: Token dict + """ + if not expires_in: + expires_in = self.DEFAULT_EXPIRES_IN + + token_data = self.get_token_data(grant_type, client, expires_in, user, scope) + access_token = jwt.encode({'alg': self.alg}, token_data, key=self.secret_key, check=False) + token = { + 'token_type': 'Bearer', + 'access_token': to_native(access_token), + 'expires_in': expires_in + } + if scope: + token['scope'] = scope + return token + + def __call__(self, grant_type, client, user=None, scope=None, + expires_in=None, include_refresh_token=True): + # there is absolutely no refresh token in JWT format + return self.generate(grant_type, client, user, scope, expires_in) diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7523/validator.py b/.venv/Lib/site-packages/authlib/oauth2/rfc7523/validator.py new file mode 100644 index 00000000..f2423b8a --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc7523/validator.py @@ -0,0 +1,54 @@ +import time +import logging +from authlib.jose import jwt, JoseError, JWTClaims +from ..rfc6749 import TokenMixin +from ..rfc6750 import BearerTokenValidator + +logger = logging.getLogger(__name__) + + +class JWTBearerToken(TokenMixin, JWTClaims): + def check_client(self, client): + return self['client_id'] == client.get_client_id() + + def get_scope(self): + return self.get('scope') + + def get_expires_in(self): + return self['exp'] - self['iat'] + + def is_expired(self): + return self['exp'] < time.time() + + def is_revoked(self): + return False + + +class JWTBearerTokenValidator(BearerTokenValidator): + TOKEN_TYPE = 'bearer' + token_cls = JWTBearerToken + + def __init__(self, public_key, issuer=None, realm=None, **extra_attributes): + super().__init__(realm, **extra_attributes) + self.public_key = public_key + claims_options = { + 'exp': {'essential': True}, + 'client_id': {'essential': True}, + 'grant_type': {'essential': True}, + } + if issuer: + claims_options['iss'] = {'essential': True, 'value': issuer} + self.claims_options = claims_options + + def authenticate_token(self, token_string): + try: + claims = jwt.decode( + token_string, self.public_key, + claims_options=self.claims_options, + claims_cls=self.token_cls, + ) + claims.validate() + return claims + except JoseError as error: + logger.debug('Authenticate token failed. %r', error) + return None diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7591/__init__.py b/.venv/Lib/site-packages/authlib/oauth2/rfc7591/__init__.py new file mode 100644 index 00000000..8ebb0709 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc7591/__init__.py @@ -0,0 +1,25 @@ +""" + authlib.oauth2.rfc7591 + ~~~~~~~~~~~~~~~~~~~~~~ + + This module represents a direct implementation of + OAuth 2.0 Dynamic Client Registration Protocol. + + https://tools.ietf.org/html/rfc7591 +""" + + +from .claims import ClientMetadataClaims +from .endpoint import ClientRegistrationEndpoint +from .errors import ( + InvalidRedirectURIError, + InvalidClientMetadataError, + InvalidSoftwareStatementError, + UnapprovedSoftwareStatementError, +) + +__all__ = [ + 'ClientMetadataClaims', 'ClientRegistrationEndpoint', + 'InvalidRedirectURIError', 'InvalidClientMetadataError', + 'InvalidSoftwareStatementError', 'UnapprovedSoftwareStatementError', +] diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7591/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc7591/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2203051aca762bc7fe95286e7fb7f3462a74f6ef GIT binary patch literal 869 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7591/__pycache__/endpoint.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc7591/__pycache__/endpoint.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2800807ad8029f3913ffd7335d4985ef21f3f53c GIT binary patch literal 11082 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7591/claims.py b/.venv/Lib/site-packages/authlib/oauth2/rfc7591/claims.py new file mode 100644 index 00000000..b6157b52 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc7591/claims.py @@ -0,0 +1,218 @@ +from authlib.jose import BaseClaims, JsonWebKey +from authlib.jose.errors import InvalidClaimError +from authlib.common.urls import is_valid_url + + +class ClientMetadataClaims(BaseClaims): + # https://tools.ietf.org/html/rfc7591#section-2 + REGISTERED_CLAIMS = [ + 'redirect_uris', + 'token_endpoint_auth_method', + 'grant_types', + 'response_types', + 'client_name', + 'client_uri', + 'logo_uri', + 'scope', + 'contacts', + 'tos_uri', + 'policy_uri', + 'jwks_uri', + 'jwks', + 'software_id', + 'software_version', + ] + + def validate(self): + self._validate_essential_claims() + self.validate_redirect_uris() + self.validate_token_endpoint_auth_method() + self.validate_grant_types() + self.validate_response_types() + self.validate_client_name() + self.validate_client_uri() + self.validate_logo_uri() + self.validate_scope() + self.validate_contacts() + self.validate_tos_uri() + self.validate_policy_uri() + self.validate_jwks_uri() + self.validate_jwks() + self.validate_software_id() + self.validate_software_version() + + def validate_redirect_uris(self): + """Array of redirection URI strings for use in redirect-based flows + such as the authorization code and implicit flows. As required by + Section 2 of OAuth 2.0 [RFC6749], clients using flows with + redirection MUST register their redirection URI values. + Authorization servers that support dynamic registration for + redirect-based flows MUST implement support for this metadata + value. + """ + uris = self.get('redirect_uris') + if uris: + for uri in uris: + self._validate_uri('redirect_uris', uri) + + def validate_token_endpoint_auth_method(self): + """String indicator of the requested authentication method for the + token endpoint. + """ + # If unspecified or omitted, the default is "client_secret_basic" + if 'token_endpoint_auth_method' not in self: + self['token_endpoint_auth_method'] = 'client_secret_basic' + self._validate_claim_value('token_endpoint_auth_method') + + def validate_grant_types(self): + """Array of OAuth 2.0 grant type strings that the client can use at + the token endpoint. + """ + self._validate_claim_value('grant_types') + + def validate_response_types(self): + """Array of the OAuth 2.0 response type strings that the client can + use at the authorization endpoint. + """ + self._validate_claim_value('response_types') + + def validate_client_name(self): + """Human-readable string name of the client to be presented to the + end-user during authorization. If omitted, the authorization + server MAY display the raw "client_id" value to the end-user + instead. It is RECOMMENDED that clients always send this field. + The value of this field MAY be internationalized, as described in + Section 2.2. + """ + + def validate_client_uri(self): + """URL string of a web page providing information about the client. + If present, the server SHOULD display this URL to the end-user in + a clickable fashion. It is RECOMMENDED that clients always send + this field. The value of this field MUST point to a valid web + page. The value of this field MAY be internationalized, as + described in Section 2.2. + """ + self._validate_uri('client_uri') + + def validate_logo_uri(self): + """URL string that references a logo for the client. If present, the + server SHOULD display this image to the end-user during approval. + The value of this field MUST point to a valid image file. The + value of this field MAY be internationalized, as described in + Section 2.2. + """ + self._validate_uri('logo_uri') + + def validate_scope(self): + """String containing a space-separated list of scope values (as + described in Section 3.3 of OAuth 2.0 [RFC6749]) that the client + can use when requesting access tokens. The semantics of values in + this list are service specific. If omitted, an authorization + server MAY register a client with a default set of scopes. + """ + self._validate_claim_value('scope') + + def validate_contacts(self): + """Array of strings representing ways to contact people responsible + for this client, typically email addresses. The authorization + server MAY make these contact addresses available to end-users for + support requests for the client. See Section 6 for information on + Privacy Considerations. + """ + if 'contacts' in self and not isinstance(self['contacts'], list): + raise InvalidClaimError('contacts') + + def validate_tos_uri(self): + """URL string that points to a human-readable terms of service + document for the client that describes a contractual relationship + between the end-user and the client that the end-user accepts when + authorizing the client. The authorization server SHOULD display + this URL to the end-user if it is provided. The value of this + field MUST point to a valid web page. The value of this field MAY + be internationalized, as described in Section 2.2. + """ + self._validate_uri('tos_uri') + + def validate_policy_uri(self): + """URL string that points to a human-readable privacy policy document + that describes how the deployment organization collects, uses, + retains, and discloses personal data. The authorization server + SHOULD display this URL to the end-user if it is provided. The + value of this field MUST point to a valid web page. The value of + this field MAY be internationalized, as described in Section 2.2. + """ + self._validate_uri('policy_uri') + + def validate_jwks_uri(self): + """URL string referencing the client's JSON Web Key (JWK) Set + [RFC7517] document, which contains the client's public keys. The + value of this field MUST point to a valid JWK Set document. These + keys can be used by higher-level protocols that use signing or + encryption. For instance, these keys might be used by some + applications for validating signed requests made to the token + endpoint when using JWTs for client authentication [RFC7523]. Use + of this parameter is preferred over the "jwks" parameter, as it + allows for easier key rotation. The "jwks_uri" and "jwks" + parameters MUST NOT both be present in the same request or + response. + """ + # TODO: use real HTTP library + self._validate_uri('jwks_uri') + + def validate_jwks(self): + """Client's JSON Web Key Set [RFC7517] document value, which contains + the client's public keys. The value of this field MUST be a JSON + object containing a valid JWK Set. These keys can be used by + higher-level protocols that use signing or encryption. This + parameter is intended to be used by clients that cannot use the + "jwks_uri" parameter, such as native clients that cannot host + public URLs. The "jwks_uri" and "jwks" parameters MUST NOT both + be present in the same request or response. + """ + if 'jwks' in self: + if 'jwks_uri' in self: + # The "jwks_uri" and "jwks" parameters MUST NOT both be present + raise InvalidClaimError('jwks') + + jwks = self['jwks'] + try: + key_set = JsonWebKey.import_key_set(jwks) + if not key_set: + raise InvalidClaimError('jwks') + except ValueError: + raise InvalidClaimError('jwks') + + def validate_software_id(self): + """A unique identifier string (e.g., a Universally Unique Identifier + (UUID)) assigned by the client developer or software publisher + used by registration endpoints to identify the client software to + be dynamically registered. Unlike "client_id", which is issued by + the authorization server and SHOULD vary between instances, the + "software_id" SHOULD remain the same for all instances of the + client software. The "software_id" SHOULD remain the same across + multiple updates or versions of the same piece of software. The + value of this field is not intended to be human readable and is + usually opaque to the client and authorization server. + """ + + def validate_software_version(self): + """A version identifier string for the client software identified by + "software_id". The value of the "software_version" SHOULD change + on any update to the client software identified by the same + "software_id". The value of this field is intended to be compared + using string equality matching and no other comparison semantics + are defined by this specification. The value of this field is + outside the scope of this specification, but it is not intended to + be human readable and is usually opaque to the client and + authorization server. The definition of what constitutes an + update to client software that would trigger a change to this + value is specific to the software itself and is outside the scope + of this specification. + """ + + def _validate_uri(self, key, uri=None): + if uri is None: + uri = self.get(key) + if uri and not is_valid_url(uri): + raise InvalidClaimError(key) diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7591/endpoint.py b/.venv/Lib/site-packages/authlib/oauth2/rfc7591/endpoint.py new file mode 100644 index 00000000..d26e0614 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc7591/endpoint.py @@ -0,0 +1,211 @@ +import os +import time +import binascii +from authlib.consts import default_json_headers +from authlib.common.security import generate_token +from authlib.jose import JsonWebToken, JoseError +from ..rfc6749 import AccessDeniedError, InvalidRequestError +from ..rfc6749 import scope_to_list +from .claims import ClientMetadataClaims +from .errors import ( + InvalidClientMetadataError, + UnapprovedSoftwareStatementError, + InvalidSoftwareStatementError, +) + + +class ClientRegistrationEndpoint: + """The client registration endpoint is an OAuth 2.0 endpoint designed to + allow a client to be registered with the authorization server. + """ + ENDPOINT_NAME = 'client_registration' + + #: The claims validation class + claims_class = ClientMetadataClaims + + #: Rewrite this value with a list to support ``software_statement`` + #: e.g. ``software_statement_alg_values_supported = ['RS256']`` + software_statement_alg_values_supported = None + + def __init__(self, server): + self.server = server + + def __call__(self, request): + return self.create_registration_response(request) + + def create_registration_response(self, request): + token = self.authenticate_token(request) + if not token: + raise AccessDeniedError() + + request.credential = token + + client_metadata = self.extract_client_metadata(request) + client_info = self.generate_client_info() + body = {} + body.update(client_metadata) + body.update(client_info) + client = self.save_client(client_info, client_metadata, request) + registration_info = self.generate_client_registration_info(client, request) + if registration_info: + body.update(registration_info) + return 201, body, default_json_headers + + def extract_client_metadata(self, request): + if not request.data: + raise InvalidRequestError() + + json_data = request.data.copy() + software_statement = json_data.pop('software_statement', None) + if software_statement and self.software_statement_alg_values_supported: + data = self.extract_software_statement(software_statement, request) + json_data.update(data) + + options = self.get_claims_options() + claims = self.claims_class(json_data, {}, options, self.get_server_metadata()) + try: + claims.validate() + except JoseError as error: + raise InvalidClientMetadataError(error.description) + return claims.get_registered_claims() + + def extract_software_statement(self, software_statement, request): + key = self.resolve_public_key(request) + if not key: + raise UnapprovedSoftwareStatementError() + + try: + jwt = JsonWebToken(self.software_statement_alg_values_supported) + claims = jwt.decode(software_statement, key) + # there is no need to validate claims + return claims + except JoseError: + raise InvalidSoftwareStatementError() + + def get_claims_options(self): + """Generate claims options validation from Authorization Server metadata.""" + metadata = self.get_server_metadata() + if not metadata: + return {} + + scopes_supported = metadata.get('scopes_supported') + response_types_supported = metadata.get('response_types_supported') + grant_types_supported = metadata.get('grant_types_supported') + auth_methods_supported = metadata.get('token_endpoint_auth_methods_supported') + options = {} + if scopes_supported is not None: + scopes_supported = set(scopes_supported) + + def _validate_scope(claims, value): + if not value: + return True + scopes = set(scope_to_list(value)) + return scopes_supported.issuperset(scopes) + + options['scope'] = {'validate': _validate_scope} + + if response_types_supported is not None: + response_types_supported = set(response_types_supported) + + def _validate_response_types(claims, value): + # If omitted, the default is that the client will use only the "code" + # response type. + response_types = set(value) if value else {"code"} + return response_types_supported.issuperset(response_types) + + options['response_types'] = {'validate': _validate_response_types} + + if grant_types_supported is not None: + grant_types_supported = set(grant_types_supported) + + def _validate_grant_types(claims, value): + # If omitted, the default behavior is that the client will use only + # the "authorization_code" Grant Type. + grant_types = set(value) if value else {"authorization_code"} + return grant_types_supported.issuperset(grant_types) + + options['grant_types'] = {'validate': _validate_grant_types} + + if auth_methods_supported is not None: + options['token_endpoint_auth_method'] = {'values': auth_methods_supported} + + return options + + def generate_client_info(self): + # https://tools.ietf.org/html/rfc7591#section-3.2.1 + client_id = self.generate_client_id() + client_secret = self.generate_client_secret() + client_id_issued_at = int(time.time()) + client_secret_expires_at = 0 + return dict( + client_id=client_id, + client_secret=client_secret, + client_id_issued_at=client_id_issued_at, + client_secret_expires_at=client_secret_expires_at, + ) + + def generate_client_registration_info(self, client, request): + """Generate ```registration_client_uri`` and ``registration_access_token`` + for RFC7592. This method returns ``None`` by default. Developers MAY rewrite + this method to return registration information.""" + return None + + def create_endpoint_request(self, request): + return self.server.create_json_request(request) + + def generate_client_id(self): + """Generate ``client_id`` value. Developers MAY rewrite this method + to use their own way to generate ``client_id``. + """ + return generate_token(42) + + def generate_client_secret(self): + """Generate ``client_secret`` value. Developers MAY rewrite this method + to use their own way to generate ``client_secret``. + """ + return binascii.hexlify(os.urandom(24)).decode('ascii') + + def get_server_metadata(self): + """Return server metadata which includes supported grant types, + response types and etc. + """ + raise NotImplementedError() + + def authenticate_token(self, request): + """Authenticate current credential who is requesting to register a client. + Developers MUST implement this method in subclass:: + + def authenticate_token(self, request): + auth = request.headers.get('Authorization') + return get_token_by_auth(auth) + + :return: token instance + """ + raise NotImplementedError() + + def resolve_public_key(self, request): + """Resolve a public key for decoding ``software_statement``. If + ``enable_software_statement=True``, developers MUST implement this + method in subclass:: + + def resolve_public_key(self, request): + return get_public_key_from_user(request.credential) + + :return: JWK or Key string + """ + raise NotImplementedError() + + def save_client(self, client_info, client_metadata, request): + """Save client into database. Developers MUST implement this method + in subclass:: + + def save_client(self, client_info, client_metadata, request): + client = OAuthClient( + client_id=client_info['client_id'], + client_secret=client_info['client_secret'], + ... + ) + client.save() + return client + """ + raise NotImplementedError() diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7591/errors.py b/.venv/Lib/site-packages/authlib/oauth2/rfc7591/errors.py new file mode 100644 index 00000000..31693c04 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc7591/errors.py @@ -0,0 +1,33 @@ +from ..rfc6749 import OAuth2Error + + +class InvalidRedirectURIError(OAuth2Error): + """The value of one or more redirection URIs is invalid. + https://tools.ietf.org/html/rfc7591#section-3.2.2 + """ + error = 'invalid_redirect_uri' + + +class InvalidClientMetadataError(OAuth2Error): + """The value of one of the client metadata fields is invalid and the + server has rejected this request. Note that an authorization + server MAY choose to substitute a valid value for any requested + parameter of a client's metadata. + https://tools.ietf.org/html/rfc7591#section-3.2.2 + """ + error = 'invalid_client_metadata' + + +class InvalidSoftwareStatementError(OAuth2Error): + """The software statement presented is invalid. + https://tools.ietf.org/html/rfc7591#section-3.2.2 + """ + error = 'invalid_software_statement' + + +class UnapprovedSoftwareStatementError(OAuth2Error): + """The software statement presented is not approved for use by this + authorization server. + https://tools.ietf.org/html/rfc7591#section-3.2.2 + """ + error = 'unapproved_software_statement' diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7592/__init__.py b/.venv/Lib/site-packages/authlib/oauth2/rfc7592/__init__.py new file mode 100644 index 00000000..6a6457be --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc7592/__init__.py @@ -0,0 +1,13 @@ +""" + authlib.oauth2.rfc7592 + ~~~~~~~~~~~~~~~~~~~~~~ + + This module represents a direct implementation of + OAuth 2.0 Dynamic Client Registration Management Protocol. + + https://tools.ietf.org/html/rfc7592 +""" + +from .endpoint import ClientConfigurationEndpoint + +__all__ = ['ClientConfigurationEndpoint'] diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7592/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc7592/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8a198b046e822434ff47bbe82d54f1efdcb895b6 GIT binary patch literal 544 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 HHdfyO=ryn$ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7636/__pycache__/challenge.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc7636/__pycache__/challenge.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..70355b3593c6c7e9be0fbfe953a9beddc6140c20 GIT binary patch literal 6235 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 E0M!&Qz5oCK literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7636/challenge.py b/.venv/Lib/site-packages/authlib/oauth2/rfc7636/challenge.py new file mode 100644 index 00000000..8303092e --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc7636/challenge.py @@ -0,0 +1,138 @@ +import re +import hashlib +from authlib.common.encoding import to_bytes, to_unicode, urlsafe_b64encode +from ..rfc6749 import ( + InvalidRequestError, + InvalidGrantError, + OAuth2Request, +) + + +CODE_VERIFIER_PATTERN = re.compile(r'^[a-zA-Z0-9\-._~]{43,128}$') + + +def create_s256_code_challenge(code_verifier): + """Create S256 code_challenge with the given code_verifier.""" + data = hashlib.sha256(to_bytes(code_verifier, 'ascii')).digest() + return to_unicode(urlsafe_b64encode(data)) + + +def compare_plain_code_challenge(code_verifier, code_challenge): + # If the "code_challenge_method" from Section 4.3 was "plain", + # they are compared directly + return code_verifier == code_challenge + + +def compare_s256_code_challenge(code_verifier, code_challenge): + # BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) == code_challenge + return create_s256_code_challenge(code_verifier) == code_challenge + + +class CodeChallenge: + """CodeChallenge extension to Authorization Code Grant. It is used to + improve the security of Authorization Code flow for public clients by + sending extra "code_challenge" and "code_verifier" to the authorization + server. + + The AuthorizationCodeGrant SHOULD save the ``code_challenge`` and + ``code_challenge_method`` into database when ``save_authorization_code``. + Then register this extension via:: + + server.register_grant( + AuthorizationCodeGrant, + [CodeChallenge(required=True)] + ) + """ + #: defaults to "plain" if not present in the request + DEFAULT_CODE_CHALLENGE_METHOD = 'plain' + #: supported ``code_challenge_method`` + SUPPORTED_CODE_CHALLENGE_METHOD = ['plain', 'S256'] + + CODE_CHALLENGE_METHODS = { + 'plain': compare_plain_code_challenge, + 'S256': compare_s256_code_challenge, + } + + def __init__(self, required=True): + self.required = required + + def __call__(self, grant): + grant.register_hook( + 'after_validate_authorization_request', + self.validate_code_challenge, + ) + grant.register_hook( + 'after_validate_token_request', + self.validate_code_verifier, + ) + + def validate_code_challenge(self, grant): + request: OAuth2Request = grant.request + challenge = request.data.get('code_challenge') + method = request.data.get('code_challenge_method') + if not challenge and not method: + return + + if not challenge: + raise InvalidRequestError('Missing "code_challenge"') + + if method and method not in self.SUPPORTED_CODE_CHALLENGE_METHOD: + raise InvalidRequestError('Unsupported "code_challenge_method"') + + def validate_code_verifier(self, grant): + request: OAuth2Request = grant.request + verifier = request.form.get('code_verifier') + + # public client MUST verify code challenge + if self.required and request.auth_method == 'none' and not verifier: + raise InvalidRequestError('Missing "code_verifier"') + + authorization_code = request.authorization_code + challenge = self.get_authorization_code_challenge(authorization_code) + + # ignore, it is the normal RFC6749 authorization_code request + if not challenge and not verifier: + return + + # challenge exists, code_verifier is required + if not verifier: + raise InvalidRequestError('Missing "code_verifier"') + + if not CODE_VERIFIER_PATTERN.match(verifier): + raise InvalidRequestError('Invalid "code_verifier"') + + # 4.6. Server Verifies code_verifier before Returning the Tokens + method = self.get_authorization_code_challenge_method(authorization_code) + if method is None: + method = self.DEFAULT_CODE_CHALLENGE_METHOD + + func = self.CODE_CHALLENGE_METHODS.get(method) + if not func: + raise RuntimeError(f'No verify method for "{method}"') + + # If the values are not equal, an error response indicating + # "invalid_grant" MUST be returned. + if not func(verifier, challenge): + raise InvalidGrantError(description='Code challenge failed.') + + def get_authorization_code_challenge(self, authorization_code): + """Get "code_challenge" associated with this authorization code. + Developers MAY re-implement it in subclass, the default logic:: + + def get_authorization_code_challenge(self, authorization_code): + return authorization_code.code_challenge + + :param authorization_code: the instance of authorization_code + """ + return authorization_code.code_challenge + + def get_authorization_code_challenge_method(self, authorization_code): + """Get "code_challenge_method" associated with this authorization code. + Developers MAY re-implement it in subclass, the default logic:: + + def get_authorization_code_challenge_method(self, authorization_code): + return authorization_code.code_challenge_method + + :param authorization_code: the instance of authorization_code + """ + return authorization_code.code_challenge_method diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7662/__init__.py b/.venv/Lib/site-packages/authlib/oauth2/rfc7662/__init__.py new file mode 100644 index 00000000..045aeda5 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc7662/__init__.py @@ -0,0 +1,15 @@ +""" + authlib.oauth2.rfc7662 + ~~~~~~~~~~~~~~~~~~~~~~ + + This module represents a direct implementation of + OAuth 2.0 Token Introspection. + + https://tools.ietf.org/html/rfc7662 +""" + +from .introspection import IntrospectionEndpoint +from .models import IntrospectionToken +from .token_validator import IntrospectTokenValidator + +__all__ = ['IntrospectionEndpoint', 'IntrospectionToken', 'IntrospectTokenValidator'] diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc7662/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc7662/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..97214944c79b37bdd74021805891a287510f0b4d GIT binary patch literal 677 zcmZuuPiqu06i;Sm|FF0UqTn$nVGqvK1y?8{2uc-1LAN~&gJE`(-3`qoLy|7E2kE!) z?xpwvdg-UwW0{lS$=gD2_2Qdsm%8A~khl!e05>?4VHu^7$B}H6?X->246)XCoOW3IGa7VGE_wtcKXP*^Cb4e7 zFgDZT`Dirsp|Agyo{x>^!je+6Bgu*3mEo2vXGu<&FuZU?l$GQq_;M$-B6{kpKE8q` zWEk&|u|DLAyi?9-TR{ON#cSrdbCumq5~sDavEXhRYcoscu9V5ppPaKGSE`ZTLHv z)>qW`T=N^c*wA^3raqUF(jVvw7}52Y*SlGvnNYKAUr)zx^WxBEpI}Jkgv0y_t_q&T z3$7N~dojtZaQsOHN%@T1>}E~LdQF=_B$Nsz9Hnt}eBFJq-p5OG7uq!wvIk&RA;x$W nbaAvojd_6Z(QtaZx*xZK1KGNOXZJLRYKZk-0I+ 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 Mo_`*MWy7!f4bpJ9^#A|> literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc8414/__pycache__/models.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc8414/__pycache__/models.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e0f1c3b8635fca56e105707856e1d59e2db68c82 GIT binary patch literal 22506 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc8414/__pycache__/well_known.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc8414/__pycache__/well_known.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ce2a0d96d14be0ed9509e7b8e4a477511824e0d6 GIT binary patch literal 1086 zcmZ`&&r2IY6rRm)VlYIjk+yg!0|jZY*=<@CiP}pgwje!dy+|OgyOU&fvm0h6(S`^f zddQ&%DFp=)Je2;RmtOjR7!VrvROqR#`wycc%DfqfF%3pXSdYJg_Q?{|kxxek@UbE(U>!vdi@ zMaNKTiEz9_Y&*5>xH}GBTX}|eEMCGEV^uD4DltTx_>r34$g6{c7?!Hy{IwSu zT;jaKGMdI+*Ji3kctLe(Q7iGXtwpnfk_{*Dw5@ry`AUU;0oLX+# z+RQPFlT-zQ^dez7aWHLbQ}d7M!~Wbgp+E0`Vzu(p8!Zx^zjEb41-$_R6u1}#*hjy{ z(9q5E_?@F#D?V`^pV-f~Vfgc5M4VTc9RAK3P^~HuQ}jA4ydXSP$gDCf~HCX5|+ivwKvJC`(drOY3TuR z;xBOL0OAL5;!orl`O1k~q~6MfU7M)13ggkU-|qO$?9O~`G-^QE@BVl6#RTA|CM#1s zx3i&oeF8D?L2Se(F{tUAhW;**5-s~>TJbA6FOw>@e2dz?o%0IWpf$fn>wcYX`kMxr zfVleE@EftU4_fx=kD8+_Jd#s_4_vN4I<6Q;TMs*1`PTcjR?GKBQ=B@K$43M?0wn^a zh{@CmnS*IU5LGOcm@|iu^Z3Dzl6N}peW!KRXYyJOMHS^*1Wph!;x&2vOAYj?jaUqHt~euB5Ujue%#~7 zte`i%lLRZ(5kEx5Qp*-4RlX=|sA#Baur$~jHZbyhjS!1a;LZ@61uyVHkYb7MB`PSKpfm`JDQXu}v}#iuLd>v)&`sW*+mDKIc`TYL zo$g=yQNglg7{=1Hjq(y`Xab`%2M_-B1$a7N=L_&;zRnk5F#o?VtChOB1S|Mp=||jD GrThUpS`#|} literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc8628/__pycache__/device_code.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc8628/__pycache__/device_code.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4b50a809e8437687d43e3624a99ac0829532419b GIT binary patch literal 9634 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 Kha*UsA^smwnTP5C literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc8628/__pycache__/endpoint.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc8628/__pycache__/endpoint.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c23a35c104e784b3700520f3c3c1e3d7da184008 GIT binary patch literal 8770 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 C{Dq1D literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc8628/__pycache__/errors.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc8628/__pycache__/errors.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a9976abc4dc1fa19be33c6a4875ba25eddda5679 GIT binary patch literal 1634 zcmbVM&ube;6rR-&TTv>vfuv0#(7^;6gCm2Jrb#FTgG~ZWoKo3`3c)hkd9sJBW|Wy( zsm>{s{sFzYxAxQ$dhY*`W6`yz-W2Rpdg*(!t46AH%B=QjX5PGSX1?#e{jJfcGi?7n z_ybPMjQvG}X{#2UvmSO%nPf6bSwCt=5i79=OqPCNvJBC$823BAd25$~uY$hng0CEW zE9hHY@Kt23#WpVdT|%6VXngU>PUerd_pCKGnS#@QR1D5O#Lg)L){Z1=mt@o~%Tl`{ z%ZO4Le@xNFs^`KhqrV0%l|Bk!&%Zx71}gyca33#5E{vZVpGOVH%HmZsal&bGApcc{ly+Vc5NE*4*E4(sTu8>ko&Pr8C&%-OLBPAm~t}{PAJyAb@m% zE1g&n4u$WY@XxpdjFXP{jKvttB7w*P^T=ggN4bUPE^^Ej8F0bj1yRP4-nXknRD(>Q z?0xE8ni`s4pu0?Tlc}-B)mgeJ>>cR7wD;XWS&#?jDHN2SQ<E-5Ntf2c zCx?%A`A8@qI1jZsTX|hTDIlO==6hjL)FbW<7ek}4mbHcik0%?`tgSnr-@ez(Ys;1iE>u_0JfP1f!<*U{`Iq2J z`w=dtFQEGw&7>Sf(Vy(btNGugUWu;b85Ybh7hlut`CHdoHM%-si{{6#UeoOPTh|9G T(X|O%G(RCG&YmxEg>3#8MAuhpN! z!%+h5-#dTtn|?xG;$Xi8yPeK$=rjo~k+U8$eZ`y>;5g~OcDomD@yJLr50ohIQVPZ`Pk7=1$Wemp6!F+X5{!QS~G3*bIZ zYK||P2LD2E#>=)@wC( zs#?4RTXOcL5ETK_n&j4^MD6rmVeUr3s4%m=Z1BR= zGA}O|zBLyL(zN-NDl954aakzV>>n(1VY-5ynQ5_TT%Vn}K3%FXZpo?YV`q4Y+qz+y zaJ+7^`gq?vP90hl09u_9fCl+zWNd3>e0yZP6&~;4&ED4<0$ndc2oV7H>LLbRCxVAd zqf+Jdi^sE53&N;BjDYk`fQzzLO>&`wNBAIXd5iE4C(0>mN}aD%O$f_+y1#)AR-j!D z*yJ)HC#>t`Vu|az6V-Kyi<*V~Azgn|D_X8Z458LX2p=OP0XAG4D;EjOIR)5}_W&B+ zv*V+Ii5=oW(CewW!9!0?IaD3dKapqP%(qEoNaqj>0)|-#k~-`pk6LWbH0=J7gLiL| zRVYelpyxK&!Ec0BRhH{0=aE1d2PW-KwP z%uGTDDLsSV-p1%Ul#orY2)SefDpjD!_#v@+sG^ta7mlT>bWg#W4hDgu`RmFrD{G;x zc=|ZDUQrxiKrdbT8xS=I7|_#3$B6R?Jq6&yY*wy7l@)2+xo>?^@&R^J@^h$u>HlXJ z!Q!slX6YD)s%m*_2H4SCa}h|&!yb-p#V5Ao6Rq&X0NXBr-rL9HPjr=v(N$`rZ@TSA zFIo?OFdr)UefS>$QS8q-QMcqty=dRg_{1299SuzY1N?&_Ff}BGUOMd-DZEba7X;IN z>YzTNcjQ$72<_CF=KSyTYt~jOyPe8DjkaScsAG}IcH;aW+Kb5Z*o)ZTiEL{q+m0un z)|6FpnTSY%w!jn-qX>HOMIfVzD@aBIa5M&1QqxBW?}cxQQ73nvb`5__z literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc8628/device_code.py b/.venv/Lib/site-packages/authlib/oauth2/rfc8628/device_code.py new file mode 100644 index 00000000..68209170 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc8628/device_code.py @@ -0,0 +1,183 @@ +import logging +from ..rfc6749.errors import ( + InvalidRequestError, + UnauthorizedClientError, + AccessDeniedError, +) +from ..rfc6749 import BaseGrant, TokenEndpointMixin +from .errors import ( + AuthorizationPendingError, + ExpiredTokenError, + SlowDownError, +) + +log = logging.getLogger(__name__) +DEVICE_CODE_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:device_code' + + +class DeviceCodeGrant(BaseGrant, TokenEndpointMixin): + """This OAuth 2.0 [RFC6749] protocol extension enables OAuth clients to + request user authorization from applications on devices that have + limited input capabilities or lack a suitable browser. Such devices + include smart TVs, media consoles, picture frames, and printers, + which lack an easy input method or a suitable browser required for + traditional OAuth interactions. Here is the authorization flow:: + + +----------+ +----------------+ + | |>---(A)-- Client Identifier --->| | + | | | | + | |<---(B)-- Device Code, ---<| | + | | User Code, | | + | Device | & Verification URI | | + | Client | | | + | | [polling] | | + | |>---(E)-- Device Code --->| | + | | & Client Identifier | | + | | | Authorization | + | |<---(F)-- Access Token ---<| Server | + +----------+ (& Optional Refresh Token) | | + v | | + : | | + (C) User Code & Verification URI | | + : | | + v | | + +----------+ | | + | End User | | | + | at |<---(D)-- End user reviews --->| | + | Browser | authorization request | | + +----------+ +----------------+ + + This DeviceCodeGrant is the implementation of step (E) and (F). + + (E) While the end user reviews the client's request (step D), the + client repeatedly polls the authorization server to find out if + the user completed the user authorization step. The client + includes the device code and its client identifier. + + (F) The authorization server validates the device code provided by + the client and responds with the access token if the client is + granted access, an error if they are denied access, or an + indication that the client should continue to poll. + """ + GRANT_TYPE = DEVICE_CODE_GRANT_TYPE + TOKEN_ENDPOINT_AUTH_METHODS = ['client_secret_basic', 'client_secret_post', 'none'] + + def validate_token_request(self): + """After displaying instructions to the user, the client creates an + access token request and sends it to the token endpoint with the + following parameters: + + grant_type + REQUIRED. Value MUST be set to + "urn:ietf:params:oauth:grant-type:device_code". + + device_code + REQUIRED. The device verification code, "device_code" from the + device authorization response. + + client_id + REQUIRED if the client is not authenticating with the + authorization server as described in Section 3.2.1. of [RFC6749]. + The client identifier as described in Section 2.2 of [RFC6749]. + + For example, the client makes the following HTTPS request:: + + POST /token HTTP/1.1 + Host: server.example.com + Content-Type: application/x-www-form-urlencoded + + grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code + &device_code=GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS + &client_id=1406020730 + """ + device_code = self.request.data.get('device_code') + if not device_code: + raise InvalidRequestError('Missing "device_code" in payload') + + client = self.authenticate_token_endpoint_client() + if not client.check_grant_type(self.GRANT_TYPE): + raise UnauthorizedClientError() + + credential = self.query_device_credential(device_code) + if not credential: + raise InvalidRequestError('Invalid "device_code" in payload') + + if credential.get_client_id() != client.get_client_id(): + raise UnauthorizedClientError() + + user = self.validate_device_credential(credential) + self.request.user = user + self.request.client = client + self.request.credential = credential + + def create_token_response(self): + """If the access token request is valid and authorized, the + authorization server issues an access token and optional refresh + token. + """ + client = self.request.client + scope = self.request.credential.get_scope() + token = self.generate_token( + user=self.request.user, + scope=scope, + include_refresh_token=client.check_grant_type('refresh_token'), + ) + log.debug('Issue token %r to %r', token, client) + self.save_token(token) + self.execute_hook('process_token', token=token) + return 200, token, self.TOKEN_RESPONSE_HEADER + + def validate_device_credential(self, credential): + if credential.is_expired(): + raise ExpiredTokenError() + + user_code = credential.get_user_code() + user_grant = self.query_user_grant(user_code) + + if user_grant is not None: + user, approved = user_grant + if not approved: + raise AccessDeniedError() + return user + + if self.should_slow_down(credential): + raise SlowDownError() + + raise AuthorizationPendingError() + + def query_device_credential(self, device_code): + """Get device credential from previously savings via ``DeviceAuthorizationEndpoint``. + Developers MUST implement it in subclass:: + + def query_device_credential(self, device_code): + return DeviceCredential.get(device_code) + + :param device_code: a string represent the code. + :return: DeviceCredential instance + """ + raise NotImplementedError() + + def query_user_grant(self, user_code): + """Get user and grant via the given user code. Developers MUST + implement it in subclass:: + + def query_user_grant(self, user_code): + # e.g. we saved user grant info in redis + data = redis.get('oauth_user_grant:' + user_code) + if not data: + return None + + user_id, allowed = data.split() + user = User.get(user_id) + return user, bool(allowed) + + Note, user grant information is saved by verification endpoint. + """ + raise NotImplementedError() + + def should_slow_down(self, credential): + """The authorization request is still pending and polling should + continue, but the interval MUST be increased by 5 seconds for this + and all subsequent requests. + """ + raise NotImplementedError() diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc8628/endpoint.py b/.venv/Lib/site-packages/authlib/oauth2/rfc8628/endpoint.py new file mode 100644 index 00000000..49221f09 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc8628/endpoint.py @@ -0,0 +1,170 @@ +from authlib.consts import default_json_headers +from authlib.common.security import generate_token +from authlib.common.urls import add_params_to_uri + + +class DeviceAuthorizationEndpoint: + """This OAuth 2.0 [RFC6749] protocol extension enables OAuth clients to + request user authorization from applications on devices that have + limited input capabilities or lack a suitable browser. Such devices + include smart TVs, media consoles, picture frames, and printers, + which lack an easy input method or a suitable browser required for + traditional OAuth interactions. Here is the authorization flow:: + + +----------+ +----------------+ + | |>---(A)-- Client Identifier --->| | + | | | | + | |<---(B)-- Device Code, ---<| | + | | User Code, | | + | Device | & Verification URI | | + | Client | | | + | | [polling] | | + | |>---(E)-- Device Code --->| | + | | & Client Identifier | | + | | | Authorization | + | |<---(F)-- Access Token ---<| Server | + +----------+ (& Optional Refresh Token) | | + v | | + : | | + (C) User Code & Verification URI | | + : | | + v | | + +----------+ | | + | End User | | | + | at |<---(D)-- End user reviews --->| | + | Browser | authorization request | | + +----------+ +----------------+ + + This DeviceAuthorizationEndpoint is the implementation of step (A) and (B). + + (A) The client requests access from the authorization server and + includes its client identifier in the request. + + (B) The authorization server issues a device code and an end-user + code and provides the end-user verification URI. + """ + + ENDPOINT_NAME = 'device_authorization' + CLIENT_AUTH_METHODS = ['client_secret_basic', 'client_secret_post', 'none'] + + #: customize "user_code" type, string or digital + USER_CODE_TYPE = 'string' + + #: The lifetime in seconds of the "device_code" and "user_code" + EXPIRES_IN = 1800 + + #: The minimum amount of time in seconds that the client SHOULD + #: wait between polling requests to the token endpoint. + INTERVAL = 5 + + def __init__(self, server): + self.server = server + + def __call__(self, request): + # make it callable for authorization server + # ``create_endpoint_response`` + return self.create_endpoint_response(request) + + def create_endpoint_request(self, request): + return self.server.create_oauth2_request(request) + + def authenticate_client(self, request): + """client_id is REQUIRED **if the client is not** authenticating with the + authorization server as described in Section 3.2.1. of [RFC6749]. + + This means the endpoint support "none" authentication method. In this case, + this endpoint's auth methods are: + + - client_secret_basic + - client_secret_post + - none + + Developers change the value of ``CLIENT_AUTH_METHODS`` in subclass. For + instance:: + + class MyDeviceAuthorizationEndpoint(DeviceAuthorizationEndpoint): + # only support ``client_secret_basic`` auth method + CLIENT_AUTH_METHODS = ['client_secret_basic'] + """ + client = self.server.authenticate_client( + request, self.CLIENT_AUTH_METHODS, self.ENDPOINT_NAME) + request.client = client + return client + + def create_endpoint_response(self, request): + # https://tools.ietf.org/html/rfc8628#section-3.1 + + self.authenticate_client(request) + self.server.validate_requested_scope(request.scope) + + device_code = self.generate_device_code() + user_code = self.generate_user_code() + verification_uri = self.get_verification_uri() + verification_uri_complete = add_params_to_uri( + verification_uri, [('user_code', user_code)]) + + data = { + 'device_code': device_code, + 'user_code': user_code, + 'verification_uri': verification_uri, + 'verification_uri_complete': verification_uri_complete, + 'expires_in': self.EXPIRES_IN, + 'interval': self.INTERVAL, + } + + self.save_device_credential(request.client_id, request.scope, data) + return 200, data, default_json_headers + + def generate_user_code(self): + """A method to generate ``user_code`` value for device authorization + endpoint. This method will generate a random string like MQNA-JPOZ. + Developers can rewrite this method to create their own ``user_code``. + """ + # https://tools.ietf.org/html/rfc8628#section-6.1 + if self.USER_CODE_TYPE == 'digital': + return create_digital_user_code() + return create_string_user_code() + + def generate_device_code(self): + """A method to generate ``device_code`` value for device authorization + endpoint. This method will generate a random string of 42 characters. + Developers can rewrite this method to create their own ``device_code``. + """ + return generate_token(42) + + def get_verification_uri(self): + """Define the ``verification_uri`` of device authorization endpoint. + Developers MUST implement this method in subclass:: + + def get_verification_uri(self): + return 'https://your-company.com/active' + """ + raise NotImplementedError() + + def save_device_credential(self, client_id, scope, data): + """Save device token into database for later use. Developers MUST + implement this method in subclass:: + + def save_device_credential(self, client_id, scope, data): + item = DeviceCredential( + client_id=client_id, + scope=scope, + **data + ) + item.save() + """ + raise NotImplementedError() + + +def create_string_user_code(): + base = 'BCDFGHJKLMNPQRSTVWXZ' + return '-'.join([generate_token(4, base), generate_token(4, base)]) + + +def create_digital_user_code(): + base = '0123456789' + return '-'.join([ + generate_token(3, base), + generate_token(3, base), + generate_token(3, base), + ]) diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc8628/errors.py b/.venv/Lib/site-packages/authlib/oauth2/rfc8628/errors.py new file mode 100644 index 00000000..4a63db82 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc8628/errors.py @@ -0,0 +1,27 @@ +from ..rfc6749.errors import OAuth2Error + +# https://tools.ietf.org/html/rfc8628#section-3.5 + + +class AuthorizationPendingError(OAuth2Error): + """The authorization request is still pending as the end user hasn't + yet completed the user-interaction steps (Section 3.3). + """ + error = 'authorization_pending' + + +class SlowDownError(OAuth2Error): + """A variant of "authorization_pending", the authorization request is + still pending and polling should continue, but the interval MUST + be increased by 5 seconds for this and all subsequent requests. + """ + error = 'slow_down' + + +class ExpiredTokenError(OAuth2Error): + """The "device_code" has expired, and the device authorization + session has concluded. The client MAY commence a new device + authorization request but SHOULD wait for user interaction before + restarting to avoid unnecessary polling. + """ + error = 'expired_token' diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc8628/models.py b/.venv/Lib/site-packages/authlib/oauth2/rfc8628/models.py new file mode 100644 index 00000000..39eb9a13 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc8628/models.py @@ -0,0 +1,38 @@ +import time + + +class DeviceCredentialMixin: + def get_client_id(self): + raise NotImplementedError() + + def get_scope(self): + raise NotImplementedError() + + def get_user_code(self): + raise NotImplementedError() + + def is_expired(self): + raise NotImplementedError() + + +class DeviceCredentialDict(dict, DeviceCredentialMixin): + def get_client_id(self): + return self['client_id'] + + def get_scope(self): + return self.get('scope') + + def get_user_code(self): + return self['user_code'] + + def get_nonce(self): + return self.get('nonce') + + def get_auth_time(self): + return self.get('auth_time') + + def is_expired(self): + expires_at = self.get('expires_at') + if expires_at: + return expires_at < time.time() + return False diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc8693/__init__.py b/.venv/Lib/site-packages/authlib/oauth2/rfc8693/__init__.py new file mode 100644 index 00000000..1a74f856 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc8693/__init__.py @@ -0,0 +1,9 @@ +""" + authlib.oauth2.rfc8693 + ~~~~~~~~~~~~~~~~~~~~~~ + + This module represents an implementation of + OAuth 2.0 Token Exchange. + + https://tools.ietf.org/html/rfc8693 +""" diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc8693/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc8693/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..94dcdbd9f041581b0a235ecc6227e927df60b7ff GIT binary patch literal 400 zcmZut!AiqG5Z$dsOQ0X%ZLdAJkqV+k1VPb*C}_RN;*xA8$HICP=xMLgm2NHGk^Dp zLol^zCPS+0W=P9e9PA(NHPrLJ@EUHMN<(rTO*0@R6eSo?){sCEnHL%4ZVIf_is-n} zU!S=3WJq_(SWiHavqzBzDgoNAORX);$oH+*nV}MFOm&&~sm(KgebUtce{FFdX~Fp$ zTGY9g52qt0bR<>6?sPo92*kv&8)u(~;BFG21TZ=SHDi}DWJX%pDV!)sz_3+xzm2~3 p@i~`DTFze#Z_0_{cBQDgBB`TZ?B1AtW3k;t-PS z5-&xDV-(upW@I^5p-oe)^ARHRBKF$O7<;z)$C zWFpnxvi2@;AOmmCSkcA-dJ0un-lI51fyzsz(r@OhYmc+AuuNs?Mpe$q$jQ`nUSG&+ zy6nHc@Up7-KQZ4P?kf-@TH(?ui%N zC+-DC82P9$2~Y&+HU}sMZio49!cuI+ddcf!;(8D19cO+^=3=9zdcp4c_D+jZCRj>o zGk*N4>_;+u;Mi76x-S3C#Md-72q7cb9L{0{jo~atur{2<2)2f^7@O8&X$(_(vh$;A Gy5p literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc9068/__pycache__/claims.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc9068/__pycache__/claims.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..778e7ab71ea53d6e8e5de25eac7d2b41668eb07f GIT binary patch literal 4083 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc9068/__pycache__/token.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc9068/__pycache__/token.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..54c38c2c623543716872138ed02746ab6a4fb5ea GIT binary patch literal 7977 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 RE+3!yO1%2!5CXBa{|90KG2#FK literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc9068/__pycache__/token_validator.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oauth2/rfc9068/__pycache__/token_validator.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e666ee26858c3955e75a18e0bb3e1791da20c996 GIT binary patch literal 6031 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 w?N6ONTWx>p str: + '''Returns an username from a user ID. + Developers MAY re-implement this method:: + + def get_username(self, user_id): + return User.get(id=user_id).username + ''' + return None diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc9068/revocation.py b/.venv/Lib/site-packages/authlib/oauth2/rfc9068/revocation.py new file mode 100644 index 00000000..9453c79a --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc9068/revocation.py @@ -0,0 +1,70 @@ +from ..rfc6749 import UnsupportedTokenTypeError +from ..rfc7009 import RevocationEndpoint +from authlib.common.errors import ContinueIteration +from authlib.oauth2.rfc6750.errors import InvalidTokenError +from authlib.oauth2.rfc9068.token_validator import JWTBearerTokenValidator + + +class JWTRevocationEndpoint(RevocationEndpoint): + '''JWTRevocationEndpoint inherits from `RFC7009`_ + :class:`~authlib.oauth2.rfc7009.RevocationEndpoint`. + + The JWT access tokens cannot be revoked. + If the submitted token is a JWT access token, then revocation returns + a `invalid_token_error`. + + :param issuer: The issuer identifier. + + :param \\*\\*kwargs: Other parameters are inherited from + :class:`~authlib.oauth2.rfc7009.RevocationEndpoint`. + + Plain text access tokens and other kind of tokens such as refresh_tokens + will be ignored by this endpoint and passed to the next revocation endpoint:: + + class MyJWTAccessTokenRevocationEndpoint(JWTRevocationEndpoint): + def get_jwks(self): + ... + + authorization_server.register_endpoint( + MyJWTAccessTokenRevocationEndpoint( + issuer="https://authorization-server.example.org", + ) + ) + authorization_server.register_endpoint(MyRefreshTokenRevocationEndpoint) + + .. _RFC7009: https://tools.ietf.org/html/rfc7009 + ''' + + def __init__(self, issuer, server=None, *args, **kwargs): + super().__init__(*args, server=server, **kwargs) + self.issuer = issuer + + def authenticate_token(self, request, client): + '''''' + self.check_params(request, client) + + # do not attempt to revoke refresh_tokens + if request.form.get('token_type_hint') not in ('access_token', None): + raise ContinueIteration() + + validator = JWTBearerTokenValidator(issuer=self.issuer, resource_server=None) + validator.get_jwks = self.get_jwks + + try: + validator.authenticate_token(request.form['token']) + + # if the token is not a JWT, fall back to the regular flow + except InvalidTokenError: + raise ContinueIteration() + + # JWT access token cannot be revoked + raise UnsupportedTokenTypeError() + + def get_jwks(self): + '''Return the JWKs that will be used to check the JWT access token signature. + Developers MUST re-implement this method:: + + def get_jwks(self): + return load_jwks("jwks.json") + ''' + raise NotImplementedError() diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc9068/token.py b/.venv/Lib/site-packages/authlib/oauth2/rfc9068/token.py new file mode 100644 index 00000000..6751b88e --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc9068/token.py @@ -0,0 +1,218 @@ +import time +from typing import List +from typing import Optional +from typing import Union + +from authlib.common.security import generate_token +from authlib.jose import jwt +from authlib.oauth2.rfc6750.token import BearerTokenGenerator + + +class JWTBearerTokenGenerator(BearerTokenGenerator): + '''A JWT formatted access token generator. + + :param issuer: The issuer identifier. Will appear in the JWT ``iss`` claim. + + :param \\*\\*kwargs: Other parameters are inherited from + :class:`~authlib.oauth2.rfc6750.token.BearerTokenGenerator`. + + This token generator can be registered into the authorization server:: + + class MyJWTBearerTokenGenerator(JWTBearerTokenGenerator): + def get_jwks(self): + ... + + def get_extra_claims(self, client, grant_type, user, scope): + ... + + authorization_server.register_token_generator( + 'default', + MyJWTBearerTokenGenerator(issuer='https://authorization-server.example.org'), + ) + ''' + + def __init__( + self, + issuer, + alg='RS256', + refresh_token_generator=None, + expires_generator=None, + ): + super().__init__( + self.access_token_generator, refresh_token_generator, expires_generator + ) + self.issuer = issuer + self.alg = alg + + def get_jwks(self): + '''Return the JWKs that will be used to sign the JWT access token. + Developers MUST re-implement this method:: + + def get_jwks(self): + return load_jwks("jwks.json") + ''' + raise NotImplementedError() + + def get_extra_claims(self, client, grant_type, user, scope): + '''Return extra claims to add in the JWT access token. Developers MAY + re-implement this method to add identity claims like the ones in + :ref:`specs/oidc` ID Token, or any other arbitrary claims:: + + def get_extra_claims(self, client, grant_type, user, scope): + return generate_user_info(user, scope) + ''' + return {} + + def get_audiences(self, client, user, scope) -> Union[str, List[str]]: + '''Return the audience for the token. By default this simply returns + the client ID. Developpers MAY re-implement this method to add extra + audiences:: + + def get_audiences(self, client, user, scope): + return [ + client.get_client_id(), + resource_server.get_id(), + ] + ''' + return client.get_client_id() + + def get_acr(self, user) -> Optional[str]: + '''Authentication Context Class Reference. + Returns a user-defined case sensitive string indicating the class of + authentication the used performed. Token audience may refuse to give access to + some resources if some ACR criterias are not met. + :ref:`specs/oidc` defines one special value: ``0`` means that the user + authentication did not respect `ISO29115`_ level 1, and will be refused monetary + operations. Developers MAY re-implement this method:: + + def get_acr(self, user): + if user.insecure_session(): + return '0' + return 'urn:mace:incommon:iap:silver' + + .. _ISO29115: https://www.iso.org/standard/45138.html + ''' + return None + + def get_auth_time(self, user) -> Optional[int]: + '''User authentication time. + Time when the End-User authentication occurred. Its value is a JSON number + representing the number of seconds from 1970-01-01T0:0:0Z as measured in UTC + until the date/time. Developers MAY re-implement this method:: + + def get_auth_time(self, user): + return datetime.timestamp(user.get_auth_time()) + ''' + return None + + def get_amr(self, user) -> Optional[List[str]]: + '''Authentication Methods References. + Defined by :ref:`specs/oidc` as an option list of user-defined case-sensitive + strings indication which authentication methods have been used to authenticate + the user. Developers MAY re-implement this method:: + + def get_amr(self, user): + return ['2FA'] if user.has_2fa_enabled() else [] + ''' + return None + + def get_jti(self, client, grant_type, user, scope) -> str: + '''JWT ID. + Create an unique identifier for the token. Developers MAY re-implement + this method:: + + def get_jti(self, client, grant_type, user scope): + return generate_random_string(16) + ''' + return generate_token(16) + + def access_token_generator(self, client, grant_type, user, scope): + now = int(time.time()) + expires_in = now + self._get_expires_in(client, grant_type) + + token_data = { + 'iss': self.issuer, + 'exp': expires_in, + 'client_id': client.get_client_id(), + 'iat': now, + 'jti': self.get_jti(client, grant_type, user, scope), + 'scope': scope, + } + + # In cases of access tokens obtained through grants where a resource owner is + # involved, such as the authorization code grant, the value of 'sub' SHOULD + # correspond to the subject identifier of the resource owner. + + if user: + token_data['sub'] = user.get_user_id() + + # In cases of access tokens obtained through grants where no resource owner is + # involved, such as the client credentials grant, the value of 'sub' SHOULD + # correspond to an identifier the authorization server uses to indicate the + # client application. + + else: + token_data['sub'] = client.get_client_id() + + # If the request includes a 'resource' parameter (as defined in [RFC8707]), the + # resulting JWT access token 'aud' claim SHOULD have the same value as the + # 'resource' parameter in the request. + + # TODO: Implement this with RFC8707 + if False: # pragma: no cover + ... + + # If the request does not include a 'resource' parameter, the authorization + # server MUST use a default resource indicator in the 'aud' claim. If a 'scope' + # parameter is present in the request, the authorization server SHOULD use it to + # infer the value of the default resource indicator to be used in the 'aud' + # claim. The mechanism through which scopes are associated with default resource + # indicator values is outside the scope of this specification. + + else: + token_data['aud'] = self.get_audiences(client, user, scope) + + # If the values in the 'scope' parameter refer to different default resource + # indicator values, the authorization server SHOULD reject the request with + # 'invalid_scope' as described in Section 4.1.2.1 of [RFC6749]. + # TODO: Implement this with RFC8707 + + if auth_time := self.get_auth_time(user): + token_data['auth_time'] = auth_time + + # The meaning and processing of acr Claim Values is out of scope for this + # specification. + + if acr := self.get_acr(user): + token_data['acr'] = acr + + # The definition of particular values to be used in the amr Claim is beyond the + # scope of this specification. + + if amr := self.get_amr(user): + token_data['amr'] = amr + + # Authorization servers MAY return arbitrary attributes not defined in any + # existing specification, as long as the corresponding claim names are collision + # resistant or the access tokens are meant to be used only within a private + # subsystem. Please refer to Sections 4.2 and 4.3 of [RFC7519] for details. + + token_data.update(self.get_extra_claims(client, grant_type, user, scope)) + + # This specification registers the 'application/at+jwt' media type, which can + # be used to indicate that the content is a JWT access token. JWT access tokens + # MUST include this media type in the 'typ' header parameter to explicitly + # declare that the JWT represents an access token complying with this profile. + # Per the definition of 'typ' in Section 4.1.9 of [RFC7515], it is RECOMMENDED + # that the 'application/' prefix be omitted. Therefore, the 'typ' value used + # SHOULD be 'at+jwt'. + + header = {'alg': self.alg, 'typ': 'at+jwt'} + + access_token = jwt.encode( + header, + token_data, + key=self.get_jwks(), + check=False, + ) + return access_token.decode() diff --git a/.venv/Lib/site-packages/authlib/oauth2/rfc9068/token_validator.py b/.venv/Lib/site-packages/authlib/oauth2/rfc9068/token_validator.py new file mode 100644 index 00000000..dc152e28 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oauth2/rfc9068/token_validator.py @@ -0,0 +1,163 @@ +''' + authlib.oauth2.rfc9068.token_validator + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Implementation of Validating JWT Access Tokens per `Section 4`_. + + .. _`Section 7`: https://www.rfc-editor.org/rfc/rfc9068.html#name-validating-jwt-access-token +''' +from authlib.jose import jwt +from authlib.jose.errors import DecodeError +from authlib.jose.errors import JoseError +from authlib.oauth2.rfc6750.errors import InsufficientScopeError +from authlib.oauth2.rfc6750.errors import InvalidTokenError +from authlib.oauth2.rfc6750.validator import BearerTokenValidator +from .claims import JWTAccessTokenClaims + + +class JWTBearerTokenValidator(BearerTokenValidator): + '''JWTBearerTokenValidator can protect your resource server endpoints. + + :param issuer: The issuer from which tokens will be accepted. + :param resource_server: An identifier for the current resource server, + which must appear in the JWT ``aud`` claim. + + Developers needs to implement the missing methods:: + + class MyJWTBearerTokenValidator(JWTBearerTokenValidator): + def get_jwks(self): + ... + + require_oauth = ResourceProtector() + require_oauth.register_token_validator( + MyJWTBearerTokenValidator( + issuer='https://authorization-server.example.org', + resource_server='https://resource-server.example.org', + ) + ) + + You can then protect resources depending on the JWT `scope`, `groups`, + `roles` or `entitlements` claims:: + + @require_oauth( + scope='profile', + groups='admins', + roles='student', + entitlements='captain', + ) + def resource_endpoint(): + ... + ''' + + def __init__(self, issuer, resource_server, *args, **kwargs): + self.issuer = issuer + self.resource_server = resource_server + super().__init__(*args, **kwargs) + + def get_jwks(self): + '''Return the JWKs that will be used to check the JWT access token signature. + Developers MUST re-implement this method. Typically the JWKs are statically + stored in the resource server configuration, or dynamically downloaded and + cached using :ref:`specs/rfc8414`:: + + def get_jwks(self): + if 'jwks' in cache: + return cache.get('jwks') + + server_metadata = get_server_metadata(self.issuer) + jwks_uri = server_metadata.get('jwks_uri') + cache['jwks'] = requests.get(jwks_uri).json() + return cache['jwks'] + ''' + raise NotImplementedError() + + def validate_iss(self, claims, iss: 'str') -> bool: + # The issuer identifier for the authorization server (which is typically + # obtained during discovery) MUST exactly match the value of the 'iss' + # claim. + return iss == self.issuer + + def authenticate_token(self, token_string): + '''''' + # empty docstring avoids to display the irrelevant parent docstring + + claims_options = { + 'iss': {'essential': True, 'validate': self.validate_iss}, + 'exp': {'essential': True}, + 'aud': {'essential': True, 'value': self.resource_server}, + 'sub': {'essential': True}, + 'client_id': {'essential': True}, + 'iat': {'essential': True}, + 'jti': {'essential': True}, + 'auth_time': {'essential': False}, + 'acr': {'essential': False}, + 'amr': {'essential': False}, + 'scope': {'essential': False}, + 'groups': {'essential': False}, + 'roles': {'essential': False}, + 'entitlements': {'essential': False}, + } + jwks = self.get_jwks() + + # If the JWT access token is encrypted, decrypt it using the keys and algorithms + # that the resource server specified during registration. If encryption was + # negotiated with the authorization server at registration time and the incoming + # JWT access token is not encrypted, the resource server SHOULD reject it. + + # The resource server MUST validate the signature of all incoming JWT access + # tokens according to [RFC7515] using the algorithm specified in the JWT 'alg' + # Header Parameter. The resource server MUST reject any JWT in which the value + # of 'alg' is 'none'. The resource server MUST use the keys provided by the + # authorization server. + try: + return jwt.decode( + token_string, + key=jwks, + claims_cls=JWTAccessTokenClaims, + claims_options=claims_options, + ) + except DecodeError: + raise InvalidTokenError( + realm=self.realm, extra_attributes=self.extra_attributes + ) + + def validate_token( + self, token, scopes, request, groups=None, roles=None, entitlements=None + ): + '''''' + # empty docstring avoids to display the irrelevant parent docstring + try: + token.validate() + except JoseError as exc: + raise InvalidTokenError( + realm=self.realm, extra_attributes=self.extra_attributes + ) from exc + + # If an authorization request includes a scope parameter, the corresponding + # issued JWT access token SHOULD include a 'scope' claim as defined in Section + # 4.2 of [RFC8693]. All the individual scope strings in the 'scope' claim MUST + # have meaning for the resources indicated in the 'aud' claim. See Section 5 for + # more considerations about the relationship between scope strings and resources + # indicated by the 'aud' claim. + + if self.scope_insufficient(token.get('scope', []), scopes): + raise InsufficientScopeError() + + # Many authorization servers embed authorization attributes that go beyond the + # delegated scenarios described by [RFC7519] in the access tokens they issue. + # Typical examples include resource owner memberships in roles and groups that + # are relevant to the resource being accessed, entitlements assigned to the + # resource owner for the targeted resource that the authorization server knows + # about, and so on. An authorization server wanting to include such attributes + # in a JWT access token SHOULD use the 'groups', 'roles', and 'entitlements' + # attributes of the 'User' resource schema defined by Section 4.1.2 of + # [RFC7643]) as claim types. + + if self.scope_insufficient(token.get('groups'), groups): + raise InvalidTokenError() + + if self.scope_insufficient(token.get('roles'), roles): + raise InvalidTokenError() + + if self.scope_insufficient(token.get('entitlements'), entitlements): + raise InvalidTokenError() diff --git a/.venv/Lib/site-packages/authlib/oidc/__init__.py b/.venv/Lib/site-packages/authlib/oidc/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/.venv/Lib/site-packages/authlib/oidc/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oidc/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bc3fa9eed93ee0f3b3d945a89ce7eb6130a9bc7e GIT binary patch literal 193 zcmZ3^%ge<81i#(4rh@3lAOZ#$p^VRLK*n^26oz01O-8?!3`I;p{%4TnuMiijnB@GF z%)IoN(EPLzkHqBc;+UY++|=Bp)S}el?m%-2$MZ#PrnS zn8ebOjGW9Q{rt?7Wc~Q~%)HE!_;|g7%3mBdx%nxjIjMFW@(fPNh|zO;3YV^eXPB9XlxsJ@7qT{Fg5=MUSbC+ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oidc/core/__pycache__/claims.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oidc/core/__pycache__/claims.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..95e8a1694f1bd127f4c4634f15a110a5d8017451 GIT binary patch literal 14374 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 T5Fw#1X$^=kiu7EMvUm7@I;uA^ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oidc/core/__pycache__/errors.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oidc/core/__pycache__/errors.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5cb176cabea397304795a48a77eca38797bd8276 GIT binary patch literal 4612 zcmb_f&rcgi6rQyW7=sB(2u(;4qmZUSEvAjyL(?A-1(cvtXdx&nwX|Ax2H4i#ac0(3 zNiI3`e+W`99I94P&;36*B42yz%?M8ErSHwIcNgzUu`Sm4d71a-?fc$*^WN;A#bSZL z_20w4`N9w(|KLBZt1q}Y9We-bMHpd5g;b3#!yp;*kg&|Jgk`z$N0yMk;Ok#o8Li8K zt}mg>YF$6*1`@iQ*5yGrn9%iUT>*4M30=R|4TG+j&<$wa2)ba|~C1>NO@Zcyv4 zfbMESS72isWaiqx2zSP446V)Ay}f%&QVMAYInY0lGku+o!_OUNc43~a8{{!9T;LNK_moxgy9(Sn+&jjOY z&7(C-T2&75(S55@=h~IyTVPb&^&Hy|3q$A1qu|;VF8`2j*FEhi-A;S5E!Pzu24KU} zD)1bLzyYu@l{u#&l`y*X9m zwh9JjZQ;7y_TX3Y*^kYSN_$?lGL50?)N2=wu~^KCN4oKr>*POxQ5or!)PUoFW(AJXyS7wgm%NpD*tjg=W%B$O4a%FSZ z=H=2pclXOH&URTj9-pm&k+sWJ*@E~g&i0&em_3J~&uQPPRC^|It7?&h8#M*uW%y}k z2Kw?%f?|{ur(Z7NM~<{+^g!AxD`MAaqbu)@t_UXLPn?xH`&}{<*q_2S?Ws#<(iB!| zKix8uwjsPYVvbZW`w=DO04`+_gC>y=mp`Nn4{JcH zjKvZTl_bqYP(8!-gfg?U0~^ovsHK#!9SduasG+@e(sqs+fy=kh;2op^ikUPT#4FoWoCY|f2O5koyKwe#Sg;K@*O&DX z;rZ`afuw)xG3(Nacc8Fjg)8JQw4#<9oV!(m=dDaE)v8#b!ol-cT zVWg|6{bB;MisF;BtmbfYp(v2zt$0>(Mh{uNaXzbS+do0u@Dux4EU~czXqYKTVJlg! z(&$ewHOAY~3hg%?@FW68@g)Mj0U|mv9p@H~atp`9x8qRJwg;%!gD6*pw^6UvgoGC3 zBmESSu6;+D;CO0=uHx&l&f*asn?b;^C=sQ`wHE7OiWyAdEFC0;m?es@;hO;Y;3)Ut zc=+6b5N&$^c{2bB+arlnuV`mD^-c=kI!cWjEv&#>vje=-5WYn55WWe#{-VAgUsSa1 z0q^8G-*uEH^~+BZ@%@fgHu4Z(-U%6V-3jJ9h#AF78s^2L+~V=@-8g2nU7ZJ8QXqC1May=*eqs0@pB4!- literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oidc/core/__pycache__/models.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oidc/core/__pycache__/models.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..39748e60a0fd3084cd0e33933ecfb1080897177f GIT binary patch literal 1022 zcmbtS&ubGw6rR~l>>8VRC`1sHwdo}XH&Ba35kXX?o?w~Uz0SRbCV%jw*F-V&P#tsQgFm_Es_HpIbr9tU2X_mjLZIfp8TO+x}ML6+f z$dlVVfQRAhF!7Jl^#_Ty&Cla!N`PP!(lr9QL%OD->6QW$o0f#4@sHD0je$!A=NA#C zM4mX?#mGLc+}_eAom^>yv{w_J_^@h^y=VkB@7r<+eeu;@4WzDI(sx*>2P^J z9!3yDA|bdd1Q!@Cr4aQ~#b_TsyK~*esxTS2PkH~zJTJgkQJW8j?SVAfD8p1aD zQoHoA*7#Iw99WIHn!tZdZBtK8iDWX2|9x`e6!HoSAs>=ZPc5q|xkaz^LbO;pDt(SHGbyDgiyA2F4^Ua6DEfCexUlg}g}*O2)672sdtm;s literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oidc/core/__pycache__/util.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oidc/core/__pycache__/util.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0bdd3370463cb020b8597782a8ecfa2822039484 GIT binary patch literal 952 zcmZuv%}*0S6rbJg2e`q)0`(&pl^C!#mL3QYF%lCKF&Yjcm%2%_-5J`A`$2Z5C}wMV zki=sT5^I!%6V`C{|Da|Qn@u=*;?{&4Tzs=>D~-P0dGkJh@6EjVHZ*hr0i8YmLEZ@n z{pL!S#Ex)s3xrPyBP^IG$9K^bEHNiqQce;OmfoXW1PiMu6*=Z9D=9G;U{1cU#Rv^X z%C1SZb&@a4%@SL8FwwifJU9wVf^{+s<)Mh+30TBvTfD-(A$>u+Vnt-&?-DzQ;6e00 zARKU%kSdZVQLwHe5qT2h6*}aheLy+rA@yr}J%nyN-}hl1^bC~<8|*2F$$w=p(vOD4 zx8Uu!RibR@d2&SU zJr!nV*hO{CS%0yt>945zoLIyv5SLILCQ8)ICb2iwXGTG#1|xSjAV`CTRISW-lQWKi z^%>o9$xN9UW@ck67}i~)F_JH7<~lH1a>t-1pA_8&RzovW8vp!j${8+3dYKiKT zqeOD&_1<7(wwcKKiEMSbC6Bg|5FKkJMnABYaM=X=k0&z4_0ofcB@)qjI`wSSak8``E=9jW38QA9CE0=rmf zu7*plaa|a$QPny(h2>fpMTi>D*lker8rjw-R>QVdv@cVLhrLlUfw*YZY8vb-<-I9KvsEe{?7$!IMaQde%$D8VejQgC563nNrkKZiw=ZOp2+!Wvg5ReRAO z#OIulSF}>oXnof^_S86wBkv};9}WC)l6hAkKm;Hm3n31{>&_sadFL$fGM2+(s+#-= zGS8ppW6lC6VKj8YM1m8Q&(9n}Sj=)ly6MBZc_I=zvZ`?D>EB YS6`rm`R`mBW?NgLEj%{LC3lqdH^dNwi2wiq literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oidc/core/grants/__pycache__/code.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oidc/core/grants/__pycache__/code.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4afd65f5348fce960f36d2d3efe75f973432c925 GIT binary patch literal 6799 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 P^Ml`F?|0h_G5P-wfGw>n literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oidc/core/grants/__pycache__/hybrid.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oidc/core/grants/__pycache__/hybrid.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..47fb4bd562776120a215b2f3b8a3e976d6b8f5dd GIT binary patch literal 5095 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oidc/core/grants/__pycache__/util.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oidc/core/grants/__pycache__/util.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2ebb6425bbed98a6633de83497b7829deaa689b8 GIT binary patch literal 5271 zcmb6dTWlN0aqq?Bo02G5wrtrH6-#DnNs$xTwN0zBE!j?@s)gkuD65n`^G?!9B#+rU zDv^2w2qQq1Kt+@wg_Xhq_~klqKJrr_pZ)CTQDBh60YU{7E#N;Ic7D>I&MqlRCp#{> zT+Z$7&g|~Y&dko-UqT^2g7Tm1e^q+g5c(&1*)43d@#G#f?jjkakR~6`J9jvXj{m7a$-uPZBN#l^QC+_f65Q+y&Z}BpSMr97D8mponuUWW`9C=g;4U)ujhW~^ygh97lo*rII2qtF0%@?* zjt98St1{++7B~|q`;Lb`be*sgi~TS=abY&2$!dOn_E*~6ts7EiNuRx`yGYYzaVM-AfxmtNKpAa^dN#+Zp}tzEuYAo8v|E8w8w-^I>(D8SKlKDq(6tQV zf46v`LFJJGzV9LvE$)t>#g-&0yE@w%BMq53ATQ2E-CCu@o17jnd0muQ6QzmpXfZ*m zCMR=CbaosCjCLciJBpCWnCw^leHeY%TK^7Xauu@YXUcu(dD!YL2{LC2%Ltz|h;W+4 z6x=(Og(bQh++nou;s9Ts=E}gq!xk5J7$dreWAdgzvBdi@!^0L&CC=oqXo4i%d?vi0 zJq4`g3Wg(OiC#N=UdtJgO34D!taQx9Uy{IHSjzBdJA0>ojdOC&URq}G0%;<;>d|fBU5u*hY2|3-=RS;`#?xs02J_Vyh zUG+MEGO|M*>+jS;C%y~yZ-x3RH>#nbT4)HgHqyCXszv(BH$Z>uh!eW(NOv7EzJB{? zd~I@l3J}(UJ7Q?#(3aS3iQN@1fbDS1K627NK2jIh$mnAP;3)xh#QH|-UKHv2IQvod z!~A-_eBB0GAUq89i_}% zaGPGGWqL5wD$g-EPLG-_ju=7<39b>hlHXxuZU(W$oIowz=5&CPe}d~L8x(<#l7N_s=n3|6@&v^LOYUrj?$Vw|Q$uPj3B{)nx5{?l-*i7*FI6R!7@;+P^ zdYVq*cnLl6@AzdH)QL=pDm64I+|ne9jE7)!l%OpD00jz0*QdS<9@`2Y+kCqkJXs5# zEKh>4iOzJ|fhf_LNoKp_q&0B0+A&eA^X|&6zV}XCJkN;SlNF4m%)4gg-sR?0f1ennzghNt zsoPJv1zz%--ZE?YOI|oC-t@!IvkEhqUYWTklme!R1yeKwGMgm5J{;SB@CMmSvzR{c zbuQ28UJ2&l=p3j*ME*>X52!*ZXa--fTJV3aCeYOam3@l3x2SpGCSj0^uh1UmVv9%c z(t^sE0h7HCa^CaPZazVM#p#6LaG;;nxiz>O}DHg!%Dwy~~#{<{ACM$`MBQ)mm z5vQ3}^K+WREh#IQ=rKM+zCy9s}U;gxKNo+I!$|XQL zJ*X{eM>-mHW9GvZyX$y8;E8zZ2tfIIJ&e56t@YVQV{77uSoI#>5d*|Vt}@%lPJTOZ z_G{ytnd-ph+Q8-Nu`9J>R{+af^&Z)Y9=?12)AO6ZtwvARqNmGKwn%JKm}0hj2fiIV z_f7C`nd;!1wZS*5y>Hce-vTmU)!Vbf2mUa9XL{p&mG7$+GCBx`}B#V4Qju|(addA>%?(`03)8E(8Ovn2>VDuD28k@*k6UrwMG z8Y_e~&-c^&mG@v!X&wk@AW#uZLH5iubKs?6f8uU9MB%vdQX zm*NYmEGzkVEHCBY4LFI>NQ*W{#vz^X5UwNxlkT0|VC$m~c%If3L*d_TLOr`$dE_=Wm_`8<0s`7REu*u}quDQ>Oy zwxZo#W+-b-k*ULA%#L>oxFabbxOaY0Q}g%@prz8oV#bLIh;|* zIv#pTy2BH7ayUp(b>i8Z9=73MdtWGN{A<7`fBhc-ATSX-Hv?N@zXhQM&xWosbq@K0 zbwBFpyxaXL#Ih~fdC-v)brD`4lfI_}K&vAFt&YH&2T0nYAFqD2`bDBLRqYwA^^AUf zwi>xmi(FXa!BcNcSVym0JvXe#4a<9D2bLAL#1ocyVmo{SJmlOrMJqg64Num>lWW`> zXZsFqzP#mo$@0Cli(pvciE4PF7M>so{|fh6@ypflm0I|U<-M{K2yd_(iYryIp zv;u<`KiF`xJTSUjNSiuY6049vR`)crW(@9j1_Dx&LE|pyZ{HsunXJiu#kp+<91sf> z{5}dYbF=&i1rHRBKouVbOh?Q#z5?JL@)p+Vw}Ld>>g3Bog2fQSAxth(2uTM>dys%u zqT>!i@k?Zo0%+);0s!0bpkODt!n!xb$~o)s%TVpep|$sR#I}v=mUt8@OxH9fQOqItGbJbPN)c&=|ROkF2fOz9XA&!>K^sBO7@!S>+dc*99`+}qszE{xL2qGc!wMeJQCzX0b{v;8k z86l18X|zJkh>H44P!}>zJopdZB)GLATr^mQSCSd&LjWN{XBZm=%JgTWvzEKs=oQOd zZFJ0XR~rpk?rNi?^}K4Me#>3!EYGlD%KrxlvrGbxeHZw97|3tk;DVQdw8IS!ql-VY f6GL^Ohq*-X_k# 1: + # If this parameter contains none with any other value, + # an error is returned + raise InvalidRequestError( + 'Invalid "prompt" parameter.', + redirect_uri=redirect_uri, + redirect_fragment=redirect_fragment) + + prompt = _guess_prompt_value( + end_user, prompts, redirect_uri, redirect_fragment=redirect_fragment) + if prompt: + grant.prompt = prompt + return grant + + +def validate_nonce(request, exists_nonce, required=False): + nonce = request.data.get('nonce') + if not nonce: + if required: + raise InvalidRequestError('Missing "nonce" in request.') + return True + + if exists_nonce(nonce, request): + raise InvalidRequestError('Replay attack') + + +def generate_id_token( + token, user_info, key, iss, aud, alg='RS256', exp=3600, + nonce=None, auth_time=None, code=None): + + now = int(time.time()) + if auth_time is None: + auth_time = now + + payload = { + 'iss': iss, + 'aud': aud, + 'iat': now, + 'exp': now + exp, + 'auth_time': auth_time, + } + if nonce: + payload['nonce'] = nonce + + if code: + payload['c_hash'] = to_native(create_half_hash(code, alg)) + + access_token = token.get('access_token') + if access_token: + payload['at_hash'] = to_native(create_half_hash(access_token, alg)) + + payload.update(user_info) + return to_native(jwt.encode({'alg': alg}, payload, key)) + + +def create_response_mode_response(redirect_uri, params, response_mode): + if response_mode == 'form_post': + tpl = ( + 'Redirecting' + '' + '{}' + ) + inputs = ''.join([ + ''.format( + quote_url(k), quote_url(v)) + for k, v in params + ]) + body = tpl.format(quote_url(redirect_uri), inputs) + return 200, body, [('Content-Type', 'text/html; charset=utf-8')] + + if response_mode == 'query': + uri = add_params_to_uri(redirect_uri, params, fragment=False) + elif response_mode == 'fragment': + uri = add_params_to_uri(redirect_uri, params, fragment=True) + else: + raise InvalidRequestError('Invalid "response_mode" value') + + return 302, '', [('Location', uri)] + + +def _guess_prompt_value(end_user, prompts, redirect_uri, redirect_fragment): + # http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest + + if not end_user and 'login' in prompts: + return 'login' + + if 'consent' in prompts: + if not end_user: + raise ConsentRequiredError( + redirect_uri=redirect_uri, + redirect_fragment=redirect_fragment) + return 'consent' + elif 'select_account' in prompts: + if not end_user: + raise AccountSelectionRequiredError( + redirect_uri=redirect_uri, + redirect_fragment=redirect_fragment) + return 'select_account' diff --git a/.venv/Lib/site-packages/authlib/oidc/core/models.py b/.venv/Lib/site-packages/authlib/oidc/core/models.py new file mode 100644 index 00000000..5f414050 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oidc/core/models.py @@ -0,0 +1,13 @@ +from authlib.oauth2.rfc6749 import ( + AuthorizationCodeMixin as _AuthorizationCodeMixin +) + + +class AuthorizationCodeMixin(_AuthorizationCodeMixin): + def get_nonce(self): + """Get "nonce" value of the authorization code object.""" + raise NotImplementedError() + + def get_auth_time(self): + """Get "auth_time" value of the authorization code object.""" + raise NotImplementedError() diff --git a/.venv/Lib/site-packages/authlib/oidc/core/util.py b/.venv/Lib/site-packages/authlib/oidc/core/util.py new file mode 100644 index 00000000..6df005d2 --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oidc/core/util.py @@ -0,0 +1,12 @@ +import hashlib +from authlib.common.encoding import to_bytes, urlsafe_b64encode + + +def create_half_hash(s, alg): + hash_type = f'sha{alg[2:]}' + hash_alg = getattr(hashlib, hash_type, None) + if not hash_alg: + return None + data_digest = hash_alg(to_bytes(s)).digest() + slice_index = int(len(data_digest) / 2) + return urlsafe_b64encode(data_digest[:slice_index]) diff --git a/.venv/Lib/site-packages/authlib/oidc/discovery/__init__.py b/.venv/Lib/site-packages/authlib/oidc/discovery/__init__.py new file mode 100644 index 00000000..1e76401b --- /dev/null +++ b/.venv/Lib/site-packages/authlib/oidc/discovery/__init__.py @@ -0,0 +1,13 @@ +""" + authlib.oidc.discover + ~~~~~~~~~~~~~~~~~~~~~ + + OpenID Connect Discovery 1.0 Implementation. + + https://openid.net/specs/openid-connect-discovery-1_0.html +""" + +from .models import OpenIDProviderMetadata +from .well_known import get_well_known_url + +__all__ = ['OpenIDProviderMetadata', 'get_well_known_url'] diff --git a/.venv/Lib/site-packages/authlib/oidc/discovery/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oidc/discovery/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6be2443ba444bd4f9c97fe45d29fdc8dd5eb219d GIT binary patch literal 569 zcmZuv&1xGl5SG?!yKL)A4mmG`9-QLcAGoZkSRr?!KbbS?lun{ zzE0KIb};Q6vV&yg3l;sskx84*ch^|5};$bF8;&Ja912c_7VHs_j+t+F*F z*$~ycc4OXTOc>7Cyiphd%B|3O^pCQNtip0k!oHC^B$DNqUN_@LNIlFxo3EdabAINs z4>(&f01J+T=8z>5(39+q9Ar*<=#&_g55Z-d#irF_)4yY-j7cp$V@Ww(K6-)ej1|1J xPq17yrt6_v)F`Ekph?38sniak&t_!*{{8XLMdxL9<`2U2u7>~s literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oidc/discovery/__pycache__/models.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oidc/discovery/__pycache__/models.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..21ae82cc8b759725bdfa7c18d5028567e9b8abac GIT binary patch literal 15745 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/authlib/oidc/discovery/__pycache__/well_known.cpython-311.pyc b/.venv/Lib/site-packages/authlib/oidc/discovery/__pycache__/well_known.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fcb7bbdcb39be41c58b3f44ade1c5df593a8a625 GIT binary patch literal 893 zcmaJBjE6uz?@*Vq+KTLPtlaDfu)Au@qZb_uwIIEBz5PL?2W72VmsMADhNlie5_ zGIR=sbW4T~o?1%h{tp{G7_Fs4H$yge=}ESehSGjW@9y4x@4fFm>9ek+;+fSb~o0E9p6;$Y8|aN54yAd zt4daD_ew;f7IB>Q6OXk#bg=gdwWzEkDuhosYElc8i7hGf&~szMNTrZMUUhA`GfrLw z?IKo1vQB2MKS|`RB;2!{JmN(9+(T90anRh0)Cdvd$YXLEG$lnjBgX{h+N(L^R$`7d zh)40d&AckD`P>S%Wwju|h2*rs!^s8lh9&FSc#xR35hUmJf<*MeFu$j0BCbr>&*aTk z-n1E}Ud=pU)%_jIJ`v^~afy3GI1x7SY+@Qs;x)}(dSnVJ$$CSPtQrxf<;%K5k8+G+ zJBO*TS(EV7TqwB`P1R_e1`lgQR&HGt)i=Md%7+rfzA|TEya`ev^2<+`pMD{eQBt#Tr~&!+E8CR+a9GKyf2(>jnbKm!g=9?7^Ihn>E-@P zagZ+dF&Ha2fU;vdI_KG5q~R aL7A}zAsm5c{kzXNp~IJO4E|@M=3.8 +License-File: LICENSE +Requires-Dist: pycparser + + +CFFI +==== + +Foreign Function Interface for Python calling C code. +Please see the `Documentation `_. + +Contact +------- + +`Mailing list `_ diff --git a/.venv/Lib/site-packages/cffi-1.16.0.dist-info/RECORD b/.venv/Lib/site-packages/cffi-1.16.0.dist-info/RECORD new file mode 100644 index 00000000..053bb7f5 --- /dev/null +++ b/.venv/Lib/site-packages/cffi-1.16.0.dist-info/RECORD @@ -0,0 +1,48 @@ +_cffi_backend.cp311-win_amd64.pyd,sha256=WXZ7CRiFm-3fKKfWalBDFBH_2UDDKz6DR-bZOLYPrN8,181248 +cffi-1.16.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +cffi-1.16.0.dist-info/LICENSE,sha256=esEZUOct9bRcUXFqeyLnuzSzJNZ_Bl4pOBUt1HLEgV8,1320 +cffi-1.16.0.dist-info/METADATA,sha256=JSVpnYGQLm_ch1eupKWpcINOEYPZdnejqtsSbz-LeJg,1519 +cffi-1.16.0.dist-info/RECORD,, +cffi-1.16.0.dist-info/WHEEL,sha256=badvNS-y9fEq0X-qzdZYvql_JFjI7Xfw-wR8FsjoK0I,102 +cffi-1.16.0.dist-info/entry_points.txt,sha256=y6jTxnyeuLnL-XJcDv8uML3n6wyYiGRg8MTp_QGJ9Ho,75 +cffi-1.16.0.dist-info/top_level.txt,sha256=rE7WR3rZfNKxWI9-jn6hsHCAl7MDkB-FmuQbxWjFehQ,19 +cffi/__init__.py,sha256=3woJiTGr2RG4_jOJxsYUhkS6p6N_oz8OBfXTiegoUwQ,527 +cffi/__pycache__/__init__.cpython-311.pyc,, +cffi/__pycache__/_imp_emulation.cpython-311.pyc,, +cffi/__pycache__/_shimmed_dist_utils.cpython-311.pyc,, +cffi/__pycache__/api.cpython-311.pyc,, +cffi/__pycache__/backend_ctypes.cpython-311.pyc,, +cffi/__pycache__/cffi_opcode.cpython-311.pyc,, +cffi/__pycache__/commontypes.cpython-311.pyc,, +cffi/__pycache__/cparser.cpython-311.pyc,, +cffi/__pycache__/error.cpython-311.pyc,, +cffi/__pycache__/ffiplatform.cpython-311.pyc,, +cffi/__pycache__/lock.cpython-311.pyc,, +cffi/__pycache__/model.cpython-311.pyc,, +cffi/__pycache__/pkgconfig.cpython-311.pyc,, +cffi/__pycache__/recompiler.cpython-311.pyc,, +cffi/__pycache__/setuptools_ext.cpython-311.pyc,, +cffi/__pycache__/vengine_cpy.cpython-311.pyc,, +cffi/__pycache__/vengine_gen.cpython-311.pyc,, +cffi/__pycache__/verifier.cpython-311.pyc,, +cffi/_cffi_errors.h,sha256=G0bGOb-6SNIO0UY8KEN3cM40Yd1JuR5bETQ8Ni5PxWY,4057 +cffi/_cffi_include.h,sha256=H7cgdZR-POwmUFrIup4jOGzmje8YoQHhN99gVFg7w08,15185 +cffi/_embedding.h,sha256=hWxZXkHEqIGELOPKKYCspuZS0su3M6Tc0sL0M2g7vzI,19337 +cffi/_imp_emulation.py,sha256=pGPNO0osgce1iFDCmVQgTEOTs4IJtJsiE8nGrFafjVA,3043 +cffi/_shimmed_dist_utils.py,sha256=39wmD8jFLis74FzCFesJ__UOPfWu4WiECozCarZcAXE,2048 +cffi/api.py,sha256=tqyTU_x_WPPFaYof4MC8PrlewL15nW9GGsr6eDJ1vsk,43050 +cffi/backend_ctypes.py,sha256=BHN3q2giL2_Y8wMDST2CIcc_qoMrs65qV9Ob5JvxBZ4,43575 +cffi/cffi_opcode.py,sha256=57P2NHLZkuTWueZybu5iosWljb6ocQmUXzGrCplrnyE,5911 +cffi/commontypes.py,sha256=mEZD4g0qtadnv6O6CEXvMQaJ1K6SRbG5S1h4YvVZHOU,2769 +cffi/cparser.py,sha256=CwVk2V3ATYlCoywG6zN35w6UQ7zj2EWX68KjoJp2Mzk,45237 +cffi/error.py,sha256=Bka7fSV22aIglTQDPIDfpnxTc1aWZLMQdQOJY-h_PUA,908 +cffi/ffiplatform.py,sha256=n1FZYFwdmzQ8bmBQWTvCWWGYu82alBTjZVc3gXjBv38,3697 +cffi/lock.py,sha256=vnbsel7392Ib8gGBifIfAfc7MHteSwd3nP725pvc25Q,777 +cffi/model.py,sha256=cafvJJEePx0PXq29IQNKpBsFabNqZk7DTkeDMZSz3nc,22408 +cffi/parse_c_type.h,sha256=fKYNqWNX5f9kZNNhbXcRLTOlpRGRhh8eCLyHmTXIZnQ,6157 +cffi/pkgconfig.py,sha256=9zDcDf0XKIJaxFHLg7e-W8-Xb8Yq5hdhqH7kLg-ugRo,4495 +cffi/recompiler.py,sha256=alZMkdmqd0dCgUQ0bxEfDNTlPUe4iGV57KUNij-vPUs,66182 +cffi/setuptools_ext.py,sha256=60wpMrriB-lC7RPG90Pc6dIbE2nVo6u1ye_S6Ei2_sM,9087 +cffi/vengine_cpy.py,sha256=vbMYENE5jlItSjb2k62AIoWbS66uBjLWOxzisRfUg5Q,44428 +cffi/vengine_gen.py,sha256=mykUhLFJIcV6AyQ5cMJ3n_7dbqw0a9WEjXW0E-WfgiI,27359 +cffi/verifier.py,sha256=Tt_mMNvykn3cFSAM7tSqaON2oaD1fbWyFqbZ2ugP98Y,11488 diff --git a/.venv/Lib/site-packages/cffi-1.16.0.dist-info/WHEEL b/.venv/Lib/site-packages/cffi-1.16.0.dist-info/WHEEL new file mode 100644 index 00000000..6d160455 --- /dev/null +++ b/.venv/Lib/site-packages/cffi-1.16.0.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.41.2) +Root-Is-Purelib: false +Tag: cp311-cp311-win_amd64 + diff --git a/.venv/Lib/site-packages/cffi-1.16.0.dist-info/entry_points.txt b/.venv/Lib/site-packages/cffi-1.16.0.dist-info/entry_points.txt new file mode 100644 index 00000000..4b0274f2 --- /dev/null +++ b/.venv/Lib/site-packages/cffi-1.16.0.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[distutils.setup_keywords] +cffi_modules = cffi.setuptools_ext:cffi_modules diff --git a/.venv/Lib/site-packages/cffi-1.16.0.dist-info/top_level.txt b/.venv/Lib/site-packages/cffi-1.16.0.dist-info/top_level.txt new file mode 100644 index 00000000..f6457795 --- /dev/null +++ b/.venv/Lib/site-packages/cffi-1.16.0.dist-info/top_level.txt @@ -0,0 +1,2 @@ +_cffi_backend +cffi diff --git a/.venv/Lib/site-packages/cffi/__init__.py b/.venv/Lib/site-packages/cffi/__init__.py new file mode 100644 index 00000000..90dedf43 --- /dev/null +++ b/.venv/Lib/site-packages/cffi/__init__.py @@ -0,0 +1,14 @@ +__all__ = ['FFI', 'VerificationError', 'VerificationMissing', 'CDefError', + 'FFIError'] + +from .api import FFI +from .error import CDefError, FFIError, VerificationError, VerificationMissing +from .error import PkgConfigError + +__version__ = "1.16.0" +__version_info__ = (1, 16, 0) + +# The verifier module file names are based on the CRC32 of a string that +# contains the following version number. It may be older than __version__ +# if nothing is clearly incompatible. +__version_verifier_modules__ = "0.8.6" diff --git a/.venv/Lib/site-packages/cffi/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/cffi/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f3afbb9e84537e3ca6a2fd23fda3a96417b2fd49 GIT binary patch literal 620 zcmah_OKTKC5U!s0?wYuosFw(Ok~uggmmopBB*q6Zh_6F4&`f4}h9>h^x;G2SDgVN| z7x4%9KjygfN$`~0KyLA3^(-L~1dHmgs=lu3s_Jh`OG7~U{qhIDX#xB)!KGl_%lR8L zU!Z^tz7h%<$*hu87PW}+?b5Cs>QpXuE021WPyL>EkPm2pzDoz0M~9hDM_KRz!a?Y2 zdw2J>zV(?)k&85$il%-cWh3> zcDWhtUoB*S#d^fpj7x<(VA=R85Ov-lvv$Q`8t%&_tD5Yn;*xT8P(m2sm|LGhawtwr-<-4b&`O5tk R#@!GeJZfQWq4G9%{{w8Mt_J`B literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cffi/__pycache__/_imp_emulation.cpython-311.pyc b/.venv/Lib/site-packages/cffi/__pycache__/_imp_emulation.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..745ebf8d6b784709ce97ee320d084cbbb163b6c5 GIT binary patch literal 4705 zcmb^!TWlN0agTST`1I*WO0q;Iq9w&PotSRwSFI>cWr?AB22nlBhOw}cIDKbK)s0fwPNAxK}#Guj1WJk&vF={xKG^NZDvxe)FmWTz~>66xo zRr}i_HWo#8v4#lEc0@W^V}xN%5j$&+I9N->$yy^_tS!>b?uzuV^m{0>o3*o@?-7w+ z_%rbDo71#<8(kyk(A$L9@dzvLB~;>omr|{<_*=`oz(tdp_!ZSEa7ivE)@o*6j4mwm zNr_LZCcqOyW|d1rOFc-(SU^mvSo|`d=7g2tBLaGTq{D#30GsHM9s>gg9T*rfFae0e z*C@CRZu0o&0B(XI-$PP^iO?eMSS#b`HvI3_Y6#`PygOuZUt0NwEWwgHWbv5aF00F; zEU^l_tPaB&u-McRa4X zc(oA!=!9&4sX-H70GaQjvd{$`;1vax$3j!nfl2@PcU5|*MQO*hti8pz3U97cA6=21 z2dV^sn$liMz$ZwxH#Smq=KSf?feZc_m984ENnlRR&HBeen#83=*dd~7 z5Hrg{oKuYpD-s8rj}!5!@OV6$(N$~fmJz&|1)mrN0DDAN-y>W7`<4FJDkRju#vA9K z805{{+6vrXQ4URj;Y&Bu}t@_pDxh@8y8CSLD_h) zx}pb* zSQcDzyTx)OOGz&_B^Dccv-;i!IiZ8Gev+eDLzcp>Jg5JkMkTZQ9itka(Vl4x*@9#Z z?du>gEXsn7!OHl|*9x{)Tt^`M&7d0>qBWHvlRh^UR89F`7 zlBWOboIvZe?#9%Ozr&xAu#cz}&=1|~Xdml3M97?(HD)`m62ckj<+?0{S_8X7ucIhu zkq$N`7JKS=*0PA>gI3xt+`9HK4&Ku{_6=xh8APulk$PKK&4>szhX{DuwaIp5&G*c= z!P<8l9wTSTTC%W{fM=}kajzw~>fV=*rMP{b)Uqgf7C2ALBTB+6o^(d?ypvmfY2Q*z zy4>UjGilC~5kLyZ-MW~HR!NB00(M)fF&gF5ycCT>e4%jPDzPBo!vu9BWC2=^;O$i* zKjYJ)6ob4#C1Fg}G`q6I`2`^(sD?yFNW~G{mbiYFP zg90{BxyQ9WyK$vUc}yAjvD`OWL6mKhsKSDwJmlN# zE)5-*JNIn4U;NdXUr+vWQuYqZBU2@JP;mzfrY%R;hsST8{MpG3Z^`kB;=t)6Gf9+P z{qmk4ZiYX%|KXy1(73TC1)2L)uXYtV_kqGJU*6A6Mw(d8!PwxsC3kv$!mK zj>_~=*?3g6!!;d@ZK1J9AI z3D069%>qd>OWY%NI7~{yZlzYTRJ*f=dzCKeCACAZ8t|2p1ILvS_)C1cp5{9I^Apj~Rf`Eu8svYrKN{h#dvMb;W__#0&%xU<< z;{f1%GkprB_ znwAqmuS+H20w%lxU8xkliwTgaA^|I)dE2UsbpivNW0GI+MHey|2^@E9Nt*^-vg@p> zqkRpxJb}R|0M$C<9}SO9ME&7#C@gp|eE*k8Lnoy253CE-VyM{Adqaetk! z8Us_)(TPy#oaV1JFQ=K}4$>y0S?Z~Ar0N7u3O|KTa5^j=1_(QxAS%?G1mW7Iy5#ov z$##dmf~J7i2F-;2AZ+CC1Pn<3vP>OleYdGWx&19uwzU9$%G9p4v-l}fj5o-VI|vh`9_IL5a9)QE X0q0r7x#@Mvi1MSxQ78F@g8=w%44XLq literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cffi/__pycache__/_shimmed_dist_utils.cpython-311.pyc b/.venv/Lib/site-packages/cffi/__pycache__/_shimmed_dist_utils.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..73e4dea75a4ed1a56e470dfdbf397e73caa1e7d3 GIT binary patch literal 2189 zcmbVN&2Jk;6rcUD*Is|*vrS7;HMG#wg1FG~SwW;W{X%N1iUv@(mdx5aj)&~bnAx=* zM;t1|At!{y0saCI;=l=sYkT9it#YvTREbk>M&%Hd3vbqm5E#&ErdE4Zf;k&DK(VB4!b%*{_ewta1#WGGt zQ}NP%mf4P-$d;dDc_*L98Na}aPLWMG6UjR3PqHazDv@n}n$0*fY}T1&2b=@RUd}(r z=A1cp$T_4T$oTM1PF{XhSF%h)w1WQvJK`MC5PyBUzLU?bulQ_zN!=6A?mu1aZ9w%V zDowgQfX7}YtRzE>q{A=u_GK<6c`LGuNVvlrJw!UGV&F3nb3ZrCgt@r*J`#^a_Mh>NPzaemw7 zaFxAE`D!A9(*opN4VzG3Q~2I+*&(tf0vh(>RG0EIry)T8+RaZ!iLF=vH%d2r;zG+Q z4?@@Xler!Pt>xBNVIs@xx1JMVG+AZ5kGGLl;k}RR(u=WGt$Lzft;Po69^1P{3e!4i zCGhHGEzScF3g9Z`4H0KYuBE!=WExmJGukZI)kv$pNlR&tjA;aeIrYk;W=gntQCu9i zkVIycS9LkZ)4LkD0II5;GN%-iy9$USWFXbl%7S7=Wl-2PfXR{*N-?PvnHHP_I7cj= z+cjZ9r~ck3?P;+489fG$o_u=YY^5&Lol*H%G?uSGV}i;@gb`LFFe`Nehp$qG)846E zrL_tS3t8CiUQnqw8uV0E-DPl#R8_d7grMB&J;}U3JQ<7f6^Nt$IRt+I9~hdZ4fK>| z4v=Dbq~-3|>Th7?w3$H~r4B~sfguehQFdm--Wp7x%+vrG+6{f2_bq$Vn)~6M2iCF3 zI`*(Qw?PL89losph0w$m{qKas&UIaVhqAy^D03WaN3;dcz)+5rFg>O9w1?)&Xg}(k z3(;Qcn{P#Xsc*g=?MHpH6z!$Hc`f>H>YHby{pg`(fBogR-3Qju$U553yc_MMt*yQ_ zsc`LS<9shpeT7qWsCU1(zFAxcT+ZoB2|U2lC^x%Nie|-qyR~VzqRv`mt|b`dlv9OK z5v4MBmhLPCC!wVqW)XdpdeiuB?v(K>ynjEJI=6`KE~d`EYTPr9pFd&TJE7!%0pEzM ASpWb4 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cffi/__pycache__/api.cpython-311.pyc b/.venv/Lib/site-packages/cffi/__pycache__/api.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6a00ae1eb2113ac0c80ba318482509c425785410 GIT binary patch literal 55609 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cffi/__pycache__/backend_ctypes.cpython-311.pyc b/.venv/Lib/site-packages/cffi/__pycache__/backend_ctypes.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8ad2633770aeb609032b3d4070ea6c1ac425de40 GIT binary patch literal 71900 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

Px1oWf%W&)F(LL1_XxH^o*ME4NU`r~{j( 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cffi/__pycache__/cffi_opcode.cpython-311.pyc b/.venv/Lib/site-packages/cffi/__pycache__/cffi_opcode.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..228d8615a476f3268acc17606e21211a5246006d GIT binary patch literal 7119 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 dGlo9rPSgK_Pt*U-O;PAe$~Vzg6nc zs*yoediq0l-O|a2m>G1EOsZ^=}EE#i7eZN`m;mJtf$(8@V-@&JB`nA5YVA`SM21n*zSlL~->?$|6sZaew z$|$#KU{kZ$ph3gjbPrAL*6CbLBw0t4n|7t*8gj&9t@))b`k`~`(Iqx6h~=O1XJOh% z2#Fzc(LHadzT(7{^Md&Z^X(KWMywU0LE4G4lWic1@n>SK7!6U;Mlm{_PFqE#6l;1k sNc)r}N!c^8W<*0&QkDcIpB8Iet5a~BEntfj@LrvVhwL)qQ;G=t139g)<^TWy literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cffi/__pycache__/model.cpython-311.pyc b/.venv/Lib/site-packages/cffi/__pycache__/model.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1e55ce6f66c87c13b4cb0faf1f0c060f4cf82b24 GIT binary patch literal 33861 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 T2KsoyeGOo4g5H+`M)?095=?q< literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cffi/__pycache__/pkgconfig.cpython-311.pyc b/.venv/Lib/site-packages/cffi/__pycache__/pkgconfig.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..53b03fdde445ce3f57667bf08c1d507fd9d1e5c7 GIT binary patch literal 8125 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%0D%mI=7kk8o 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 Ifvl4MKcBnNr2qf` literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cffi/__pycache__/verifier.cpython-311.pyc b/.venv/Lib/site-packages/cffi/__pycache__/verifier.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5e670094561b216514267eb943b01be579db79dc GIT binary patch literal 18082 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 HY)StgxN#lV literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cffi/_cffi_errors.h b/.venv/Lib/site-packages/cffi/_cffi_errors.h new file mode 100644 index 00000000..158e0590 --- /dev/null +++ b/.venv/Lib/site-packages/cffi/_cffi_errors.h @@ -0,0 +1,149 @@ +#ifndef CFFI_MESSAGEBOX +# ifdef _MSC_VER +# define CFFI_MESSAGEBOX 1 +# else +# define CFFI_MESSAGEBOX 0 +# endif +#endif + + +#if CFFI_MESSAGEBOX +/* Windows only: logic to take the Python-CFFI embedding logic + initialization errors and display them in a background thread + with MessageBox. The idea is that if the whole program closes + as a result of this problem, then likely it is already a console + program and you can read the stderr output in the console too. + If it is not a console program, then it will likely show its own + dialog to complain, or generally not abruptly close, and for this + case the background thread should stay alive. +*/ +static void *volatile _cffi_bootstrap_text; + +static PyObject *_cffi_start_error_capture(void) +{ + PyObject *result = NULL; + PyObject *x, *m, *bi; + + if (InterlockedCompareExchangePointer(&_cffi_bootstrap_text, + (void *)1, NULL) != NULL) + return (PyObject *)1; + + m = PyImport_AddModule("_cffi_error_capture"); + if (m == NULL) + goto error; + + result = PyModule_GetDict(m); + if (result == NULL) + goto error; + +#if PY_MAJOR_VERSION >= 3 + bi = PyImport_ImportModule("builtins"); +#else + bi = PyImport_ImportModule("__builtin__"); +#endif + if (bi == NULL) + goto error; + PyDict_SetItemString(result, "__builtins__", bi); + Py_DECREF(bi); + + x = PyRun_String( + "import sys\n" + "class FileLike:\n" + " def write(self, x):\n" + " try:\n" + " of.write(x)\n" + " except: pass\n" + " self.buf += x\n" + " def flush(self):\n" + " pass\n" + "fl = FileLike()\n" + "fl.buf = ''\n" + "of = sys.stderr\n" + "sys.stderr = fl\n" + "def done():\n" + " sys.stderr = of\n" + " return fl.buf\n", /* make sure the returned value stays alive */ + Py_file_input, + result, result); + Py_XDECREF(x); + + error: + if (PyErr_Occurred()) + { + PyErr_WriteUnraisable(Py_None); + PyErr_Clear(); + } + return result; +} + +#pragma comment(lib, "user32.lib") + +static DWORD WINAPI _cffi_bootstrap_dialog(LPVOID ignored) +{ + Sleep(666); /* may be interrupted if the whole process is closing */ +#if PY_MAJOR_VERSION >= 3 + MessageBoxW(NULL, (wchar_t *)_cffi_bootstrap_text, + L"Python-CFFI error", + MB_OK | MB_ICONERROR); +#else + MessageBoxA(NULL, (char *)_cffi_bootstrap_text, + "Python-CFFI error", + MB_OK | MB_ICONERROR); +#endif + _cffi_bootstrap_text = NULL; + return 0; +} + +static void _cffi_stop_error_capture(PyObject *ecap) +{ + PyObject *s; + void *text; + + if (ecap == (PyObject *)1) + return; + + if (ecap == NULL) + goto error; + + s = PyRun_String("done()", Py_eval_input, ecap, ecap); + if (s == NULL) + goto error; + + /* Show a dialog box, but in a background thread, and + never show multiple dialog boxes at once. */ +#if PY_MAJOR_VERSION >= 3 + text = PyUnicode_AsWideCharString(s, NULL); +#else + text = PyString_AsString(s); +#endif + + _cffi_bootstrap_text = text; + + if (text != NULL) + { + HANDLE h; + h = CreateThread(NULL, 0, _cffi_bootstrap_dialog, + NULL, 0, NULL); + if (h != NULL) + CloseHandle(h); + } + /* decref the string, but it should stay alive as 'fl.buf' + in the small module above. It will really be freed only if + we later get another similar error. So it's a leak of at + most one copy of the small module. That's fine for this + situation which is usually a "fatal error" anyway. */ + Py_DECREF(s); + PyErr_Clear(); + return; + + error: + _cffi_bootstrap_text = NULL; + PyErr_Clear(); +} + +#else + +static PyObject *_cffi_start_error_capture(void) { return NULL; } +static void _cffi_stop_error_capture(PyObject *ecap) { } + +#endif diff --git a/.venv/Lib/site-packages/cffi/_cffi_include.h b/.venv/Lib/site-packages/cffi/_cffi_include.h new file mode 100644 index 00000000..e4c0a672 --- /dev/null +++ b/.venv/Lib/site-packages/cffi/_cffi_include.h @@ -0,0 +1,385 @@ +#define _CFFI_ + +/* We try to define Py_LIMITED_API before including Python.h. + + Mess: we can only define it if Py_DEBUG, Py_TRACE_REFS and + Py_REF_DEBUG are not defined. This is a best-effort approximation: + we can learn about Py_DEBUG from pyconfig.h, but it is unclear if + the same works for the other two macros. Py_DEBUG implies them, + but not the other way around. + + The implementation is messy (issue #350): on Windows, with _MSC_VER, + we have to define Py_LIMITED_API even before including pyconfig.h. + In that case, we guess what pyconfig.h will do to the macros above, + and check our guess after the #include. + + Note that on Windows, with CPython 3.x, you need >= 3.5 and virtualenv + version >= 16.0.0. With older versions of either, you don't get a + copy of PYTHON3.DLL in the virtualenv. We can't check the version of + CPython *before* we even include pyconfig.h. ffi.set_source() puts + a ``#define _CFFI_NO_LIMITED_API'' at the start of this file if it is + running on Windows < 3.5, as an attempt at fixing it, but that's + arguably wrong because it may not be the target version of Python. + Still better than nothing I guess. As another workaround, you can + remove the definition of Py_LIMITED_API here. + + See also 'py_limited_api' in cffi/setuptools_ext.py. +*/ +#if !defined(_CFFI_USE_EMBEDDING) && !defined(Py_LIMITED_API) +# ifdef _MSC_VER +# if !defined(_DEBUG) && !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) && !defined(_CFFI_NO_LIMITED_API) +# define Py_LIMITED_API +# endif +# include + /* sanity-check: Py_LIMITED_API will cause crashes if any of these + are also defined. Normally, the Python file PC/pyconfig.h does not + cause any of these to be defined, with the exception that _DEBUG + causes Py_DEBUG. Double-check that. */ +# ifdef Py_LIMITED_API +# if defined(Py_DEBUG) +# error "pyconfig.h unexpectedly defines Py_DEBUG, but Py_LIMITED_API is set" +# endif +# if defined(Py_TRACE_REFS) +# error "pyconfig.h unexpectedly defines Py_TRACE_REFS, but Py_LIMITED_API is set" +# endif +# if defined(Py_REF_DEBUG) +# error "pyconfig.h unexpectedly defines Py_REF_DEBUG, but Py_LIMITED_API is set" +# endif +# endif +# else +# include +# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) && !defined(_CFFI_NO_LIMITED_API) +# define Py_LIMITED_API +# endif +# endif +#endif + +#include +#ifdef __cplusplus +extern "C" { +#endif +#include +#include "parse_c_type.h" + +/* this block of #ifs should be kept exactly identical between + c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py + and cffi/_cffi_include.h */ +#if defined(_MSC_VER) +# include /* for alloca() */ +# if _MSC_VER < 1600 /* MSVC < 2010 */ + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + typedef __int8 int_least8_t; + typedef __int16 int_least16_t; + typedef __int32 int_least32_t; + typedef __int64 int_least64_t; + typedef unsigned __int8 uint_least8_t; + typedef unsigned __int16 uint_least16_t; + typedef unsigned __int32 uint_least32_t; + typedef unsigned __int64 uint_least64_t; + typedef __int8 int_fast8_t; + typedef __int16 int_fast16_t; + typedef __int32 int_fast32_t; + typedef __int64 int_fast64_t; + typedef unsigned __int8 uint_fast8_t; + typedef unsigned __int16 uint_fast16_t; + typedef unsigned __int32 uint_fast32_t; + typedef unsigned __int64 uint_fast64_t; + typedef __int64 intmax_t; + typedef unsigned __int64 uintmax_t; +# else +# include +# endif +# if _MSC_VER < 1800 /* MSVC < 2013 */ +# ifndef __cplusplus + typedef unsigned char _Bool; +# endif +# endif +#else +# include +# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) +# include +# endif +#endif + +#ifdef __GNUC__ +# define _CFFI_UNUSED_FN __attribute__((unused)) +#else +# define _CFFI_UNUSED_FN /* nothing */ +#endif + +#ifdef __cplusplus +# ifndef _Bool + typedef bool _Bool; /* semi-hackish: C++ has no _Bool; bool is builtin */ +# endif +#endif + +/********** CPython-specific section **********/ +#ifndef PYPY_VERSION + + +#if PY_MAJOR_VERSION >= 3 +# define PyInt_FromLong PyLong_FromLong +#endif + +#define _cffi_from_c_double PyFloat_FromDouble +#define _cffi_from_c_float PyFloat_FromDouble +#define _cffi_from_c_long PyInt_FromLong +#define _cffi_from_c_ulong PyLong_FromUnsignedLong +#define _cffi_from_c_longlong PyLong_FromLongLong +#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong +#define _cffi_from_c__Bool PyBool_FromLong + +#define _cffi_to_c_double PyFloat_AsDouble +#define _cffi_to_c_float PyFloat_AsDouble + +#define _cffi_from_c_int(x, type) \ + (((type)-1) > 0 ? /* unsigned */ \ + (sizeof(type) < sizeof(long) ? \ + PyInt_FromLong((long)x) : \ + sizeof(type) == sizeof(long) ? \ + PyLong_FromUnsignedLong((unsigned long)x) : \ + PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ + (sizeof(type) <= sizeof(long) ? \ + PyInt_FromLong((long)x) : \ + PyLong_FromLongLong((long long)x))) + +#define _cffi_to_c_int(o, type) \ + ((type)( \ + sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \ + : (type)_cffi_to_c_i8(o)) : \ + sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \ + : (type)_cffi_to_c_i16(o)) : \ + sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \ + : (type)_cffi_to_c_i32(o)) : \ + sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \ + : (type)_cffi_to_c_i64(o)) : \ + (Py_FatalError("unsupported size for type " #type), (type)0))) + +#define _cffi_to_c_i8 \ + ((int(*)(PyObject *))_cffi_exports[1]) +#define _cffi_to_c_u8 \ + ((int(*)(PyObject *))_cffi_exports[2]) +#define _cffi_to_c_i16 \ + ((int(*)(PyObject *))_cffi_exports[3]) +#define _cffi_to_c_u16 \ + ((int(*)(PyObject *))_cffi_exports[4]) +#define _cffi_to_c_i32 \ + ((int(*)(PyObject *))_cffi_exports[5]) +#define _cffi_to_c_u32 \ + ((unsigned int(*)(PyObject *))_cffi_exports[6]) +#define _cffi_to_c_i64 \ + ((long long(*)(PyObject *))_cffi_exports[7]) +#define _cffi_to_c_u64 \ + ((unsigned long long(*)(PyObject *))_cffi_exports[8]) +#define _cffi_to_c_char \ + ((int(*)(PyObject *))_cffi_exports[9]) +#define _cffi_from_c_pointer \ + ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[10]) +#define _cffi_to_c_pointer \ + ((char *(*)(PyObject *, struct _cffi_ctypedescr *))_cffi_exports[11]) +#define _cffi_get_struct_layout \ + not used any more +#define _cffi_restore_errno \ + ((void(*)(void))_cffi_exports[13]) +#define _cffi_save_errno \ + ((void(*)(void))_cffi_exports[14]) +#define _cffi_from_c_char \ + ((PyObject *(*)(char))_cffi_exports[15]) +#define _cffi_from_c_deref \ + ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[16]) +#define _cffi_to_c \ + ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[17]) +#define _cffi_from_c_struct \ + ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[18]) +#define _cffi_to_c_wchar_t \ + ((_cffi_wchar_t(*)(PyObject *))_cffi_exports[19]) +#define _cffi_from_c_wchar_t \ + ((PyObject *(*)(_cffi_wchar_t))_cffi_exports[20]) +#define _cffi_to_c_long_double \ + ((long double(*)(PyObject *))_cffi_exports[21]) +#define _cffi_to_c__Bool \ + ((_Bool(*)(PyObject *))_cffi_exports[22]) +#define _cffi_prepare_pointer_call_argument \ + ((Py_ssize_t(*)(struct _cffi_ctypedescr *, \ + PyObject *, char **))_cffi_exports[23]) +#define _cffi_convert_array_from_object \ + ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[24]) +#define _CFFI_CPIDX 25 +#define _cffi_call_python \ + ((void(*)(struct _cffi_externpy_s *, char *))_cffi_exports[_CFFI_CPIDX]) +#define _cffi_to_c_wchar3216_t \ + ((int(*)(PyObject *))_cffi_exports[26]) +#define _cffi_from_c_wchar3216_t \ + ((PyObject *(*)(int))_cffi_exports[27]) +#define _CFFI_NUM_EXPORTS 28 + +struct _cffi_ctypedescr; + +static void *_cffi_exports[_CFFI_NUM_EXPORTS]; + +#define _cffi_type(index) ( \ + assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \ + (struct _cffi_ctypedescr *)_cffi_types[index]) + +static PyObject *_cffi_init(const char *module_name, Py_ssize_t version, + const struct _cffi_type_context_s *ctx) +{ + PyObject *module, *o_arg, *new_module; + void *raw[] = { + (void *)module_name, + (void *)version, + (void *)_cffi_exports, + (void *)ctx, + }; + + module = PyImport_ImportModule("_cffi_backend"); + if (module == NULL) + goto failure; + + o_arg = PyLong_FromVoidPtr((void *)raw); + if (o_arg == NULL) + goto failure; + + new_module = PyObject_CallMethod( + module, (char *)"_init_cffi_1_0_external_module", (char *)"O", o_arg); + + Py_DECREF(o_arg); + Py_DECREF(module); + return new_module; + + failure: + Py_XDECREF(module); + return NULL; +} + + +#ifdef HAVE_WCHAR_H +typedef wchar_t _cffi_wchar_t; +#else +typedef uint16_t _cffi_wchar_t; /* same random pick as _cffi_backend.c */ +#endif + +_CFFI_UNUSED_FN static uint16_t _cffi_to_c_char16_t(PyObject *o) +{ + if (sizeof(_cffi_wchar_t) == 2) + return (uint16_t)_cffi_to_c_wchar_t(o); + else + return (uint16_t)_cffi_to_c_wchar3216_t(o); +} + +_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char16_t(uint16_t x) +{ + if (sizeof(_cffi_wchar_t) == 2) + return _cffi_from_c_wchar_t((_cffi_wchar_t)x); + else + return _cffi_from_c_wchar3216_t((int)x); +} + +_CFFI_UNUSED_FN static int _cffi_to_c_char32_t(PyObject *o) +{ + if (sizeof(_cffi_wchar_t) == 4) + return (int)_cffi_to_c_wchar_t(o); + else + return (int)_cffi_to_c_wchar3216_t(o); +} + +_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char32_t(unsigned int x) +{ + if (sizeof(_cffi_wchar_t) == 4) + return _cffi_from_c_wchar_t((_cffi_wchar_t)x); + else + return _cffi_from_c_wchar3216_t((int)x); +} + +union _cffi_union_alignment_u { + unsigned char m_char; + unsigned short m_short; + unsigned int m_int; + unsigned long m_long; + unsigned long long m_longlong; + float m_float; + double m_double; + long double m_longdouble; +}; + +struct _cffi_freeme_s { + struct _cffi_freeme_s *next; + union _cffi_union_alignment_u alignment; +}; + +_CFFI_UNUSED_FN static int +_cffi_convert_array_argument(struct _cffi_ctypedescr *ctptr, PyObject *arg, + char **output_data, Py_ssize_t datasize, + struct _cffi_freeme_s **freeme) +{ + char *p; + if (datasize < 0) + return -1; + + p = *output_data; + if (p == NULL) { + struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc( + offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize); + if (fp == NULL) + return -1; + fp->next = *freeme; + *freeme = fp; + p = *output_data = (char *)&fp->alignment; + } + memset((void *)p, 0, (size_t)datasize); + return _cffi_convert_array_from_object(p, ctptr, arg); +} + +_CFFI_UNUSED_FN static void +_cffi_free_array_arguments(struct _cffi_freeme_s *freeme) +{ + do { + void *p = (void *)freeme; + freeme = freeme->next; + PyObject_Free(p); + } while (freeme != NULL); +} + +/********** end CPython-specific section **********/ +#else +_CFFI_UNUSED_FN +static void (*_cffi_call_python_org)(struct _cffi_externpy_s *, char *); +# define _cffi_call_python _cffi_call_python_org +#endif + + +#define _cffi_array_len(array) (sizeof(array) / sizeof((array)[0])) + +#define _cffi_prim_int(size, sign) \ + ((size) == 1 ? ((sign) ? _CFFI_PRIM_INT8 : _CFFI_PRIM_UINT8) : \ + (size) == 2 ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) : \ + (size) == 4 ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) : \ + (size) == 8 ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) : \ + _CFFI__UNKNOWN_PRIM) + +#define _cffi_prim_float(size) \ + ((size) == sizeof(float) ? _CFFI_PRIM_FLOAT : \ + (size) == sizeof(double) ? _CFFI_PRIM_DOUBLE : \ + (size) == sizeof(long double) ? _CFFI__UNKNOWN_LONG_DOUBLE : \ + _CFFI__UNKNOWN_FLOAT_PRIM) + +#define _cffi_check_int(got, got_nonpos, expected) \ + ((got_nonpos) == (expected <= 0) && \ + (got) == (unsigned long long)expected) + +#ifdef MS_WIN32 +# define _cffi_stdcall __stdcall +#else +# define _cffi_stdcall /* nothing */ +#endif + +#ifdef __cplusplus +} +#endif diff --git a/.venv/Lib/site-packages/cffi/_embedding.h b/.venv/Lib/site-packages/cffi/_embedding.h new file mode 100644 index 00000000..1cb66f23 --- /dev/null +++ b/.venv/Lib/site-packages/cffi/_embedding.h @@ -0,0 +1,550 @@ + +/***** Support code for embedding *****/ + +#ifdef __cplusplus +extern "C" { +#endif + + +#if defined(_WIN32) +# define CFFI_DLLEXPORT __declspec(dllexport) +#elif defined(__GNUC__) +# define CFFI_DLLEXPORT __attribute__((visibility("default"))) +#else +# define CFFI_DLLEXPORT /* nothing */ +#endif + + +/* There are two global variables of type _cffi_call_python_fnptr: + + * _cffi_call_python, which we declare just below, is the one called + by ``extern "Python"`` implementations. + + * _cffi_call_python_org, which on CPython is actually part of the + _cffi_exports[] array, is the function pointer copied from + _cffi_backend. If _cffi_start_python() fails, then this is set + to NULL; otherwise, it should never be NULL. + + After initialization is complete, both are equal. However, the + first one remains equal to &_cffi_start_and_call_python until the + very end of initialization, when we are (or should be) sure that + concurrent threads also see a completely initialized world, and + only then is it changed. +*/ +#undef _cffi_call_python +typedef void (*_cffi_call_python_fnptr)(struct _cffi_externpy_s *, char *); +static void _cffi_start_and_call_python(struct _cffi_externpy_s *, char *); +static _cffi_call_python_fnptr _cffi_call_python = &_cffi_start_and_call_python; + + +#ifndef _MSC_VER + /* --- Assuming a GCC not infinitely old --- */ +# define cffi_compare_and_swap(l,o,n) __sync_bool_compare_and_swap(l,o,n) +# define cffi_write_barrier() __sync_synchronize() +# if !defined(__amd64__) && !defined(__x86_64__) && \ + !defined(__i386__) && !defined(__i386) +# define cffi_read_barrier() __sync_synchronize() +# else +# define cffi_read_barrier() (void)0 +# endif +#else + /* --- Windows threads version --- */ +# include +# define cffi_compare_and_swap(l,o,n) \ + (InterlockedCompareExchangePointer(l,n,o) == (o)) +# define cffi_write_barrier() InterlockedCompareExchange(&_cffi_dummy,0,0) +# define cffi_read_barrier() (void)0 +static volatile LONG _cffi_dummy; +#endif + +#ifdef WITH_THREAD +# ifndef _MSC_VER +# include + static pthread_mutex_t _cffi_embed_startup_lock; +# else + static CRITICAL_SECTION _cffi_embed_startup_lock; +# endif + static char _cffi_embed_startup_lock_ready = 0; +#endif + +static void _cffi_acquire_reentrant_mutex(void) +{ + static void *volatile lock = NULL; + + while (!cffi_compare_and_swap(&lock, NULL, (void *)1)) { + /* should ideally do a spin loop instruction here, but + hard to do it portably and doesn't really matter I + think: pthread_mutex_init() should be very fast, and + this is only run at start-up anyway. */ + } + +#ifdef WITH_THREAD + if (!_cffi_embed_startup_lock_ready) { +# ifndef _MSC_VER + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&_cffi_embed_startup_lock, &attr); +# else + InitializeCriticalSection(&_cffi_embed_startup_lock); +# endif + _cffi_embed_startup_lock_ready = 1; + } +#endif + + while (!cffi_compare_and_swap(&lock, (void *)1, NULL)) + ; + +#ifndef _MSC_VER + pthread_mutex_lock(&_cffi_embed_startup_lock); +#else + EnterCriticalSection(&_cffi_embed_startup_lock); +#endif +} + +static void _cffi_release_reentrant_mutex(void) +{ +#ifndef _MSC_VER + pthread_mutex_unlock(&_cffi_embed_startup_lock); +#else + LeaveCriticalSection(&_cffi_embed_startup_lock); +#endif +} + + +/********** CPython-specific section **********/ +#ifndef PYPY_VERSION + +#include "_cffi_errors.h" + + +#define _cffi_call_python_org _cffi_exports[_CFFI_CPIDX] + +PyMODINIT_FUNC _CFFI_PYTHON_STARTUP_FUNC(void); /* forward */ + +static void _cffi_py_initialize(void) +{ + /* XXX use initsigs=0, which "skips initialization registration of + signal handlers, which might be useful when Python is + embedded" according to the Python docs. But review and think + if it should be a user-controllable setting. + + XXX we should also give a way to write errors to a buffer + instead of to stderr. + + XXX if importing 'site' fails, CPython (any version) calls + exit(). Should we try to work around this behavior here? + */ + Py_InitializeEx(0); +} + +static int _cffi_initialize_python(void) +{ + /* This initializes Python, imports _cffi_backend, and then the + present .dll/.so is set up as a CPython C extension module. + */ + int result; + PyGILState_STATE state; + PyObject *pycode=NULL, *global_dict=NULL, *x; + PyObject *builtins; + + state = PyGILState_Ensure(); + + /* Call the initxxx() function from the present module. It will + create and initialize us as a CPython extension module, instead + of letting the startup Python code do it---it might reimport + the same .dll/.so and get maybe confused on some platforms. + It might also have troubles locating the .dll/.so again for all + I know. + */ + (void)_CFFI_PYTHON_STARTUP_FUNC(); + if (PyErr_Occurred()) + goto error; + + /* Now run the Python code provided to ffi.embedding_init_code(). + */ + pycode = Py_CompileString(_CFFI_PYTHON_STARTUP_CODE, + "", + Py_file_input); + if (pycode == NULL) + goto error; + global_dict = PyDict_New(); + if (global_dict == NULL) + goto error; + builtins = PyEval_GetBuiltins(); + if (builtins == NULL) + goto error; + if (PyDict_SetItemString(global_dict, "__builtins__", builtins) < 0) + goto error; + x = PyEval_EvalCode( +#if PY_MAJOR_VERSION < 3 + (PyCodeObject *) +#endif + pycode, global_dict, global_dict); + if (x == NULL) + goto error; + Py_DECREF(x); + + /* Done! Now if we've been called from + _cffi_start_and_call_python() in an ``extern "Python"``, we can + only hope that the Python code did correctly set up the + corresponding @ffi.def_extern() function. Otherwise, the + general logic of ``extern "Python"`` functions (inside the + _cffi_backend module) will find that the reference is still + missing and print an error. + */ + result = 0; + done: + Py_XDECREF(pycode); + Py_XDECREF(global_dict); + PyGILState_Release(state); + return result; + + error:; + { + /* Print as much information as potentially useful. + Debugging load-time failures with embedding is not fun + */ + PyObject *ecap; + PyObject *exception, *v, *tb, *f, *modules, *mod; + PyErr_Fetch(&exception, &v, &tb); + ecap = _cffi_start_error_capture(); + f = PySys_GetObject((char *)"stderr"); + if (f != NULL && f != Py_None) { + PyFile_WriteString( + "Failed to initialize the Python-CFFI embedding logic:\n\n", f); + } + + if (exception != NULL) { + PyErr_NormalizeException(&exception, &v, &tb); + PyErr_Display(exception, v, tb); + } + Py_XDECREF(exception); + Py_XDECREF(v); + Py_XDECREF(tb); + + if (f != NULL && f != Py_None) { + PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME + "\ncompiled with cffi version: 1.16.0" + "\n_cffi_backend module: ", f); + modules = PyImport_GetModuleDict(); + mod = PyDict_GetItemString(modules, "_cffi_backend"); + if (mod == NULL) { + PyFile_WriteString("not loaded", f); + } + else { + v = PyObject_GetAttrString(mod, "__file__"); + PyFile_WriteObject(v, f, 0); + Py_XDECREF(v); + } + PyFile_WriteString("\nsys.path: ", f); + PyFile_WriteObject(PySys_GetObject((char *)"path"), f, 0); + PyFile_WriteString("\n\n", f); + } + _cffi_stop_error_capture(ecap); + } + result = -1; + goto done; +} + +#if PY_VERSION_HEX < 0x03080000 +PyAPI_DATA(char *) _PyParser_TokenNames[]; /* from CPython */ +#endif + +static int _cffi_carefully_make_gil(void) +{ + /* This does the basic initialization of Python. It can be called + completely concurrently from unrelated threads. It assumes + that we don't hold the GIL before (if it exists), and we don't + hold it afterwards. + + (What it really does used to be completely different in Python 2 + and Python 3, with the Python 2 solution avoiding the spin-lock + around the Py_InitializeEx() call. However, after recent changes + to CPython 2.7 (issue #358) it no longer works. So we use the + Python 3 solution everywhere.) + + This initializes Python by calling Py_InitializeEx(). + Important: this must not be called concurrently at all. + So we use a global variable as a simple spin lock. This global + variable must be from 'libpythonX.Y.so', not from this + cffi-based extension module, because it must be shared from + different cffi-based extension modules. + + In Python < 3.8, we choose + _PyParser_TokenNames[0] as a completely arbitrary pointer value + that is never written to. The default is to point to the + string "ENDMARKER". We change it temporarily to point to the + next character in that string. (Yes, I know it's REALLY + obscure.) + + In Python >= 3.8, this string array is no longer writable, so + instead we pick PyCapsuleType.tp_version_tag. We can't change + Python < 3.8 because someone might use a mixture of cffi + embedded modules, some of which were compiled before this file + changed. + + In Python >= 3.12, this stopped working because that particular + tp_version_tag gets modified during interpreter startup. It's + arguably a bad idea before 3.12 too, but again we can't change + that because someone might use a mixture of cffi embedded + modules, and no-one reported a bug so far. In Python >= 3.12 + we go instead for PyCapsuleType.tp_as_buffer, which is supposed + to always be NULL. We write to it temporarily a pointer to + a struct full of NULLs, which is semantically the same. + */ + +#ifdef WITH_THREAD +# if PY_VERSION_HEX < 0x03080000 + char *volatile *lock = (char *volatile *)_PyParser_TokenNames; + char *old_value, *locked_value; + + while (1) { /* spin loop */ + old_value = *lock; + locked_value = old_value + 1; + if (old_value[0] == 'E') { + assert(old_value[1] == 'N'); + if (cffi_compare_and_swap(lock, old_value, locked_value)) + break; + } + else { + assert(old_value[0] == 'N'); + /* should ideally do a spin loop instruction here, but + hard to do it portably and doesn't really matter I + think: PyEval_InitThreads() should be very fast, and + this is only run at start-up anyway. */ + } + } +# else +# if PY_VERSION_HEX < 0x030C0000 + int volatile *lock = (int volatile *)&PyCapsule_Type.tp_version_tag; + int old_value, locked_value = -42; + assert(!(PyCapsule_Type.tp_flags & Py_TPFLAGS_HAVE_VERSION_TAG)); +# else + static struct ebp_s { PyBufferProcs buf; int mark; } empty_buffer_procs; + empty_buffer_procs.mark = -42; + PyBufferProcs *volatile *lock = (PyBufferProcs *volatile *) + &PyCapsule_Type.tp_as_buffer; + PyBufferProcs *old_value, *locked_value = &empty_buffer_procs.buf; +# endif + + while (1) { /* spin loop */ + old_value = *lock; + if (old_value == 0) { + if (cffi_compare_and_swap(lock, old_value, locked_value)) + break; + } + else { +# if PY_VERSION_HEX < 0x030C0000 + assert(old_value == locked_value); +# else + /* The pointer should point to a possibly different + empty_buffer_procs from another C extension module */ + assert(((struct ebp_s *)old_value)->mark == -42); +# endif + /* should ideally do a spin loop instruction here, but + hard to do it portably and doesn't really matter I + think: PyEval_InitThreads() should be very fast, and + this is only run at start-up anyway. */ + } + } +# endif +#endif + + /* call Py_InitializeEx() */ + if (!Py_IsInitialized()) { + _cffi_py_initialize(); +#if PY_VERSION_HEX < 0x03070000 + PyEval_InitThreads(); +#endif + PyEval_SaveThread(); /* release the GIL */ + /* the returned tstate must be the one that has been stored into the + autoTLSkey by _PyGILState_Init() called from Py_Initialize(). */ + } + else { +#if PY_VERSION_HEX < 0x03070000 + /* PyEval_InitThreads() is always a no-op from CPython 3.7 */ + PyGILState_STATE state = PyGILState_Ensure(); + PyEval_InitThreads(); + PyGILState_Release(state); +#endif + } + +#ifdef WITH_THREAD + /* release the lock */ + while (!cffi_compare_and_swap(lock, locked_value, old_value)) + ; +#endif + + return 0; +} + +/********** end CPython-specific section **********/ + + +#else + + +/********** PyPy-specific section **********/ + +PyMODINIT_FUNC _CFFI_PYTHON_STARTUP_FUNC(const void *[]); /* forward */ + +static struct _cffi_pypy_init_s { + const char *name; + void *func; /* function pointer */ + const char *code; +} _cffi_pypy_init = { + _CFFI_MODULE_NAME, + _CFFI_PYTHON_STARTUP_FUNC, + _CFFI_PYTHON_STARTUP_CODE, +}; + +extern int pypy_carefully_make_gil(const char *); +extern int pypy_init_embedded_cffi_module(int, struct _cffi_pypy_init_s *); + +static int _cffi_carefully_make_gil(void) +{ + return pypy_carefully_make_gil(_CFFI_MODULE_NAME); +} + +static int _cffi_initialize_python(void) +{ + return pypy_init_embedded_cffi_module(0xB011, &_cffi_pypy_init); +} + +/********** end PyPy-specific section **********/ + + +#endif + + +#ifdef __GNUC__ +__attribute__((noinline)) +#endif +static _cffi_call_python_fnptr _cffi_start_python(void) +{ + /* Delicate logic to initialize Python. This function can be + called multiple times concurrently, e.g. when the process calls + its first ``extern "Python"`` functions in multiple threads at + once. It can also be called recursively, in which case we must + ignore it. We also have to consider what occurs if several + different cffi-based extensions reach this code in parallel + threads---it is a different copy of the code, then, and we + can't have any shared global variable unless it comes from + 'libpythonX.Y.so'. + + Idea: + + * _cffi_carefully_make_gil(): "carefully" call + PyEval_InitThreads() (possibly with Py_InitializeEx() first). + + * then we use a (local) custom lock to make sure that a call to this + cffi-based extension will wait if another call to the *same* + extension is running the initialization in another thread. + It is reentrant, so that a recursive call will not block, but + only one from a different thread. + + * then we grab the GIL and (Python 2) we call Py_InitializeEx(). + At this point, concurrent calls to Py_InitializeEx() are not + possible: we have the GIL. + + * do the rest of the specific initialization, which may + temporarily release the GIL but not the custom lock. + Only release the custom lock when we are done. + */ + static char called = 0; + + if (_cffi_carefully_make_gil() != 0) + return NULL; + + _cffi_acquire_reentrant_mutex(); + + /* Here the GIL exists, but we don't have it. We're only protected + from concurrency by the reentrant mutex. */ + + /* This file only initializes the embedded module once, the first + time this is called, even if there are subinterpreters. */ + if (!called) { + called = 1; /* invoke _cffi_initialize_python() only once, + but don't set '_cffi_call_python' right now, + otherwise concurrent threads won't call + this function at all (we need them to wait) */ + if (_cffi_initialize_python() == 0) { + /* now initialization is finished. Switch to the fast-path. */ + + /* We would like nobody to see the new value of + '_cffi_call_python' without also seeing the rest of the + data initialized. However, this is not possible. But + the new value of '_cffi_call_python' is the function + 'cffi_call_python()' from _cffi_backend. So: */ + cffi_write_barrier(); + /* ^^^ we put a write barrier here, and a corresponding + read barrier at the start of cffi_call_python(). This + ensures that after that read barrier, we see everything + done here before the write barrier. + */ + + assert(_cffi_call_python_org != NULL); + _cffi_call_python = (_cffi_call_python_fnptr)_cffi_call_python_org; + } + else { + /* initialization failed. Reset this to NULL, even if it was + already set to some other value. Future calls to + _cffi_start_python() are still forced to occur, and will + always return NULL from now on. */ + _cffi_call_python_org = NULL; + } + } + + _cffi_release_reentrant_mutex(); + + return (_cffi_call_python_fnptr)_cffi_call_python_org; +} + +static +void _cffi_start_and_call_python(struct _cffi_externpy_s *externpy, char *args) +{ + _cffi_call_python_fnptr fnptr; + int current_err = errno; +#ifdef _MSC_VER + int current_lasterr = GetLastError(); +#endif + fnptr = _cffi_start_python(); + if (fnptr == NULL) { + fprintf(stderr, "function %s() called, but initialization code " + "failed. Returning 0.\n", externpy->name); + memset(args, 0, externpy->size_of_result); + } +#ifdef _MSC_VER + SetLastError(current_lasterr); +#endif + errno = current_err; + + if (fnptr != NULL) + fnptr(externpy, args); +} + + +/* The cffi_start_python() function makes sure Python is initialized + and our cffi module is set up. It can be called manually from the + user C code. The same effect is obtained automatically from any + dll-exported ``extern "Python"`` function. This function returns + -1 if initialization failed, 0 if all is OK. */ +_CFFI_UNUSED_FN +static int cffi_start_python(void) +{ + if (_cffi_call_python == &_cffi_start_and_call_python) { + if (_cffi_start_python() == NULL) + return -1; + } + cffi_read_barrier(); + return 0; +} + +#undef cffi_compare_and_swap +#undef cffi_write_barrier +#undef cffi_read_barrier + +#ifdef __cplusplus +} +#endif diff --git a/.venv/Lib/site-packages/cffi/_imp_emulation.py b/.venv/Lib/site-packages/cffi/_imp_emulation.py new file mode 100644 index 00000000..136abddd --- /dev/null +++ b/.venv/Lib/site-packages/cffi/_imp_emulation.py @@ -0,0 +1,83 @@ + +try: + # this works on Python < 3.12 + from imp import * + +except ImportError: + # this is a limited emulation for Python >= 3.12. + # Note that this is used only for tests or for the old ffi.verify(). + # This is copied from the source code of Python 3.11. + + from _imp import (acquire_lock, release_lock, + is_builtin, is_frozen) + + from importlib._bootstrap import _load + + from importlib import machinery + import os + import sys + import tokenize + + SEARCH_ERROR = 0 + PY_SOURCE = 1 + PY_COMPILED = 2 + C_EXTENSION = 3 + PY_RESOURCE = 4 + PKG_DIRECTORY = 5 + C_BUILTIN = 6 + PY_FROZEN = 7 + PY_CODERESOURCE = 8 + IMP_HOOK = 9 + + def get_suffixes(): + extensions = [(s, 'rb', C_EXTENSION) + for s in machinery.EXTENSION_SUFFIXES] + source = [(s, 'r', PY_SOURCE) for s in machinery.SOURCE_SUFFIXES] + bytecode = [(s, 'rb', PY_COMPILED) for s in machinery.BYTECODE_SUFFIXES] + return extensions + source + bytecode + + def find_module(name, path=None): + if not isinstance(name, str): + raise TypeError("'name' must be a str, not {}".format(type(name))) + elif not isinstance(path, (type(None), list)): + # Backwards-compatibility + raise RuntimeError("'path' must be None or a list, " + "not {}".format(type(path))) + + if path is None: + if is_builtin(name): + return None, None, ('', '', C_BUILTIN) + elif is_frozen(name): + return None, None, ('', '', PY_FROZEN) + else: + path = sys.path + + for entry in path: + package_directory = os.path.join(entry, name) + for suffix in ['.py', machinery.BYTECODE_SUFFIXES[0]]: + package_file_name = '__init__' + suffix + file_path = os.path.join(package_directory, package_file_name) + if os.path.isfile(file_path): + return None, package_directory, ('', '', PKG_DIRECTORY) + for suffix, mode, type_ in get_suffixes(): + file_name = name + suffix + file_path = os.path.join(entry, file_name) + if os.path.isfile(file_path): + break + else: + continue + break # Break out of outer loop when breaking out of inner loop. + else: + raise ImportError(name, name=name) + + encoding = None + if 'b' not in mode: + with open(file_path, 'rb') as file: + encoding = tokenize.detect_encoding(file.readline)[0] + file = open(file_path, mode, encoding=encoding) + return file, file_path, (suffix, mode, type_) + + def load_dynamic(name, path, file=None): + loader = machinery.ExtensionFileLoader(name, path) + spec = machinery.ModuleSpec(name=name, loader=loader, origin=path) + return _load(spec) diff --git a/.venv/Lib/site-packages/cffi/_shimmed_dist_utils.py b/.venv/Lib/site-packages/cffi/_shimmed_dist_utils.py new file mode 100644 index 00000000..611bf40f --- /dev/null +++ b/.venv/Lib/site-packages/cffi/_shimmed_dist_utils.py @@ -0,0 +1,41 @@ +""" +Temporary shim module to indirect the bits of distutils we need from setuptools/distutils while providing useful +error messages beyond `No module named 'distutils' on Python >= 3.12, or when setuptools' vendored distutils is broken. + +This is a compromise to avoid a hard-dep on setuptools for Python >= 3.12, since many users don't need runtime compilation support from CFFI. +""" +import sys + +try: + # import setuptools first; this is the most robust way to ensure its embedded distutils is available + # (the .pth shim should usually work, but this is even more robust) + import setuptools +except Exception as ex: + if sys.version_info >= (3, 12): + # Python 3.12 has no built-in distutils to fall back on, so any import problem is fatal + raise Exception("This CFFI feature requires setuptools on Python >= 3.12. The setuptools module is missing or non-functional.") from ex + + # silently ignore on older Pythons (support fallback to stdlib distutils where available) +else: + del setuptools + +try: + # bring in just the bits of distutils we need, whether they really came from setuptools or stdlib-embedded distutils + from distutils import log, sysconfig + from distutils.ccompiler import CCompiler + from distutils.command.build_ext import build_ext + from distutils.core import Distribution, Extension + from distutils.dir_util import mkpath + from distutils.errors import DistutilsSetupError, CompileError, LinkError + from distutils.log import set_threshold, set_verbosity + + if sys.platform == 'win32': + from distutils.msvc9compiler import MSVCCompiler +except Exception as ex: + if sys.version_info >= (3, 12): + raise Exception("This CFFI feature requires setuptools on Python >= 3.12. Please install the setuptools package.") from ex + + # anything older, just let the underlying distutils import error fly + raise Exception("This CFFI feature requires distutils. Please install the distutils or setuptools package.") from ex + +del sys diff --git a/.venv/Lib/site-packages/cffi/api.py b/.venv/Lib/site-packages/cffi/api.py new file mode 100644 index 00000000..edeb7928 --- /dev/null +++ b/.venv/Lib/site-packages/cffi/api.py @@ -0,0 +1,965 @@ +import sys, types +from .lock import allocate_lock +from .error import CDefError +from . import model + +try: + callable +except NameError: + # Python 3.1 + from collections import Callable + callable = lambda x: isinstance(x, Callable) + +try: + basestring +except NameError: + # Python 3.x + basestring = str + +_unspecified = object() + + + +class FFI(object): + r''' + The main top-level class that you instantiate once, or once per module. + + Example usage: + + ffi = FFI() + ffi.cdef(""" + int printf(const char *, ...); + """) + + C = ffi.dlopen(None) # standard library + -or- + C = ffi.verify() # use a C compiler: verify the decl above is right + + C.printf("hello, %s!\n", ffi.new("char[]", "world")) + ''' + + def __init__(self, backend=None): + """Create an FFI instance. The 'backend' argument is used to + select a non-default backend, mostly for tests. + """ + if backend is None: + # You need PyPy (>= 2.0 beta), or a CPython (>= 2.6) with + # _cffi_backend.so compiled. + import _cffi_backend as backend + from . import __version__ + if backend.__version__ != __version__: + # bad version! Try to be as explicit as possible. + if hasattr(backend, '__file__'): + # CPython + raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r. When we import the top-level '_cffi_backend' extension module, we get version %s, located in %r. The two versions should be equal; check your installation." % ( + __version__, __file__, + backend.__version__, backend.__file__)) + else: + # PyPy + raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r. This interpreter comes with a built-in '_cffi_backend' module, which is version %s. The two versions should be equal; check your installation." % ( + __version__, __file__, backend.__version__)) + # (If you insist you can also try to pass the option + # 'backend=backend_ctypes.CTypesBackend()', but don't + # rely on it! It's probably not going to work well.) + + from . import cparser + self._backend = backend + self._lock = allocate_lock() + self._parser = cparser.Parser() + self._cached_btypes = {} + self._parsed_types = types.ModuleType('parsed_types').__dict__ + self._new_types = types.ModuleType('new_types').__dict__ + self._function_caches = [] + self._libraries = [] + self._cdefsources = [] + self._included_ffis = [] + self._windows_unicode = None + self._init_once_cache = {} + self._cdef_version = None + self._embedding = None + self._typecache = model.get_typecache(backend) + if hasattr(backend, 'set_ffi'): + backend.set_ffi(self) + for name in list(backend.__dict__): + if name.startswith('RTLD_'): + setattr(self, name, getattr(backend, name)) + # + with self._lock: + self.BVoidP = self._get_cached_btype(model.voidp_type) + self.BCharA = self._get_cached_btype(model.char_array_type) + if isinstance(backend, types.ModuleType): + # _cffi_backend: attach these constants to the class + if not hasattr(FFI, 'NULL'): + FFI.NULL = self.cast(self.BVoidP, 0) + FFI.CData, FFI.CType = backend._get_types() + else: + # ctypes backend: attach these constants to the instance + self.NULL = self.cast(self.BVoidP, 0) + self.CData, self.CType = backend._get_types() + self.buffer = backend.buffer + + def cdef(self, csource, override=False, packed=False, pack=None): + """Parse the given C source. This registers all declared functions, + types, and global variables. The functions and global variables can + then be accessed via either 'ffi.dlopen()' or 'ffi.verify()'. + The types can be used in 'ffi.new()' and other functions. + If 'packed' is specified as True, all structs declared inside this + cdef are packed, i.e. laid out without any field alignment at all. + Alternatively, 'pack' can be a small integer, and requests for + alignment greater than that are ignored (pack=1 is equivalent to + packed=True). + """ + self._cdef(csource, override=override, packed=packed, pack=pack) + + def embedding_api(self, csource, packed=False, pack=None): + self._cdef(csource, packed=packed, pack=pack, dllexport=True) + if self._embedding is None: + self._embedding = '' + + def _cdef(self, csource, override=False, **options): + if not isinstance(csource, str): # unicode, on Python 2 + if not isinstance(csource, basestring): + raise TypeError("cdef() argument must be a string") + csource = csource.encode('ascii') + with self._lock: + self._cdef_version = object() + self._parser.parse(csource, override=override, **options) + self._cdefsources.append(csource) + if override: + for cache in self._function_caches: + cache.clear() + finishlist = self._parser._recomplete + if finishlist: + self._parser._recomplete = [] + for tp in finishlist: + tp.finish_backend_type(self, finishlist) + + def dlopen(self, name, flags=0): + """Load and return a dynamic library identified by 'name'. + The standard C library can be loaded by passing None. + Note that functions and types declared by 'ffi.cdef()' are not + linked to a particular library, just like C headers; in the + library we only look for the actual (untyped) symbols. + """ + if not (isinstance(name, basestring) or + name is None or + isinstance(name, self.CData)): + raise TypeError("dlopen(name): name must be a file name, None, " + "or an already-opened 'void *' handle") + with self._lock: + lib, function_cache = _make_ffi_library(self, name, flags) + self._function_caches.append(function_cache) + self._libraries.append(lib) + return lib + + def dlclose(self, lib): + """Close a library obtained with ffi.dlopen(). After this call, + access to functions or variables from the library will fail + (possibly with a segmentation fault). + """ + type(lib).__cffi_close__(lib) + + def _typeof_locked(self, cdecl): + # call me with the lock! + key = cdecl + if key in self._parsed_types: + return self._parsed_types[key] + # + if not isinstance(cdecl, str): # unicode, on Python 2 + cdecl = cdecl.encode('ascii') + # + type = self._parser.parse_type(cdecl) + really_a_function_type = type.is_raw_function + if really_a_function_type: + type = type.as_function_pointer() + btype = self._get_cached_btype(type) + result = btype, really_a_function_type + self._parsed_types[key] = result + return result + + def _typeof(self, cdecl, consider_function_as_funcptr=False): + # string -> ctype object + try: + result = self._parsed_types[cdecl] + except KeyError: + with self._lock: + result = self._typeof_locked(cdecl) + # + btype, really_a_function_type = result + if really_a_function_type and not consider_function_as_funcptr: + raise CDefError("the type %r is a function type, not a " + "pointer-to-function type" % (cdecl,)) + return btype + + def typeof(self, cdecl): + """Parse the C type given as a string and return the + corresponding object. + It can also be used on 'cdata' instance to get its C type. + """ + if isinstance(cdecl, basestring): + return self._typeof(cdecl) + if isinstance(cdecl, self.CData): + return self._backend.typeof(cdecl) + if isinstance(cdecl, types.BuiltinFunctionType): + res = _builtin_function_type(cdecl) + if res is not None: + return res + if (isinstance(cdecl, types.FunctionType) + and hasattr(cdecl, '_cffi_base_type')): + with self._lock: + return self._get_cached_btype(cdecl._cffi_base_type) + raise TypeError(type(cdecl)) + + def sizeof(self, cdecl): + """Return the size in bytes of the argument. It can be a + string naming a C type, or a 'cdata' instance. + """ + if isinstance(cdecl, basestring): + BType = self._typeof(cdecl) + return self._backend.sizeof(BType) + else: + return self._backend.sizeof(cdecl) + + def alignof(self, cdecl): + """Return the natural alignment size in bytes of the C type + given as a string. + """ + if isinstance(cdecl, basestring): + cdecl = self._typeof(cdecl) + return self._backend.alignof(cdecl) + + def offsetof(self, cdecl, *fields_or_indexes): + """Return the offset of the named field inside the given + structure or array, which must be given as a C type name. + You can give several field names in case of nested structures. + You can also give numeric values which correspond to array + items, in case of an array type. + """ + if isinstance(cdecl, basestring): + cdecl = self._typeof(cdecl) + return self._typeoffsetof(cdecl, *fields_or_indexes)[1] + + def new(self, cdecl, init=None): + """Allocate an instance according to the specified C type and + return a pointer to it. The specified C type must be either a + pointer or an array: ``new('X *')`` allocates an X and returns + a pointer to it, whereas ``new('X[n]')`` allocates an array of + n X'es and returns an array referencing it (which works + mostly like a pointer, like in C). You can also use + ``new('X[]', n)`` to allocate an array of a non-constant + length n. + + The memory is initialized following the rules of declaring a + global variable in C: by default it is zero-initialized, but + an explicit initializer can be given which can be used to + fill all or part of the memory. + + When the returned object goes out of scope, the memory + is freed. In other words the returned object has + ownership of the value of type 'cdecl' that it points to. This + means that the raw data can be used as long as this object is + kept alive, but must not be used for a longer time. Be careful + about that when copying the pointer to the memory somewhere + else, e.g. into another structure. + """ + if isinstance(cdecl, basestring): + cdecl = self._typeof(cdecl) + return self._backend.newp(cdecl, init) + + def new_allocator(self, alloc=None, free=None, + should_clear_after_alloc=True): + """Return a new allocator, i.e. a function that behaves like ffi.new() + but uses the provided low-level 'alloc' and 'free' functions. + + 'alloc' is called with the size as argument. If it returns NULL, a + MemoryError is raised. 'free' is called with the result of 'alloc' + as argument. Both can be either Python function or directly C + functions. If 'free' is None, then no free function is called. + If both 'alloc' and 'free' are None, the default is used. + + If 'should_clear_after_alloc' is set to False, then the memory + returned by 'alloc' is assumed to be already cleared (or you are + fine with garbage); otherwise CFFI will clear it. + """ + compiled_ffi = self._backend.FFI() + allocator = compiled_ffi.new_allocator(alloc, free, + should_clear_after_alloc) + def allocate(cdecl, init=None): + if isinstance(cdecl, basestring): + cdecl = self._typeof(cdecl) + return allocator(cdecl, init) + return allocate + + def cast(self, cdecl, source): + """Similar to a C cast: returns an instance of the named C + type initialized with the given 'source'. The source is + casted between integers or pointers of any type. + """ + if isinstance(cdecl, basestring): + cdecl = self._typeof(cdecl) + return self._backend.cast(cdecl, source) + + def string(self, cdata, maxlen=-1): + """Return a Python string (or unicode string) from the 'cdata'. + If 'cdata' is a pointer or array of characters or bytes, returns + the null-terminated string. The returned string extends until + the first null character, or at most 'maxlen' characters. If + 'cdata' is an array then 'maxlen' defaults to its length. + + If 'cdata' is a pointer or array of wchar_t, returns a unicode + string following the same rules. + + If 'cdata' is a single character or byte or a wchar_t, returns + it as a string or unicode string. + + If 'cdata' is an enum, returns the value of the enumerator as a + string, or 'NUMBER' if the value is out of range. + """ + return self._backend.string(cdata, maxlen) + + def unpack(self, cdata, length): + """Unpack an array of C data of the given length, + returning a Python string/unicode/list. + + If 'cdata' is a pointer to 'char', returns a byte string. + It does not stop at the first null. This is equivalent to: + ffi.buffer(cdata, length)[:] + + If 'cdata' is a pointer to 'wchar_t', returns a unicode string. + 'length' is measured in wchar_t's; it is not the size in bytes. + + If 'cdata' is a pointer to anything else, returns a list of + 'length' items. This is a faster equivalent to: + [cdata[i] for i in range(length)] + """ + return self._backend.unpack(cdata, length) + + #def buffer(self, cdata, size=-1): + # """Return a read-write buffer object that references the raw C data + # pointed to by the given 'cdata'. The 'cdata' must be a pointer or + # an array. Can be passed to functions expecting a buffer, or directly + # manipulated with: + # + # buf[:] get a copy of it in a regular string, or + # buf[idx] as a single character + # buf[:] = ... + # buf[idx] = ... change the content + # """ + # note that 'buffer' is a type, set on this instance by __init__ + + def from_buffer(self, cdecl, python_buffer=_unspecified, + require_writable=False): + """Return a cdata of the given type pointing to the data of the + given Python object, which must support the buffer interface. + Note that this is not meant to be used on the built-in types + str or unicode (you can build 'char[]' arrays explicitly) + but only on objects containing large quantities of raw data + in some other format, like 'array.array' or numpy arrays. + + The first argument is optional and default to 'char[]'. + """ + if python_buffer is _unspecified: + cdecl, python_buffer = self.BCharA, cdecl + elif isinstance(cdecl, basestring): + cdecl = self._typeof(cdecl) + return self._backend.from_buffer(cdecl, python_buffer, + require_writable) + + def memmove(self, dest, src, n): + """ffi.memmove(dest, src, n) copies n bytes of memory from src to dest. + + Like the C function memmove(), the memory areas may overlap; + apart from that it behaves like the C function memcpy(). + + 'src' can be any cdata ptr or array, or any Python buffer object. + 'dest' can be any cdata ptr or array, or a writable Python buffer + object. The size to copy, 'n', is always measured in bytes. + + Unlike other methods, this one supports all Python buffer including + byte strings and bytearrays---but it still does not support + non-contiguous buffers. + """ + return self._backend.memmove(dest, src, n) + + def callback(self, cdecl, python_callable=None, error=None, onerror=None): + """Return a callback object or a decorator making such a + callback object. 'cdecl' must name a C function pointer type. + The callback invokes the specified 'python_callable' (which may + be provided either directly or via a decorator). Important: the + callback object must be manually kept alive for as long as the + callback may be invoked from the C level. + """ + def callback_decorator_wrap(python_callable): + if not callable(python_callable): + raise TypeError("the 'python_callable' argument " + "is not callable") + return self._backend.callback(cdecl, python_callable, + error, onerror) + if isinstance(cdecl, basestring): + cdecl = self._typeof(cdecl, consider_function_as_funcptr=True) + if python_callable is None: + return callback_decorator_wrap # decorator mode + else: + return callback_decorator_wrap(python_callable) # direct mode + + def getctype(self, cdecl, replace_with=''): + """Return a string giving the C type 'cdecl', which may be itself + a string or a object. If 'replace_with' is given, it gives + extra text to append (or insert for more complicated C types), like + a variable name, or '*' to get actually the C type 'pointer-to-cdecl'. + """ + if isinstance(cdecl, basestring): + cdecl = self._typeof(cdecl) + replace_with = replace_with.strip() + if (replace_with.startswith('*') + and '&[' in self._backend.getcname(cdecl, '&')): + replace_with = '(%s)' % replace_with + elif replace_with and not replace_with[0] in '[(': + replace_with = ' ' + replace_with + return self._backend.getcname(cdecl, replace_with) + + def gc(self, cdata, destructor, size=0): + """Return a new cdata object that points to the same + data. Later, when this new cdata object is garbage-collected, + 'destructor(old_cdata_object)' will be called. + + The optional 'size' gives an estimate of the size, used to + trigger the garbage collection more eagerly. So far only used + on PyPy. It tells the GC that the returned object keeps alive + roughly 'size' bytes of external memory. + """ + return self._backend.gcp(cdata, destructor, size) + + def _get_cached_btype(self, type): + assert self._lock.acquire(False) is False + # call me with the lock! + try: + BType = self._cached_btypes[type] + except KeyError: + finishlist = [] + BType = type.get_cached_btype(self, finishlist) + for type in finishlist: + type.finish_backend_type(self, finishlist) + return BType + + def verify(self, source='', tmpdir=None, **kwargs): + """Verify that the current ffi signatures compile on this + machine, and return a dynamic library object. The dynamic + library can be used to call functions and access global + variables declared in this 'ffi'. The library is compiled + by the C compiler: it gives you C-level API compatibility + (including calling macros). This is unlike 'ffi.dlopen()', + which requires binary compatibility in the signatures. + """ + from .verifier import Verifier, _caller_dir_pycache + # + # If set_unicode(True) was called, insert the UNICODE and + # _UNICODE macro declarations + if self._windows_unicode: + self._apply_windows_unicode(kwargs) + # + # Set the tmpdir here, and not in Verifier.__init__: it picks + # up the caller's directory, which we want to be the caller of + # ffi.verify(), as opposed to the caller of Veritier(). + tmpdir = tmpdir or _caller_dir_pycache() + # + # Make a Verifier() and use it to load the library. + self.verifier = Verifier(self, source, tmpdir, **kwargs) + lib = self.verifier.load_library() + # + # Save the loaded library for keep-alive purposes, even + # if the caller doesn't keep it alive itself (it should). + self._libraries.append(lib) + return lib + + def _get_errno(self): + return self._backend.get_errno() + def _set_errno(self, errno): + self._backend.set_errno(errno) + errno = property(_get_errno, _set_errno, None, + "the value of 'errno' from/to the C calls") + + def getwinerror(self, code=-1): + return self._backend.getwinerror(code) + + def _pointer_to(self, ctype): + with self._lock: + return model.pointer_cache(self, ctype) + + def addressof(self, cdata, *fields_or_indexes): + """Return the address of a . + If 'fields_or_indexes' are given, returns the address of that + field or array item in the structure or array, recursively in + case of nested structures. + """ + try: + ctype = self._backend.typeof(cdata) + except TypeError: + if '__addressof__' in type(cdata).__dict__: + return type(cdata).__addressof__(cdata, *fields_or_indexes) + raise + if fields_or_indexes: + ctype, offset = self._typeoffsetof(ctype, *fields_or_indexes) + else: + if ctype.kind == "pointer": + raise TypeError("addressof(pointer)") + offset = 0 + ctypeptr = self._pointer_to(ctype) + return self._backend.rawaddressof(ctypeptr, cdata, offset) + + def _typeoffsetof(self, ctype, field_or_index, *fields_or_indexes): + ctype, offset = self._backend.typeoffsetof(ctype, field_or_index) + for field1 in fields_or_indexes: + ctype, offset1 = self._backend.typeoffsetof(ctype, field1, 1) + offset += offset1 + return ctype, offset + + def include(self, ffi_to_include): + """Includes the typedefs, structs, unions and enums defined + in another FFI instance. Usage is similar to a #include in C, + where a part of the program might include types defined in + another part for its own usage. Note that the include() + method has no effect on functions, constants and global + variables, which must anyway be accessed directly from the + lib object returned by the original FFI instance. + """ + if not isinstance(ffi_to_include, FFI): + raise TypeError("ffi.include() expects an argument that is also of" + " type cffi.FFI, not %r" % ( + type(ffi_to_include).__name__,)) + if ffi_to_include is self: + raise ValueError("self.include(self)") + with ffi_to_include._lock: + with self._lock: + self._parser.include(ffi_to_include._parser) + self._cdefsources.append('[') + self._cdefsources.extend(ffi_to_include._cdefsources) + self._cdefsources.append(']') + self._included_ffis.append(ffi_to_include) + + def new_handle(self, x): + return self._backend.newp_handle(self.BVoidP, x) + + def from_handle(self, x): + return self._backend.from_handle(x) + + def release(self, x): + self._backend.release(x) + + def set_unicode(self, enabled_flag): + """Windows: if 'enabled_flag' is True, enable the UNICODE and + _UNICODE defines in C, and declare the types like TCHAR and LPTCSTR + to be (pointers to) wchar_t. If 'enabled_flag' is False, + declare these types to be (pointers to) plain 8-bit characters. + This is mostly for backward compatibility; you usually want True. + """ + if self._windows_unicode is not None: + raise ValueError("set_unicode() can only be called once") + enabled_flag = bool(enabled_flag) + if enabled_flag: + self.cdef("typedef wchar_t TBYTE;" + "typedef wchar_t TCHAR;" + "typedef const wchar_t *LPCTSTR;" + "typedef const wchar_t *PCTSTR;" + "typedef wchar_t *LPTSTR;" + "typedef wchar_t *PTSTR;" + "typedef TBYTE *PTBYTE;" + "typedef TCHAR *PTCHAR;") + else: + self.cdef("typedef char TBYTE;" + "typedef char TCHAR;" + "typedef const char *LPCTSTR;" + "typedef const char *PCTSTR;" + "typedef char *LPTSTR;" + "typedef char *PTSTR;" + "typedef TBYTE *PTBYTE;" + "typedef TCHAR *PTCHAR;") + self._windows_unicode = enabled_flag + + def _apply_windows_unicode(self, kwds): + defmacros = kwds.get('define_macros', ()) + if not isinstance(defmacros, (list, tuple)): + raise TypeError("'define_macros' must be a list or tuple") + defmacros = list(defmacros) + [('UNICODE', '1'), + ('_UNICODE', '1')] + kwds['define_macros'] = defmacros + + def _apply_embedding_fix(self, kwds): + # must include an argument like "-lpython2.7" for the compiler + def ensure(key, value): + lst = kwds.setdefault(key, []) + if value not in lst: + lst.append(value) + # + if '__pypy__' in sys.builtin_module_names: + import os + if sys.platform == "win32": + # we need 'libpypy-c.lib'. Current distributions of + # pypy (>= 4.1) contain it as 'libs/python27.lib'. + pythonlib = "python{0[0]}{0[1]}".format(sys.version_info) + if hasattr(sys, 'prefix'): + ensure('library_dirs', os.path.join(sys.prefix, 'libs')) + else: + # we need 'libpypy-c.{so,dylib}', which should be by + # default located in 'sys.prefix/bin' for installed + # systems. + if sys.version_info < (3,): + pythonlib = "pypy-c" + else: + pythonlib = "pypy3-c" + if hasattr(sys, 'prefix'): + ensure('library_dirs', os.path.join(sys.prefix, 'bin')) + # On uninstalled pypy's, the libpypy-c is typically found in + # .../pypy/goal/. + if hasattr(sys, 'prefix'): + ensure('library_dirs', os.path.join(sys.prefix, 'pypy', 'goal')) + else: + if sys.platform == "win32": + template = "python%d%d" + if hasattr(sys, 'gettotalrefcount'): + template += '_d' + else: + try: + import sysconfig + except ImportError: # 2.6 + from cffi._shimmed_dist_utils import sysconfig + template = "python%d.%d" + if sysconfig.get_config_var('DEBUG_EXT'): + template += sysconfig.get_config_var('DEBUG_EXT') + pythonlib = (template % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + if hasattr(sys, 'abiflags'): + pythonlib += sys.abiflags + ensure('libraries', pythonlib) + if sys.platform == "win32": + ensure('extra_link_args', '/MANIFEST') + + def set_source(self, module_name, source, source_extension='.c', **kwds): + import os + if hasattr(self, '_assigned_source'): + raise ValueError("set_source() cannot be called several times " + "per ffi object") + if not isinstance(module_name, basestring): + raise TypeError("'module_name' must be a string") + if os.sep in module_name or (os.altsep and os.altsep in module_name): + raise ValueError("'module_name' must not contain '/': use a dotted " + "name to make a 'package.module' location") + self._assigned_source = (str(module_name), source, + source_extension, kwds) + + def set_source_pkgconfig(self, module_name, pkgconfig_libs, source, + source_extension='.c', **kwds): + from . import pkgconfig + if not isinstance(pkgconfig_libs, list): + raise TypeError("the pkgconfig_libs argument must be a list " + "of package names") + kwds2 = pkgconfig.flags_from_pkgconfig(pkgconfig_libs) + pkgconfig.merge_flags(kwds, kwds2) + self.set_source(module_name, source, source_extension, **kwds) + + def distutils_extension(self, tmpdir='build', verbose=True): + from cffi._shimmed_dist_utils import mkpath + from .recompiler import recompile + # + if not hasattr(self, '_assigned_source'): + if hasattr(self, 'verifier'): # fallback, 'tmpdir' ignored + return self.verifier.get_extension() + raise ValueError("set_source() must be called before" + " distutils_extension()") + module_name, source, source_extension, kwds = self._assigned_source + if source is None: + raise TypeError("distutils_extension() is only for C extension " + "modules, not for dlopen()-style pure Python " + "modules") + mkpath(tmpdir) + ext, updated = recompile(self, module_name, + source, tmpdir=tmpdir, extradir=tmpdir, + source_extension=source_extension, + call_c_compiler=False, **kwds) + if verbose: + if updated: + sys.stderr.write("regenerated: %r\n" % (ext.sources[0],)) + else: + sys.stderr.write("not modified: %r\n" % (ext.sources[0],)) + return ext + + def emit_c_code(self, filename): + from .recompiler import recompile + # + if not hasattr(self, '_assigned_source'): + raise ValueError("set_source() must be called before emit_c_code()") + module_name, source, source_extension, kwds = self._assigned_source + if source is None: + raise TypeError("emit_c_code() is only for C extension modules, " + "not for dlopen()-style pure Python modules") + recompile(self, module_name, source, + c_file=filename, call_c_compiler=False, **kwds) + + def emit_python_code(self, filename): + from .recompiler import recompile + # + if not hasattr(self, '_assigned_source'): + raise ValueError("set_source() must be called before emit_c_code()") + module_name, source, source_extension, kwds = self._assigned_source + if source is not None: + raise TypeError("emit_python_code() is only for dlopen()-style " + "pure Python modules, not for C extension modules") + recompile(self, module_name, source, + c_file=filename, call_c_compiler=False, **kwds) + + def compile(self, tmpdir='.', verbose=0, target=None, debug=None): + """The 'target' argument gives the final file name of the + compiled DLL. Use '*' to force distutils' choice, suitable for + regular CPython C API modules. Use a file name ending in '.*' + to ask for the system's default extension for dynamic libraries + (.so/.dll/.dylib). + + The default is '*' when building a non-embedded C API extension, + and (module_name + '.*') when building an embedded library. + """ + from .recompiler import recompile + # + if not hasattr(self, '_assigned_source'): + raise ValueError("set_source() must be called before compile()") + module_name, source, source_extension, kwds = self._assigned_source + return recompile(self, module_name, source, tmpdir=tmpdir, + target=target, source_extension=source_extension, + compiler_verbose=verbose, debug=debug, **kwds) + + def init_once(self, func, tag): + # Read _init_once_cache[tag], which is either (False, lock) if + # we're calling the function now in some thread, or (True, result). + # Don't call setdefault() in most cases, to avoid allocating and + # immediately freeing a lock; but still use setdefaut() to avoid + # races. + try: + x = self._init_once_cache[tag] + except KeyError: + x = self._init_once_cache.setdefault(tag, (False, allocate_lock())) + # Common case: we got (True, result), so we return the result. + if x[0]: + return x[1] + # Else, it's a lock. Acquire it to serialize the following tests. + with x[1]: + # Read again from _init_once_cache the current status. + x = self._init_once_cache[tag] + if x[0]: + return x[1] + # Call the function and store the result back. + result = func() + self._init_once_cache[tag] = (True, result) + return result + + def embedding_init_code(self, pysource): + if self._embedding: + raise ValueError("embedding_init_code() can only be called once") + # fix 'pysource' before it gets dumped into the C file: + # - remove empty lines at the beginning, so it starts at "line 1" + # - dedent, if all non-empty lines are indented + # - check for SyntaxErrors + import re + match = re.match(r'\s*\n', pysource) + if match: + pysource = pysource[match.end():] + lines = pysource.splitlines() or [''] + prefix = re.match(r'\s*', lines[0]).group() + for i in range(1, len(lines)): + line = lines[i] + if line.rstrip(): + while not line.startswith(prefix): + prefix = prefix[:-1] + i = len(prefix) + lines = [line[i:]+'\n' for line in lines] + pysource = ''.join(lines) + # + compile(pysource, "cffi_init", "exec") + # + self._embedding = pysource + + def def_extern(self, *args, **kwds): + raise ValueError("ffi.def_extern() is only available on API-mode FFI " + "objects") + + def list_types(self): + """Returns the user type names known to this FFI instance. + This returns a tuple containing three lists of names: + (typedef_names, names_of_structs, names_of_unions) + """ + typedefs = [] + structs = [] + unions = [] + for key in self._parser._declarations: + if key.startswith('typedef '): + typedefs.append(key[8:]) + elif key.startswith('struct '): + structs.append(key[7:]) + elif key.startswith('union '): + unions.append(key[6:]) + typedefs.sort() + structs.sort() + unions.sort() + return (typedefs, structs, unions) + + +def _load_backend_lib(backend, name, flags): + import os + if not isinstance(name, basestring): + if sys.platform != "win32" or name is not None: + return backend.load_library(name, flags) + name = "c" # Windows: load_library(None) fails, but this works + # on Python 2 (backward compatibility hack only) + first_error = None + if '.' in name or '/' in name or os.sep in name: + try: + return backend.load_library(name, flags) + except OSError as e: + first_error = e + import ctypes.util + path = ctypes.util.find_library(name) + if path is None: + if name == "c" and sys.platform == "win32" and sys.version_info >= (3,): + raise OSError("dlopen(None) cannot work on Windows for Python 3 " + "(see http://bugs.python.org/issue23606)") + msg = ("ctypes.util.find_library() did not manage " + "to locate a library called %r" % (name,)) + if first_error is not None: + msg = "%s. Additionally, %s" % (first_error, msg) + raise OSError(msg) + return backend.load_library(path, flags) + +def _make_ffi_library(ffi, libname, flags): + backend = ffi._backend + backendlib = _load_backend_lib(backend, libname, flags) + # + def accessor_function(name): + key = 'function ' + name + tp, _ = ffi._parser._declarations[key] + BType = ffi._get_cached_btype(tp) + value = backendlib.load_function(BType, name) + library.__dict__[name] = value + # + def accessor_variable(name): + key = 'variable ' + name + tp, _ = ffi._parser._declarations[key] + BType = ffi._get_cached_btype(tp) + read_variable = backendlib.read_variable + write_variable = backendlib.write_variable + setattr(FFILibrary, name, property( + lambda self: read_variable(BType, name), + lambda self, value: write_variable(BType, name, value))) + # + def addressof_var(name): + try: + return addr_variables[name] + except KeyError: + with ffi._lock: + if name not in addr_variables: + key = 'variable ' + name + tp, _ = ffi._parser._declarations[key] + BType = ffi._get_cached_btype(tp) + if BType.kind != 'array': + BType = model.pointer_cache(ffi, BType) + p = backendlib.load_function(BType, name) + addr_variables[name] = p + return addr_variables[name] + # + def accessor_constant(name): + raise NotImplementedError("non-integer constant '%s' cannot be " + "accessed from a dlopen() library" % (name,)) + # + def accessor_int_constant(name): + library.__dict__[name] = ffi._parser._int_constants[name] + # + accessors = {} + accessors_version = [False] + addr_variables = {} + # + def update_accessors(): + if accessors_version[0] is ffi._cdef_version: + return + # + for key, (tp, _) in ffi._parser._declarations.items(): + if not isinstance(tp, model.EnumType): + tag, name = key.split(' ', 1) + if tag == 'function': + accessors[name] = accessor_function + elif tag == 'variable': + accessors[name] = accessor_variable + elif tag == 'constant': + accessors[name] = accessor_constant + else: + for i, enumname in enumerate(tp.enumerators): + def accessor_enum(name, tp=tp, i=i): + tp.check_not_partial() + library.__dict__[name] = tp.enumvalues[i] + accessors[enumname] = accessor_enum + for name in ffi._parser._int_constants: + accessors.setdefault(name, accessor_int_constant) + accessors_version[0] = ffi._cdef_version + # + def make_accessor(name): + with ffi._lock: + if name in library.__dict__ or name in FFILibrary.__dict__: + return # added by another thread while waiting for the lock + if name not in accessors: + update_accessors() + if name not in accessors: + raise AttributeError(name) + accessors[name](name) + # + class FFILibrary(object): + def __getattr__(self, name): + make_accessor(name) + return getattr(self, name) + def __setattr__(self, name, value): + try: + property = getattr(self.__class__, name) + except AttributeError: + make_accessor(name) + setattr(self, name, value) + else: + property.__set__(self, value) + def __dir__(self): + with ffi._lock: + update_accessors() + return accessors.keys() + def __addressof__(self, name): + if name in library.__dict__: + return library.__dict__[name] + if name in FFILibrary.__dict__: + return addressof_var(name) + make_accessor(name) + if name in library.__dict__: + return library.__dict__[name] + if name in FFILibrary.__dict__: + return addressof_var(name) + raise AttributeError("cffi library has no function or " + "global variable named '%s'" % (name,)) + def __cffi_close__(self): + backendlib.close_lib() + self.__dict__.clear() + # + if isinstance(libname, basestring): + try: + if not isinstance(libname, str): # unicode, on Python 2 + libname = libname.encode('utf-8') + FFILibrary.__name__ = 'FFILibrary_%s' % libname + except UnicodeError: + pass + library = FFILibrary() + return library, library.__dict__ + +def _builtin_function_type(func): + # a hack to make at least ffi.typeof(builtin_function) work, + # if the builtin function was obtained by 'vengine_cpy'. + import sys + try: + module = sys.modules[func.__module__] + ffi = module._cffi_original_ffi + types_of_builtin_funcs = module._cffi_types_of_builtin_funcs + tp = types_of_builtin_funcs[func] + except (KeyError, AttributeError, TypeError): + return None + else: + with ffi._lock: + return ffi._get_cached_btype(tp) diff --git a/.venv/Lib/site-packages/cffi/backend_ctypes.py b/.venv/Lib/site-packages/cffi/backend_ctypes.py new file mode 100644 index 00000000..e7956a79 --- /dev/null +++ b/.venv/Lib/site-packages/cffi/backend_ctypes.py @@ -0,0 +1,1121 @@ +import ctypes, ctypes.util, operator, sys +from . import model + +if sys.version_info < (3,): + bytechr = chr +else: + unicode = str + long = int + xrange = range + bytechr = lambda num: bytes([num]) + +class CTypesType(type): + pass + +class CTypesData(object): + __metaclass__ = CTypesType + __slots__ = ['__weakref__'] + __name__ = '' + + def __init__(self, *args): + raise TypeError("cannot instantiate %r" % (self.__class__,)) + + @classmethod + def _newp(cls, init): + raise TypeError("expected a pointer or array ctype, got '%s'" + % (cls._get_c_name(),)) + + @staticmethod + def _to_ctypes(value): + raise TypeError + + @classmethod + def _arg_to_ctypes(cls, *value): + try: + ctype = cls._ctype + except AttributeError: + raise TypeError("cannot create an instance of %r" % (cls,)) + if value: + res = cls._to_ctypes(*value) + if not isinstance(res, ctype): + res = cls._ctype(res) + else: + res = cls._ctype() + return res + + @classmethod + def _create_ctype_obj(cls, init): + if init is None: + return cls._arg_to_ctypes() + else: + return cls._arg_to_ctypes(init) + + @staticmethod + def _from_ctypes(ctypes_value): + raise TypeError + + @classmethod + def _get_c_name(cls, replace_with=''): + return cls._reftypename.replace(' &', replace_with) + + @classmethod + def _fix_class(cls): + cls.__name__ = 'CData<%s>' % (cls._get_c_name(),) + cls.__qualname__ = 'CData<%s>' % (cls._get_c_name(),) + cls.__module__ = 'ffi' + + def _get_own_repr(self): + raise NotImplementedError + + def _addr_repr(self, address): + if address == 0: + return 'NULL' + else: + if address < 0: + address += 1 << (8*ctypes.sizeof(ctypes.c_void_p)) + return '0x%x' % address + + def __repr__(self, c_name=None): + own = self._get_own_repr() + return '' % (c_name or self._get_c_name(), own) + + def _convert_to_address(self, BClass): + if BClass is None: + raise TypeError("cannot convert %r to an address" % ( + self._get_c_name(),)) + else: + raise TypeError("cannot convert %r to %r" % ( + self._get_c_name(), BClass._get_c_name())) + + @classmethod + def _get_size(cls): + return ctypes.sizeof(cls._ctype) + + def _get_size_of_instance(self): + return ctypes.sizeof(self._ctype) + + @classmethod + def _cast_from(cls, source): + raise TypeError("cannot cast to %r" % (cls._get_c_name(),)) + + def _cast_to_integer(self): + return self._convert_to_address(None) + + @classmethod + def _alignment(cls): + return ctypes.alignment(cls._ctype) + + def __iter__(self): + raise TypeError("cdata %r does not support iteration" % ( + self._get_c_name()),) + + def _make_cmp(name): + cmpfunc = getattr(operator, name) + def cmp(self, other): + v_is_ptr = not isinstance(self, CTypesGenericPrimitive) + w_is_ptr = (isinstance(other, CTypesData) and + not isinstance(other, CTypesGenericPrimitive)) + if v_is_ptr and w_is_ptr: + return cmpfunc(self._convert_to_address(None), + other._convert_to_address(None)) + elif v_is_ptr or w_is_ptr: + return NotImplemented + else: + if isinstance(self, CTypesGenericPrimitive): + self = self._value + if isinstance(other, CTypesGenericPrimitive): + other = other._value + return cmpfunc(self, other) + cmp.func_name = name + return cmp + + __eq__ = _make_cmp('__eq__') + __ne__ = _make_cmp('__ne__') + __lt__ = _make_cmp('__lt__') + __le__ = _make_cmp('__le__') + __gt__ = _make_cmp('__gt__') + __ge__ = _make_cmp('__ge__') + + def __hash__(self): + return hash(self._convert_to_address(None)) + + def _to_string(self, maxlen): + raise TypeError("string(): %r" % (self,)) + + +class CTypesGenericPrimitive(CTypesData): + __slots__ = [] + + def __hash__(self): + return hash(self._value) + + def _get_own_repr(self): + return repr(self._from_ctypes(self._value)) + + +class CTypesGenericArray(CTypesData): + __slots__ = [] + + @classmethod + def _newp(cls, init): + return cls(init) + + def __iter__(self): + for i in xrange(len(self)): + yield self[i] + + def _get_own_repr(self): + return self._addr_repr(ctypes.addressof(self._blob)) + + +class CTypesGenericPtr(CTypesData): + __slots__ = ['_address', '_as_ctype_ptr'] + _automatic_casts = False + kind = "pointer" + + @classmethod + def _newp(cls, init): + return cls(init) + + @classmethod + def _cast_from(cls, source): + if source is None: + address = 0 + elif isinstance(source, CTypesData): + address = source._cast_to_integer() + elif isinstance(source, (int, long)): + address = source + else: + raise TypeError("bad type for cast to %r: %r" % + (cls, type(source).__name__)) + return cls._new_pointer_at(address) + + @classmethod + def _new_pointer_at(cls, address): + self = cls.__new__(cls) + self._address = address + self._as_ctype_ptr = ctypes.cast(address, cls._ctype) + return self + + def _get_own_repr(self): + try: + return self._addr_repr(self._address) + except AttributeError: + return '???' + + def _cast_to_integer(self): + return self._address + + def __nonzero__(self): + return bool(self._address) + __bool__ = __nonzero__ + + @classmethod + def _to_ctypes(cls, value): + if not isinstance(value, CTypesData): + raise TypeError("unexpected %s object" % type(value).__name__) + address = value._convert_to_address(cls) + return ctypes.cast(address, cls._ctype) + + @classmethod + def _from_ctypes(cls, ctypes_ptr): + address = ctypes.cast(ctypes_ptr, ctypes.c_void_p).value or 0 + return cls._new_pointer_at(address) + + @classmethod + def _initialize(cls, ctypes_ptr, value): + if value: + ctypes_ptr.contents = cls._to_ctypes(value).contents + + def _convert_to_address(self, BClass): + if (BClass in (self.__class__, None) or BClass._automatic_casts + or self._automatic_casts): + return self._address + else: + return CTypesData._convert_to_address(self, BClass) + + +class CTypesBaseStructOrUnion(CTypesData): + __slots__ = ['_blob'] + + @classmethod + def _create_ctype_obj(cls, init): + # may be overridden + raise TypeError("cannot instantiate opaque type %s" % (cls,)) + + def _get_own_repr(self): + return self._addr_repr(ctypes.addressof(self._blob)) + + @classmethod + def _offsetof(cls, fieldname): + return getattr(cls._ctype, fieldname).offset + + def _convert_to_address(self, BClass): + if getattr(BClass, '_BItem', None) is self.__class__: + return ctypes.addressof(self._blob) + else: + return CTypesData._convert_to_address(self, BClass) + + @classmethod + def _from_ctypes(cls, ctypes_struct_or_union): + self = cls.__new__(cls) + self._blob = ctypes_struct_or_union + return self + + @classmethod + def _to_ctypes(cls, value): + return value._blob + + def __repr__(self, c_name=None): + return CTypesData.__repr__(self, c_name or self._get_c_name(' &')) + + +class CTypesBackend(object): + + PRIMITIVE_TYPES = { + 'char': ctypes.c_char, + 'short': ctypes.c_short, + 'int': ctypes.c_int, + 'long': ctypes.c_long, + 'long long': ctypes.c_longlong, + 'signed char': ctypes.c_byte, + 'unsigned char': ctypes.c_ubyte, + 'unsigned short': ctypes.c_ushort, + 'unsigned int': ctypes.c_uint, + 'unsigned long': ctypes.c_ulong, + 'unsigned long long': ctypes.c_ulonglong, + 'float': ctypes.c_float, + 'double': ctypes.c_double, + '_Bool': ctypes.c_bool, + } + + for _name in ['unsigned long long', 'unsigned long', + 'unsigned int', 'unsigned short', 'unsigned char']: + _size = ctypes.sizeof(PRIMITIVE_TYPES[_name]) + PRIMITIVE_TYPES['uint%d_t' % (8*_size)] = PRIMITIVE_TYPES[_name] + if _size == ctypes.sizeof(ctypes.c_void_p): + PRIMITIVE_TYPES['uintptr_t'] = PRIMITIVE_TYPES[_name] + if _size == ctypes.sizeof(ctypes.c_size_t): + PRIMITIVE_TYPES['size_t'] = PRIMITIVE_TYPES[_name] + + for _name in ['long long', 'long', 'int', 'short', 'signed char']: + _size = ctypes.sizeof(PRIMITIVE_TYPES[_name]) + PRIMITIVE_TYPES['int%d_t' % (8*_size)] = PRIMITIVE_TYPES[_name] + if _size == ctypes.sizeof(ctypes.c_void_p): + PRIMITIVE_TYPES['intptr_t'] = PRIMITIVE_TYPES[_name] + PRIMITIVE_TYPES['ptrdiff_t'] = PRIMITIVE_TYPES[_name] + if _size == ctypes.sizeof(ctypes.c_size_t): + PRIMITIVE_TYPES['ssize_t'] = PRIMITIVE_TYPES[_name] + + + def __init__(self): + self.RTLD_LAZY = 0 # not supported anyway by ctypes + self.RTLD_NOW = 0 + self.RTLD_GLOBAL = ctypes.RTLD_GLOBAL + self.RTLD_LOCAL = ctypes.RTLD_LOCAL + + def set_ffi(self, ffi): + self.ffi = ffi + + def _get_types(self): + return CTypesData, CTypesType + + def load_library(self, path, flags=0): + cdll = ctypes.CDLL(path, flags) + return CTypesLibrary(self, cdll) + + def new_void_type(self): + class CTypesVoid(CTypesData): + __slots__ = [] + _reftypename = 'void &' + @staticmethod + def _from_ctypes(novalue): + return None + @staticmethod + def _to_ctypes(novalue): + if novalue is not None: + raise TypeError("None expected, got %s object" % + (type(novalue).__name__,)) + return None + CTypesVoid._fix_class() + return CTypesVoid + + def new_primitive_type(self, name): + if name == 'wchar_t': + raise NotImplementedError(name) + ctype = self.PRIMITIVE_TYPES[name] + if name == 'char': + kind = 'char' + elif name in ('float', 'double'): + kind = 'float' + else: + if name in ('signed char', 'unsigned char'): + kind = 'byte' + elif name == '_Bool': + kind = 'bool' + else: + kind = 'int' + is_signed = (ctype(-1).value == -1) + # + def _cast_source_to_int(source): + if isinstance(source, (int, long, float)): + source = int(source) + elif isinstance(source, CTypesData): + source = source._cast_to_integer() + elif isinstance(source, bytes): + source = ord(source) + elif source is None: + source = 0 + else: + raise TypeError("bad type for cast to %r: %r" % + (CTypesPrimitive, type(source).__name__)) + return source + # + kind1 = kind + class CTypesPrimitive(CTypesGenericPrimitive): + __slots__ = ['_value'] + _ctype = ctype + _reftypename = '%s &' % name + kind = kind1 + + def __init__(self, value): + self._value = value + + @staticmethod + def _create_ctype_obj(init): + if init is None: + return ctype() + return ctype(CTypesPrimitive._to_ctypes(init)) + + if kind == 'int' or kind == 'byte': + @classmethod + def _cast_from(cls, source): + source = _cast_source_to_int(source) + source = ctype(source).value # cast within range + return cls(source) + def __int__(self): + return self._value + + if kind == 'bool': + @classmethod + def _cast_from(cls, source): + if not isinstance(source, (int, long, float)): + source = _cast_source_to_int(source) + return cls(bool(source)) + def __int__(self): + return int(self._value) + + if kind == 'char': + @classmethod + def _cast_from(cls, source): + source = _cast_source_to_int(source) + source = bytechr(source & 0xFF) + return cls(source) + def __int__(self): + return ord(self._value) + + if kind == 'float': + @classmethod + def _cast_from(cls, source): + if isinstance(source, float): + pass + elif isinstance(source, CTypesGenericPrimitive): + if hasattr(source, '__float__'): + source = float(source) + else: + source = int(source) + else: + source = _cast_source_to_int(source) + source = ctype(source).value # fix precision + return cls(source) + def __int__(self): + return int(self._value) + def __float__(self): + return self._value + + _cast_to_integer = __int__ + + if kind == 'int' or kind == 'byte' or kind == 'bool': + @staticmethod + def _to_ctypes(x): + if not isinstance(x, (int, long)): + if isinstance(x, CTypesData): + x = int(x) + else: + raise TypeError("integer expected, got %s" % + type(x).__name__) + if ctype(x).value != x: + if not is_signed and x < 0: + raise OverflowError("%s: negative integer" % name) + else: + raise OverflowError("%s: integer out of bounds" + % name) + return x + + if kind == 'char': + @staticmethod + def _to_ctypes(x): + if isinstance(x, bytes) and len(x) == 1: + return x + if isinstance(x, CTypesPrimitive): # > + return x._value + raise TypeError("character expected, got %s" % + type(x).__name__) + def __nonzero__(self): + return ord(self._value) != 0 + else: + def __nonzero__(self): + return self._value != 0 + __bool__ = __nonzero__ + + if kind == 'float': + @staticmethod + def _to_ctypes(x): + if not isinstance(x, (int, long, float, CTypesData)): + raise TypeError("float expected, got %s" % + type(x).__name__) + return ctype(x).value + + @staticmethod + def _from_ctypes(value): + return getattr(value, 'value', value) + + @staticmethod + def _initialize(blob, init): + blob.value = CTypesPrimitive._to_ctypes(init) + + if kind == 'char': + def _to_string(self, maxlen): + return self._value + if kind == 'byte': + def _to_string(self, maxlen): + return chr(self._value & 0xff) + # + CTypesPrimitive._fix_class() + return CTypesPrimitive + + def new_pointer_type(self, BItem): + getbtype = self.ffi._get_cached_btype + if BItem is getbtype(model.PrimitiveType('char')): + kind = 'charp' + elif BItem in (getbtype(model.PrimitiveType('signed char')), + getbtype(model.PrimitiveType('unsigned char'))): + kind = 'bytep' + elif BItem is getbtype(model.void_type): + kind = 'voidp' + else: + kind = 'generic' + # + class CTypesPtr(CTypesGenericPtr): + __slots__ = ['_own'] + if kind == 'charp': + __slots__ += ['__as_strbuf'] + _BItem = BItem + if hasattr(BItem, '_ctype'): + _ctype = ctypes.POINTER(BItem._ctype) + _bitem_size = ctypes.sizeof(BItem._ctype) + else: + _ctype = ctypes.c_void_p + if issubclass(BItem, CTypesGenericArray): + _reftypename = BItem._get_c_name('(* &)') + else: + _reftypename = BItem._get_c_name(' * &') + + def __init__(self, init): + ctypeobj = BItem._create_ctype_obj(init) + if kind == 'charp': + self.__as_strbuf = ctypes.create_string_buffer( + ctypeobj.value + b'\x00') + self._as_ctype_ptr = ctypes.cast( + self.__as_strbuf, self._ctype) + else: + self._as_ctype_ptr = ctypes.pointer(ctypeobj) + self._address = ctypes.cast(self._as_ctype_ptr, + ctypes.c_void_p).value + self._own = True + + def __add__(self, other): + if isinstance(other, (int, long)): + return self._new_pointer_at(self._address + + other * self._bitem_size) + else: + return NotImplemented + + def __sub__(self, other): + if isinstance(other, (int, long)): + return self._new_pointer_at(self._address - + other * self._bitem_size) + elif type(self) is type(other): + return (self._address - other._address) // self._bitem_size + else: + return NotImplemented + + def __getitem__(self, index): + if getattr(self, '_own', False) and index != 0: + raise IndexError + return BItem._from_ctypes(self._as_ctype_ptr[index]) + + def __setitem__(self, index, value): + self._as_ctype_ptr[index] = BItem._to_ctypes(value) + + if kind == 'charp' or kind == 'voidp': + @classmethod + def _arg_to_ctypes(cls, *value): + if value and isinstance(value[0], bytes): + return ctypes.c_char_p(value[0]) + else: + return super(CTypesPtr, cls)._arg_to_ctypes(*value) + + if kind == 'charp' or kind == 'bytep': + def _to_string(self, maxlen): + if maxlen < 0: + maxlen = sys.maxsize + p = ctypes.cast(self._as_ctype_ptr, + ctypes.POINTER(ctypes.c_char)) + n = 0 + while n < maxlen and p[n] != b'\x00': + n += 1 + return b''.join([p[i] for i in range(n)]) + + def _get_own_repr(self): + if getattr(self, '_own', False): + return 'owning %d bytes' % ( + ctypes.sizeof(self._as_ctype_ptr.contents),) + return super(CTypesPtr, self)._get_own_repr() + # + if (BItem is self.ffi._get_cached_btype(model.void_type) or + BItem is self.ffi._get_cached_btype(model.PrimitiveType('char'))): + CTypesPtr._automatic_casts = True + # + CTypesPtr._fix_class() + return CTypesPtr + + def new_array_type(self, CTypesPtr, length): + if length is None: + brackets = ' &[]' + else: + brackets = ' &[%d]' % length + BItem = CTypesPtr._BItem + getbtype = self.ffi._get_cached_btype + if BItem is getbtype(model.PrimitiveType('char')): + kind = 'char' + elif BItem in (getbtype(model.PrimitiveType('signed char')), + getbtype(model.PrimitiveType('unsigned char'))): + kind = 'byte' + else: + kind = 'generic' + # + class CTypesArray(CTypesGenericArray): + __slots__ = ['_blob', '_own'] + if length is not None: + _ctype = BItem._ctype * length + else: + __slots__.append('_ctype') + _reftypename = BItem._get_c_name(brackets) + _declared_length = length + _CTPtr = CTypesPtr + + def __init__(self, init): + if length is None: + if isinstance(init, (int, long)): + len1 = init + init = None + elif kind == 'char' and isinstance(init, bytes): + len1 = len(init) + 1 # extra null + else: + init = tuple(init) + len1 = len(init) + self._ctype = BItem._ctype * len1 + self._blob = self._ctype() + self._own = True + if init is not None: + self._initialize(self._blob, init) + + @staticmethod + def _initialize(blob, init): + if isinstance(init, bytes): + init = [init[i:i+1] for i in range(len(init))] + else: + if isinstance(init, CTypesGenericArray): + if (len(init) != len(blob) or + not isinstance(init, CTypesArray)): + raise TypeError("length/type mismatch: %s" % (init,)) + init = tuple(init) + if len(init) > len(blob): + raise IndexError("too many initializers") + addr = ctypes.cast(blob, ctypes.c_void_p).value + PTR = ctypes.POINTER(BItem._ctype) + itemsize = ctypes.sizeof(BItem._ctype) + for i, value in enumerate(init): + p = ctypes.cast(addr + i * itemsize, PTR) + BItem._initialize(p.contents, value) + + def __len__(self): + return len(self._blob) + + def __getitem__(self, index): + if not (0 <= index < len(self._blob)): + raise IndexError + return BItem._from_ctypes(self._blob[index]) + + def __setitem__(self, index, value): + if not (0 <= index < len(self._blob)): + raise IndexError + self._blob[index] = BItem._to_ctypes(value) + + if kind == 'char' or kind == 'byte': + def _to_string(self, maxlen): + if maxlen < 0: + maxlen = len(self._blob) + p = ctypes.cast(self._blob, + ctypes.POINTER(ctypes.c_char)) + n = 0 + while n < maxlen and p[n] != b'\x00': + n += 1 + return b''.join([p[i] for i in range(n)]) + + def _get_own_repr(self): + if getattr(self, '_own', False): + return 'owning %d bytes' % (ctypes.sizeof(self._blob),) + return super(CTypesArray, self)._get_own_repr() + + def _convert_to_address(self, BClass): + if BClass in (CTypesPtr, None) or BClass._automatic_casts: + return ctypes.addressof(self._blob) + else: + return CTypesData._convert_to_address(self, BClass) + + @staticmethod + def _from_ctypes(ctypes_array): + self = CTypesArray.__new__(CTypesArray) + self._blob = ctypes_array + return self + + @staticmethod + def _arg_to_ctypes(value): + return CTypesPtr._arg_to_ctypes(value) + + def __add__(self, other): + if isinstance(other, (int, long)): + return CTypesPtr._new_pointer_at( + ctypes.addressof(self._blob) + + other * ctypes.sizeof(BItem._ctype)) + else: + return NotImplemented + + @classmethod + def _cast_from(cls, source): + raise NotImplementedError("casting to %r" % ( + cls._get_c_name(),)) + # + CTypesArray._fix_class() + return CTypesArray + + def _new_struct_or_union(self, kind, name, base_ctypes_class): + # + class struct_or_union(base_ctypes_class): + pass + struct_or_union.__name__ = '%s_%s' % (kind, name) + kind1 = kind + # + class CTypesStructOrUnion(CTypesBaseStructOrUnion): + __slots__ = ['_blob'] + _ctype = struct_or_union + _reftypename = '%s &' % (name,) + _kind = kind = kind1 + # + CTypesStructOrUnion._fix_class() + return CTypesStructOrUnion + + def new_struct_type(self, name): + return self._new_struct_or_union('struct', name, ctypes.Structure) + + def new_union_type(self, name): + return self._new_struct_or_union('union', name, ctypes.Union) + + def complete_struct_or_union(self, CTypesStructOrUnion, fields, tp, + totalsize=-1, totalalignment=-1, sflags=0, + pack=0): + if totalsize >= 0 or totalalignment >= 0: + raise NotImplementedError("the ctypes backend of CFFI does not support " + "structures completed by verify(); please " + "compile and install the _cffi_backend module.") + struct_or_union = CTypesStructOrUnion._ctype + fnames = [fname for (fname, BField, bitsize) in fields] + btypes = [BField for (fname, BField, bitsize) in fields] + bitfields = [bitsize for (fname, BField, bitsize) in fields] + # + bfield_types = {} + cfields = [] + for (fname, BField, bitsize) in fields: + if bitsize < 0: + cfields.append((fname, BField._ctype)) + bfield_types[fname] = BField + else: + cfields.append((fname, BField._ctype, bitsize)) + bfield_types[fname] = Ellipsis + if sflags & 8: + struct_or_union._pack_ = 1 + elif pack: + struct_or_union._pack_ = pack + struct_or_union._fields_ = cfields + CTypesStructOrUnion._bfield_types = bfield_types + # + @staticmethod + def _create_ctype_obj(init): + result = struct_or_union() + if init is not None: + initialize(result, init) + return result + CTypesStructOrUnion._create_ctype_obj = _create_ctype_obj + # + def initialize(blob, init): + if is_union: + if len(init) > 1: + raise ValueError("union initializer: %d items given, but " + "only one supported (use a dict if needed)" + % (len(init),)) + if not isinstance(init, dict): + if isinstance(init, (bytes, unicode)): + raise TypeError("union initializer: got a str") + init = tuple(init) + if len(init) > len(fnames): + raise ValueError("too many values for %s initializer" % + CTypesStructOrUnion._get_c_name()) + init = dict(zip(fnames, init)) + addr = ctypes.addressof(blob) + for fname, value in init.items(): + BField, bitsize = name2fieldtype[fname] + assert bitsize < 0, \ + "not implemented: initializer with bit fields" + offset = CTypesStructOrUnion._offsetof(fname) + PTR = ctypes.POINTER(BField._ctype) + p = ctypes.cast(addr + offset, PTR) + BField._initialize(p.contents, value) + is_union = CTypesStructOrUnion._kind == 'union' + name2fieldtype = dict(zip(fnames, zip(btypes, bitfields))) + # + for fname, BField, bitsize in fields: + if fname == '': + raise NotImplementedError("nested anonymous structs/unions") + if hasattr(CTypesStructOrUnion, fname): + raise ValueError("the field name %r conflicts in " + "the ctypes backend" % fname) + if bitsize < 0: + def getter(self, fname=fname, BField=BField, + offset=CTypesStructOrUnion._offsetof(fname), + PTR=ctypes.POINTER(BField._ctype)): + addr = ctypes.addressof(self._blob) + p = ctypes.cast(addr + offset, PTR) + return BField._from_ctypes(p.contents) + def setter(self, value, fname=fname, BField=BField): + setattr(self._blob, fname, BField._to_ctypes(value)) + # + if issubclass(BField, CTypesGenericArray): + setter = None + if BField._declared_length == 0: + def getter(self, fname=fname, BFieldPtr=BField._CTPtr, + offset=CTypesStructOrUnion._offsetof(fname), + PTR=ctypes.POINTER(BField._ctype)): + addr = ctypes.addressof(self._blob) + p = ctypes.cast(addr + offset, PTR) + return BFieldPtr._from_ctypes(p) + # + else: + def getter(self, fname=fname, BField=BField): + return BField._from_ctypes(getattr(self._blob, fname)) + def setter(self, value, fname=fname, BField=BField): + # xxx obscure workaround + value = BField._to_ctypes(value) + oldvalue = getattr(self._blob, fname) + setattr(self._blob, fname, value) + if value != getattr(self._blob, fname): + setattr(self._blob, fname, oldvalue) + raise OverflowError("value too large for bitfield") + setattr(CTypesStructOrUnion, fname, property(getter, setter)) + # + CTypesPtr = self.ffi._get_cached_btype(model.PointerType(tp)) + for fname in fnames: + if hasattr(CTypesPtr, fname): + raise ValueError("the field name %r conflicts in " + "the ctypes backend" % fname) + def getter(self, fname=fname): + return getattr(self[0], fname) + def setter(self, value, fname=fname): + setattr(self[0], fname, value) + setattr(CTypesPtr, fname, property(getter, setter)) + + def new_function_type(self, BArgs, BResult, has_varargs): + nameargs = [BArg._get_c_name() for BArg in BArgs] + if has_varargs: + nameargs.append('...') + nameargs = ', '.join(nameargs) + # + class CTypesFunctionPtr(CTypesGenericPtr): + __slots__ = ['_own_callback', '_name'] + _ctype = ctypes.CFUNCTYPE(getattr(BResult, '_ctype', None), + *[BArg._ctype for BArg in BArgs], + use_errno=True) + _reftypename = BResult._get_c_name('(* &)(%s)' % (nameargs,)) + + def __init__(self, init, error=None): + # create a callback to the Python callable init() + import traceback + assert not has_varargs, "varargs not supported for callbacks" + if getattr(BResult, '_ctype', None) is not None: + error = BResult._from_ctypes( + BResult._create_ctype_obj(error)) + else: + error = None + def callback(*args): + args2 = [] + for arg, BArg in zip(args, BArgs): + args2.append(BArg._from_ctypes(arg)) + try: + res2 = init(*args2) + res2 = BResult._to_ctypes(res2) + except: + traceback.print_exc() + res2 = error + if issubclass(BResult, CTypesGenericPtr): + if res2: + res2 = ctypes.cast(res2, ctypes.c_void_p).value + # .value: http://bugs.python.org/issue1574593 + else: + res2 = None + #print repr(res2) + return res2 + if issubclass(BResult, CTypesGenericPtr): + # The only pointers callbacks can return are void*s: + # http://bugs.python.org/issue5710 + callback_ctype = ctypes.CFUNCTYPE( + ctypes.c_void_p, + *[BArg._ctype for BArg in BArgs], + use_errno=True) + else: + callback_ctype = CTypesFunctionPtr._ctype + self._as_ctype_ptr = callback_ctype(callback) + self._address = ctypes.cast(self._as_ctype_ptr, + ctypes.c_void_p).value + self._own_callback = init + + @staticmethod + def _initialize(ctypes_ptr, value): + if value: + raise NotImplementedError("ctypes backend: not supported: " + "initializers for function pointers") + + def __repr__(self): + c_name = getattr(self, '_name', None) + if c_name: + i = self._reftypename.index('(* &)') + if self._reftypename[i-1] not in ' )*': + c_name = ' ' + c_name + c_name = self._reftypename.replace('(* &)', c_name) + return CTypesData.__repr__(self, c_name) + + def _get_own_repr(self): + if getattr(self, '_own_callback', None) is not None: + return 'calling %r' % (self._own_callback,) + return super(CTypesFunctionPtr, self)._get_own_repr() + + def __call__(self, *args): + if has_varargs: + assert len(args) >= len(BArgs) + extraargs = args[len(BArgs):] + args = args[:len(BArgs)] + else: + assert len(args) == len(BArgs) + ctypes_args = [] + for arg, BArg in zip(args, BArgs): + ctypes_args.append(BArg._arg_to_ctypes(arg)) + if has_varargs: + for i, arg in enumerate(extraargs): + if arg is None: + ctypes_args.append(ctypes.c_void_p(0)) # NULL + continue + if not isinstance(arg, CTypesData): + raise TypeError( + "argument %d passed in the variadic part " + "needs to be a cdata object (got %s)" % + (1 + len(BArgs) + i, type(arg).__name__)) + ctypes_args.append(arg._arg_to_ctypes(arg)) + result = self._as_ctype_ptr(*ctypes_args) + return BResult._from_ctypes(result) + # + CTypesFunctionPtr._fix_class() + return CTypesFunctionPtr + + def new_enum_type(self, name, enumerators, enumvalues, CTypesInt): + assert isinstance(name, str) + reverse_mapping = dict(zip(reversed(enumvalues), + reversed(enumerators))) + # + class CTypesEnum(CTypesInt): + __slots__ = [] + _reftypename = '%s &' % name + + def _get_own_repr(self): + value = self._value + try: + return '%d: %s' % (value, reverse_mapping[value]) + except KeyError: + return str(value) + + def _to_string(self, maxlen): + value = self._value + try: + return reverse_mapping[value] + except KeyError: + return str(value) + # + CTypesEnum._fix_class() + return CTypesEnum + + def get_errno(self): + return ctypes.get_errno() + + def set_errno(self, value): + ctypes.set_errno(value) + + def string(self, b, maxlen=-1): + return b._to_string(maxlen) + + def buffer(self, bptr, size=-1): + raise NotImplementedError("buffer() with ctypes backend") + + def sizeof(self, cdata_or_BType): + if isinstance(cdata_or_BType, CTypesData): + return cdata_or_BType._get_size_of_instance() + else: + assert issubclass(cdata_or_BType, CTypesData) + return cdata_or_BType._get_size() + + def alignof(self, BType): + assert issubclass(BType, CTypesData) + return BType._alignment() + + def newp(self, BType, source): + if not issubclass(BType, CTypesData): + raise TypeError + return BType._newp(source) + + def cast(self, BType, source): + return BType._cast_from(source) + + def callback(self, BType, source, error, onerror): + assert onerror is None # XXX not implemented + return BType(source, error) + + _weakref_cache_ref = None + + def gcp(self, cdata, destructor, size=0): + if self._weakref_cache_ref is None: + import weakref + class MyRef(weakref.ref): + def __eq__(self, other): + myref = self() + return self is other or ( + myref is not None and myref is other()) + def __ne__(self, other): + return not (self == other) + def __hash__(self): + try: + return self._hash + except AttributeError: + self._hash = hash(self()) + return self._hash + self._weakref_cache_ref = {}, MyRef + weak_cache, MyRef = self._weakref_cache_ref + + if destructor is None: + try: + del weak_cache[MyRef(cdata)] + except KeyError: + raise TypeError("Can remove destructor only on a object " + "previously returned by ffi.gc()") + return None + + def remove(k): + cdata, destructor = weak_cache.pop(k, (None, None)) + if destructor is not None: + destructor(cdata) + + new_cdata = self.cast(self.typeof(cdata), cdata) + assert new_cdata is not cdata + weak_cache[MyRef(new_cdata, remove)] = (cdata, destructor) + return new_cdata + + typeof = type + + def getcname(self, BType, replace_with): + return BType._get_c_name(replace_with) + + def typeoffsetof(self, BType, fieldname, num=0): + if isinstance(fieldname, str): + if num == 0 and issubclass(BType, CTypesGenericPtr): + BType = BType._BItem + if not issubclass(BType, CTypesBaseStructOrUnion): + raise TypeError("expected a struct or union ctype") + BField = BType._bfield_types[fieldname] + if BField is Ellipsis: + raise TypeError("not supported for bitfields") + return (BField, BType._offsetof(fieldname)) + elif isinstance(fieldname, (int, long)): + if issubclass(BType, CTypesGenericArray): + BType = BType._CTPtr + if not issubclass(BType, CTypesGenericPtr): + raise TypeError("expected an array or ptr ctype") + BItem = BType._BItem + offset = BItem._get_size() * fieldname + if offset > sys.maxsize: + raise OverflowError + return (BItem, offset) + else: + raise TypeError(type(fieldname)) + + def rawaddressof(self, BTypePtr, cdata, offset=None): + if isinstance(cdata, CTypesBaseStructOrUnion): + ptr = ctypes.pointer(type(cdata)._to_ctypes(cdata)) + elif isinstance(cdata, CTypesGenericPtr): + if offset is None or not issubclass(type(cdata)._BItem, + CTypesBaseStructOrUnion): + raise TypeError("unexpected cdata type") + ptr = type(cdata)._to_ctypes(cdata) + elif isinstance(cdata, CTypesGenericArray): + ptr = type(cdata)._to_ctypes(cdata) + else: + raise TypeError("expected a ") + if offset: + ptr = ctypes.cast( + ctypes.c_void_p( + ctypes.cast(ptr, ctypes.c_void_p).value + offset), + type(ptr)) + return BTypePtr._from_ctypes(ptr) + + +class CTypesLibrary(object): + + def __init__(self, backend, cdll): + self.backend = backend + self.cdll = cdll + + def load_function(self, BType, name): + c_func = getattr(self.cdll, name) + funcobj = BType._from_ctypes(c_func) + funcobj._name = name + return funcobj + + def read_variable(self, BType, name): + try: + ctypes_obj = BType._ctype.in_dll(self.cdll, name) + except AttributeError as e: + raise NotImplementedError(e) + return BType._from_ctypes(ctypes_obj) + + def write_variable(self, BType, name, value): + new_ctypes_obj = BType._to_ctypes(value) + ctypes_obj = BType._ctype.in_dll(self.cdll, name) + ctypes.memmove(ctypes.addressof(ctypes_obj), + ctypes.addressof(new_ctypes_obj), + ctypes.sizeof(BType._ctype)) diff --git a/.venv/Lib/site-packages/cffi/cffi_opcode.py b/.venv/Lib/site-packages/cffi/cffi_opcode.py new file mode 100644 index 00000000..a0df98d1 --- /dev/null +++ b/.venv/Lib/site-packages/cffi/cffi_opcode.py @@ -0,0 +1,187 @@ +from .error import VerificationError + +class CffiOp(object): + def __init__(self, op, arg): + self.op = op + self.arg = arg + + def as_c_expr(self): + if self.op is None: + assert isinstance(self.arg, str) + return '(_cffi_opcode_t)(%s)' % (self.arg,) + classname = CLASS_NAME[self.op] + return '_CFFI_OP(_CFFI_OP_%s, %s)' % (classname, self.arg) + + def as_python_bytes(self): + if self.op is None and self.arg.isdigit(): + value = int(self.arg) # non-negative: '-' not in self.arg + if value >= 2**31: + raise OverflowError("cannot emit %r: limited to 2**31-1" + % (self.arg,)) + return format_four_bytes(value) + if isinstance(self.arg, str): + raise VerificationError("cannot emit to Python: %r" % (self.arg,)) + return format_four_bytes((self.arg << 8) | self.op) + + def __str__(self): + classname = CLASS_NAME.get(self.op, self.op) + return '(%s %s)' % (classname, self.arg) + +def format_four_bytes(num): + return '\\x%02X\\x%02X\\x%02X\\x%02X' % ( + (num >> 24) & 0xFF, + (num >> 16) & 0xFF, + (num >> 8) & 0xFF, + (num ) & 0xFF) + +OP_PRIMITIVE = 1 +OP_POINTER = 3 +OP_ARRAY = 5 +OP_OPEN_ARRAY = 7 +OP_STRUCT_UNION = 9 +OP_ENUM = 11 +OP_FUNCTION = 13 +OP_FUNCTION_END = 15 +OP_NOOP = 17 +OP_BITFIELD = 19 +OP_TYPENAME = 21 +OP_CPYTHON_BLTN_V = 23 # varargs +OP_CPYTHON_BLTN_N = 25 # noargs +OP_CPYTHON_BLTN_O = 27 # O (i.e. a single arg) +OP_CONSTANT = 29 +OP_CONSTANT_INT = 31 +OP_GLOBAL_VAR = 33 +OP_DLOPEN_FUNC = 35 +OP_DLOPEN_CONST = 37 +OP_GLOBAL_VAR_F = 39 +OP_EXTERN_PYTHON = 41 + +PRIM_VOID = 0 +PRIM_BOOL = 1 +PRIM_CHAR = 2 +PRIM_SCHAR = 3 +PRIM_UCHAR = 4 +PRIM_SHORT = 5 +PRIM_USHORT = 6 +PRIM_INT = 7 +PRIM_UINT = 8 +PRIM_LONG = 9 +PRIM_ULONG = 10 +PRIM_LONGLONG = 11 +PRIM_ULONGLONG = 12 +PRIM_FLOAT = 13 +PRIM_DOUBLE = 14 +PRIM_LONGDOUBLE = 15 + +PRIM_WCHAR = 16 +PRIM_INT8 = 17 +PRIM_UINT8 = 18 +PRIM_INT16 = 19 +PRIM_UINT16 = 20 +PRIM_INT32 = 21 +PRIM_UINT32 = 22 +PRIM_INT64 = 23 +PRIM_UINT64 = 24 +PRIM_INTPTR = 25 +PRIM_UINTPTR = 26 +PRIM_PTRDIFF = 27 +PRIM_SIZE = 28 +PRIM_SSIZE = 29 +PRIM_INT_LEAST8 = 30 +PRIM_UINT_LEAST8 = 31 +PRIM_INT_LEAST16 = 32 +PRIM_UINT_LEAST16 = 33 +PRIM_INT_LEAST32 = 34 +PRIM_UINT_LEAST32 = 35 +PRIM_INT_LEAST64 = 36 +PRIM_UINT_LEAST64 = 37 +PRIM_INT_FAST8 = 38 +PRIM_UINT_FAST8 = 39 +PRIM_INT_FAST16 = 40 +PRIM_UINT_FAST16 = 41 +PRIM_INT_FAST32 = 42 +PRIM_UINT_FAST32 = 43 +PRIM_INT_FAST64 = 44 +PRIM_UINT_FAST64 = 45 +PRIM_INTMAX = 46 +PRIM_UINTMAX = 47 +PRIM_FLOATCOMPLEX = 48 +PRIM_DOUBLECOMPLEX = 49 +PRIM_CHAR16 = 50 +PRIM_CHAR32 = 51 + +_NUM_PRIM = 52 +_UNKNOWN_PRIM = -1 +_UNKNOWN_FLOAT_PRIM = -2 +_UNKNOWN_LONG_DOUBLE = -3 + +_IO_FILE_STRUCT = -1 + +PRIMITIVE_TO_INDEX = { + 'char': PRIM_CHAR, + 'short': PRIM_SHORT, + 'int': PRIM_INT, + 'long': PRIM_LONG, + 'long long': PRIM_LONGLONG, + 'signed char': PRIM_SCHAR, + 'unsigned char': PRIM_UCHAR, + 'unsigned short': PRIM_USHORT, + 'unsigned int': PRIM_UINT, + 'unsigned long': PRIM_ULONG, + 'unsigned long long': PRIM_ULONGLONG, + 'float': PRIM_FLOAT, + 'double': PRIM_DOUBLE, + 'long double': PRIM_LONGDOUBLE, + 'float _Complex': PRIM_FLOATCOMPLEX, + 'double _Complex': PRIM_DOUBLECOMPLEX, + '_Bool': PRIM_BOOL, + 'wchar_t': PRIM_WCHAR, + 'char16_t': PRIM_CHAR16, + 'char32_t': PRIM_CHAR32, + 'int8_t': PRIM_INT8, + 'uint8_t': PRIM_UINT8, + 'int16_t': PRIM_INT16, + 'uint16_t': PRIM_UINT16, + 'int32_t': PRIM_INT32, + 'uint32_t': PRIM_UINT32, + 'int64_t': PRIM_INT64, + 'uint64_t': PRIM_UINT64, + 'intptr_t': PRIM_INTPTR, + 'uintptr_t': PRIM_UINTPTR, + 'ptrdiff_t': PRIM_PTRDIFF, + 'size_t': PRIM_SIZE, + 'ssize_t': PRIM_SSIZE, + 'int_least8_t': PRIM_INT_LEAST8, + 'uint_least8_t': PRIM_UINT_LEAST8, + 'int_least16_t': PRIM_INT_LEAST16, + 'uint_least16_t': PRIM_UINT_LEAST16, + 'int_least32_t': PRIM_INT_LEAST32, + 'uint_least32_t': PRIM_UINT_LEAST32, + 'int_least64_t': PRIM_INT_LEAST64, + 'uint_least64_t': PRIM_UINT_LEAST64, + 'int_fast8_t': PRIM_INT_FAST8, + 'uint_fast8_t': PRIM_UINT_FAST8, + 'int_fast16_t': PRIM_INT_FAST16, + 'uint_fast16_t': PRIM_UINT_FAST16, + 'int_fast32_t': PRIM_INT_FAST32, + 'uint_fast32_t': PRIM_UINT_FAST32, + 'int_fast64_t': PRIM_INT_FAST64, + 'uint_fast64_t': PRIM_UINT_FAST64, + 'intmax_t': PRIM_INTMAX, + 'uintmax_t': PRIM_UINTMAX, + } + +F_UNION = 0x01 +F_CHECK_FIELDS = 0x02 +F_PACKED = 0x04 +F_EXTERNAL = 0x08 +F_OPAQUE = 0x10 + +G_FLAGS = dict([('_CFFI_' + _key, globals()[_key]) + for _key in ['F_UNION', 'F_CHECK_FIELDS', 'F_PACKED', + 'F_EXTERNAL', 'F_OPAQUE']]) + +CLASS_NAME = {} +for _name, _value in list(globals().items()): + if _name.startswith('OP_') and isinstance(_value, int): + CLASS_NAME[_value] = _name[3:] diff --git a/.venv/Lib/site-packages/cffi/commontypes.py b/.venv/Lib/site-packages/cffi/commontypes.py new file mode 100644 index 00000000..8ec97c75 --- /dev/null +++ b/.venv/Lib/site-packages/cffi/commontypes.py @@ -0,0 +1,80 @@ +import sys +from . import model +from .error import FFIError + + +COMMON_TYPES = {} + +try: + # fetch "bool" and all simple Windows types + from _cffi_backend import _get_common_types + _get_common_types(COMMON_TYPES) +except ImportError: + pass + +COMMON_TYPES['FILE'] = model.unknown_type('FILE', '_IO_FILE') +COMMON_TYPES['bool'] = '_Bool' # in case we got ImportError above + +for _type in model.PrimitiveType.ALL_PRIMITIVE_TYPES: + if _type.endswith('_t'): + COMMON_TYPES[_type] = _type +del _type + +_CACHE = {} + +def resolve_common_type(parser, commontype): + try: + return _CACHE[commontype] + except KeyError: + cdecl = COMMON_TYPES.get(commontype, commontype) + if not isinstance(cdecl, str): + result, quals = cdecl, 0 # cdecl is already a BaseType + elif cdecl in model.PrimitiveType.ALL_PRIMITIVE_TYPES: + result, quals = model.PrimitiveType(cdecl), 0 + elif cdecl == 'set-unicode-needed': + raise FFIError("The Windows type %r is only available after " + "you call ffi.set_unicode()" % (commontype,)) + else: + if commontype == cdecl: + raise FFIError( + "Unsupported type: %r. Please look at " + "http://cffi.readthedocs.io/en/latest/cdef.html#ffi-cdef-limitations " + "and file an issue if you think this type should really " + "be supported." % (commontype,)) + result, quals = parser.parse_type_and_quals(cdecl) # recursive + + assert isinstance(result, model.BaseTypeByIdentity) + _CACHE[commontype] = result, quals + return result, quals + + +# ____________________________________________________________ +# extra types for Windows (most of them are in commontypes.c) + + +def win_common_types(): + return { + "UNICODE_STRING": model.StructType( + "_UNICODE_STRING", + ["Length", + "MaximumLength", + "Buffer"], + [model.PrimitiveType("unsigned short"), + model.PrimitiveType("unsigned short"), + model.PointerType(model.PrimitiveType("wchar_t"))], + [-1, -1, -1]), + "PUNICODE_STRING": "UNICODE_STRING *", + "PCUNICODE_STRING": "const UNICODE_STRING *", + + "TBYTE": "set-unicode-needed", + "TCHAR": "set-unicode-needed", + "LPCTSTR": "set-unicode-needed", + "PCTSTR": "set-unicode-needed", + "LPTSTR": "set-unicode-needed", + "PTSTR": "set-unicode-needed", + "PTBYTE": "set-unicode-needed", + "PTCHAR": "set-unicode-needed", + } + +if sys.platform == 'win32': + COMMON_TYPES.update(win_common_types()) diff --git a/.venv/Lib/site-packages/cffi/cparser.py b/.venv/Lib/site-packages/cffi/cparser.py new file mode 100644 index 00000000..74830e91 --- /dev/null +++ b/.venv/Lib/site-packages/cffi/cparser.py @@ -0,0 +1,1006 @@ +from . import model +from .commontypes import COMMON_TYPES, resolve_common_type +from .error import FFIError, CDefError +try: + from . import _pycparser as pycparser +except ImportError: + import pycparser +import weakref, re, sys + +try: + if sys.version_info < (3,): + import thread as _thread + else: + import _thread + lock = _thread.allocate_lock() +except ImportError: + lock = None + +def _workaround_for_static_import_finders(): + # Issue #392: packaging tools like cx_Freeze can not find these + # because pycparser uses exec dynamic import. This is an obscure + # workaround. This function is never called. + import pycparser.yacctab + import pycparser.lextab + +CDEF_SOURCE_STRING = "" +_r_comment = re.compile(r"/\*.*?\*/|//([^\n\\]|\\.)*?$", + re.DOTALL | re.MULTILINE) +_r_define = re.compile(r"^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)" + r"\b((?:[^\n\\]|\\.)*?)$", + re.DOTALL | re.MULTILINE) +_r_line_directive = re.compile(r"^[ \t]*#[ \t]*(?:line|\d+)\b.*$", re.MULTILINE) +_r_partial_enum = re.compile(r"=\s*\.\.\.\s*[,}]|\.\.\.\s*\}") +_r_enum_dotdotdot = re.compile(r"__dotdotdot\d+__$") +_r_partial_array = re.compile(r"\[\s*\.\.\.\s*\]") +_r_words = re.compile(r"\w+|\S") +_parser_cache = None +_r_int_literal = re.compile(r"-?0?x?[0-9a-f]+[lu]*$", re.IGNORECASE) +_r_stdcall1 = re.compile(r"\b(__stdcall|WINAPI)\b") +_r_stdcall2 = re.compile(r"[(]\s*(__stdcall|WINAPI)\b") +_r_cdecl = re.compile(r"\b__cdecl\b") +_r_extern_python = re.compile(r'\bextern\s*"' + r'(Python|Python\s*\+\s*C|C\s*\+\s*Python)"\s*.') +_r_star_const_space = re.compile( # matches "* const " + r"[*]\s*((const|volatile|restrict)\b\s*)+") +_r_int_dotdotdot = re.compile(r"(\b(int|long|short|signed|unsigned|char)\s*)+" + r"\.\.\.") +_r_float_dotdotdot = re.compile(r"\b(double|float)\s*\.\.\.") + +def _get_parser(): + global _parser_cache + if _parser_cache is None: + _parser_cache = pycparser.CParser() + return _parser_cache + +def _workaround_for_old_pycparser(csource): + # Workaround for a pycparser issue (fixed between pycparser 2.10 and + # 2.14): "char*const***" gives us a wrong syntax tree, the same as + # for "char***(*const)". This means we can't tell the difference + # afterwards. But "char(*const(***))" gives us the right syntax + # tree. The issue only occurs if there are several stars in + # sequence with no parenthesis inbetween, just possibly qualifiers. + # Attempt to fix it by adding some parentheses in the source: each + # time we see "* const" or "* const *", we add an opening + # parenthesis before each star---the hard part is figuring out where + # to close them. + parts = [] + while True: + match = _r_star_const_space.search(csource) + if not match: + break + #print repr(''.join(parts)+csource), '=>', + parts.append(csource[:match.start()]) + parts.append('('); closing = ')' + parts.append(match.group()) # e.g. "* const " + endpos = match.end() + if csource.startswith('*', endpos): + parts.append('('); closing += ')' + level = 0 + i = endpos + while i < len(csource): + c = csource[i] + if c == '(': + level += 1 + elif c == ')': + if level == 0: + break + level -= 1 + elif c in ',;=': + if level == 0: + break + i += 1 + csource = csource[endpos:i] + closing + csource[i:] + #print repr(''.join(parts)+csource) + parts.append(csource) + return ''.join(parts) + +def _preprocess_extern_python(csource): + # input: `extern "Python" int foo(int);` or + # `extern "Python" { int foo(int); }` + # output: + # void __cffi_extern_python_start; + # int foo(int); + # void __cffi_extern_python_stop; + # + # input: `extern "Python+C" int foo(int);` + # output: + # void __cffi_extern_python_plus_c_start; + # int foo(int); + # void __cffi_extern_python_stop; + parts = [] + while True: + match = _r_extern_python.search(csource) + if not match: + break + endpos = match.end() - 1 + #print + #print ''.join(parts)+csource + #print '=>' + parts.append(csource[:match.start()]) + if 'C' in match.group(1): + parts.append('void __cffi_extern_python_plus_c_start; ') + else: + parts.append('void __cffi_extern_python_start; ') + if csource[endpos] == '{': + # grouping variant + closing = csource.find('}', endpos) + if closing < 0: + raise CDefError("'extern \"Python\" {': no '}' found") + if csource.find('{', endpos + 1, closing) >= 0: + raise NotImplementedError("cannot use { } inside a block " + "'extern \"Python\" { ... }'") + parts.append(csource[endpos+1:closing]) + csource = csource[closing+1:] + else: + # non-grouping variant + semicolon = csource.find(';', endpos) + if semicolon < 0: + raise CDefError("'extern \"Python\": no ';' found") + parts.append(csource[endpos:semicolon+1]) + csource = csource[semicolon+1:] + parts.append(' void __cffi_extern_python_stop;') + #print ''.join(parts)+csource + #print + parts.append(csource) + return ''.join(parts) + +def _warn_for_string_literal(csource): + if '"' not in csource: + return + for line in csource.splitlines(): + if '"' in line and not line.lstrip().startswith('#'): + import warnings + warnings.warn("String literal found in cdef() or type source. " + "String literals are ignored here, but you should " + "remove them anyway because some character sequences " + "confuse pre-parsing.") + break + +def _warn_for_non_extern_non_static_global_variable(decl): + if not decl.storage: + import warnings + warnings.warn("Global variable '%s' in cdef(): for consistency " + "with C it should have a storage class specifier " + "(usually 'extern')" % (decl.name,)) + +def _remove_line_directives(csource): + # _r_line_directive matches whole lines, without the final \n, if they + # start with '#line' with some spacing allowed, or '#NUMBER'. This + # function stores them away and replaces them with exactly the string + # '#line@N', where N is the index in the list 'line_directives'. + line_directives = [] + def replace(m): + i = len(line_directives) + line_directives.append(m.group()) + return '#line@%d' % i + csource = _r_line_directive.sub(replace, csource) + return csource, line_directives + +def _put_back_line_directives(csource, line_directives): + def replace(m): + s = m.group() + if not s.startswith('#line@'): + raise AssertionError("unexpected #line directive " + "(should have been processed and removed") + return line_directives[int(s[6:])] + return _r_line_directive.sub(replace, csource) + +def _preprocess(csource): + # First, remove the lines of the form '#line N "filename"' because + # the "filename" part could confuse the rest + csource, line_directives = _remove_line_directives(csource) + # Remove comments. NOTE: this only work because the cdef() section + # should not contain any string literals (except in line directives)! + def replace_keeping_newlines(m): + return ' ' + m.group().count('\n') * '\n' + csource = _r_comment.sub(replace_keeping_newlines, csource) + # Remove the "#define FOO x" lines + macros = {} + for match in _r_define.finditer(csource): + macroname, macrovalue = match.groups() + macrovalue = macrovalue.replace('\\\n', '').strip() + macros[macroname] = macrovalue + csource = _r_define.sub('', csource) + # + if pycparser.__version__ < '2.14': + csource = _workaround_for_old_pycparser(csource) + # + # BIG HACK: replace WINAPI or __stdcall with "volatile const". + # It doesn't make sense for the return type of a function to be + # "volatile volatile const", so we abuse it to detect __stdcall... + # Hack number 2 is that "int(volatile *fptr)();" is not valid C + # syntax, so we place the "volatile" before the opening parenthesis. + csource = _r_stdcall2.sub(' volatile volatile const(', csource) + csource = _r_stdcall1.sub(' volatile volatile const ', csource) + csource = _r_cdecl.sub(' ', csource) + # + # Replace `extern "Python"` with start/end markers + csource = _preprocess_extern_python(csource) + # + # Now there should not be any string literal left; warn if we get one + _warn_for_string_literal(csource) + # + # Replace "[...]" with "[__dotdotdotarray__]" + csource = _r_partial_array.sub('[__dotdotdotarray__]', csource) + # + # Replace "...}" with "__dotdotdotNUM__}". This construction should + # occur only at the end of enums; at the end of structs we have "...;}" + # and at the end of vararg functions "...);". Also replace "=...[,}]" + # with ",__dotdotdotNUM__[,}]": this occurs in the enums too, when + # giving an unknown value. + matches = list(_r_partial_enum.finditer(csource)) + for number, match in enumerate(reversed(matches)): + p = match.start() + if csource[p] == '=': + p2 = csource.find('...', p, match.end()) + assert p2 > p + csource = '%s,__dotdotdot%d__ %s' % (csource[:p], number, + csource[p2+3:]) + else: + assert csource[p:p+3] == '...' + csource = '%s __dotdotdot%d__ %s' % (csource[:p], number, + csource[p+3:]) + # Replace "int ..." or "unsigned long int..." with "__dotdotdotint__" + csource = _r_int_dotdotdot.sub(' __dotdotdotint__ ', csource) + # Replace "float ..." or "double..." with "__dotdotdotfloat__" + csource = _r_float_dotdotdot.sub(' __dotdotdotfloat__ ', csource) + # Replace all remaining "..." with the same name, "__dotdotdot__", + # which is declared with a typedef for the purpose of C parsing. + csource = csource.replace('...', ' __dotdotdot__ ') + # Finally, put back the line directives + csource = _put_back_line_directives(csource, line_directives) + return csource, macros + +def _common_type_names(csource): + # Look in the source for what looks like usages of types from the + # list of common types. A "usage" is approximated here as the + # appearance of the word, minus a "definition" of the type, which + # is the last word in a "typedef" statement. Approximative only + # but should be fine for all the common types. + look_for_words = set(COMMON_TYPES) + look_for_words.add(';') + look_for_words.add(',') + look_for_words.add('(') + look_for_words.add(')') + look_for_words.add('typedef') + words_used = set() + is_typedef = False + paren = 0 + previous_word = '' + for word in _r_words.findall(csource): + if word in look_for_words: + if word == ';': + if is_typedef: + words_used.discard(previous_word) + look_for_words.discard(previous_word) + is_typedef = False + elif word == 'typedef': + is_typedef = True + paren = 0 + elif word == '(': + paren += 1 + elif word == ')': + paren -= 1 + elif word == ',': + if is_typedef and paren == 0: + words_used.discard(previous_word) + look_for_words.discard(previous_word) + else: # word in COMMON_TYPES + words_used.add(word) + previous_word = word + return words_used + + +class Parser(object): + + def __init__(self): + self._declarations = {} + self._included_declarations = set() + self._anonymous_counter = 0 + self._structnode2type = weakref.WeakKeyDictionary() + self._options = {} + self._int_constants = {} + self._recomplete = [] + self._uses_new_feature = None + + def _parse(self, csource): + csource, macros = _preprocess(csource) + # XXX: for more efficiency we would need to poke into the + # internals of CParser... the following registers the + # typedefs, because their presence or absence influences the + # parsing itself (but what they are typedef'ed to plays no role) + ctn = _common_type_names(csource) + typenames = [] + for name in sorted(self._declarations): + if name.startswith('typedef '): + name = name[8:] + typenames.append(name) + ctn.discard(name) + typenames += sorted(ctn) + # + csourcelines = [] + csourcelines.append('# 1 ""') + for typename in typenames: + csourcelines.append('typedef int %s;' % typename) + csourcelines.append('typedef int __dotdotdotint__, __dotdotdotfloat__,' + ' __dotdotdot__;') + # this forces pycparser to consider the following in the file + # called from line 1 + csourcelines.append('# 1 "%s"' % (CDEF_SOURCE_STRING,)) + csourcelines.append(csource) + fullcsource = '\n'.join(csourcelines) + if lock is not None: + lock.acquire() # pycparser is not thread-safe... + try: + ast = _get_parser().parse(fullcsource) + except pycparser.c_parser.ParseError as e: + self.convert_pycparser_error(e, csource) + finally: + if lock is not None: + lock.release() + # csource will be used to find buggy source text + return ast, macros, csource + + def _convert_pycparser_error(self, e, csource): + # xxx look for ":NUM:" at the start of str(e) + # and interpret that as a line number. This will not work if + # the user gives explicit ``# NUM "FILE"`` directives. + line = None + msg = str(e) + match = re.match(r"%s:(\d+):" % (CDEF_SOURCE_STRING,), msg) + if match: + linenum = int(match.group(1), 10) + csourcelines = csource.splitlines() + if 1 <= linenum <= len(csourcelines): + line = csourcelines[linenum-1] + return line + + def convert_pycparser_error(self, e, csource): + line = self._convert_pycparser_error(e, csource) + + msg = str(e) + if line: + msg = 'cannot parse "%s"\n%s' % (line.strip(), msg) + else: + msg = 'parse error\n%s' % (msg,) + raise CDefError(msg) + + def parse(self, csource, override=False, packed=False, pack=None, + dllexport=False): + if packed: + if packed != True: + raise ValueError("'packed' should be False or True; use " + "'pack' to give another value") + if pack: + raise ValueError("cannot give both 'pack' and 'packed'") + pack = 1 + elif pack: + if pack & (pack - 1): + raise ValueError("'pack' must be a power of two, not %r" % + (pack,)) + else: + pack = 0 + prev_options = self._options + try: + self._options = {'override': override, + 'packed': pack, + 'dllexport': dllexport} + self._internal_parse(csource) + finally: + self._options = prev_options + + def _internal_parse(self, csource): + ast, macros, csource = self._parse(csource) + # add the macros + self._process_macros(macros) + # find the first "__dotdotdot__" and use that as a separator + # between the repeated typedefs and the real csource + iterator = iter(ast.ext) + for decl in iterator: + if decl.name == '__dotdotdot__': + break + else: + assert 0 + current_decl = None + # + try: + self._inside_extern_python = '__cffi_extern_python_stop' + for decl in iterator: + current_decl = decl + if isinstance(decl, pycparser.c_ast.Decl): + self._parse_decl(decl) + elif isinstance(decl, pycparser.c_ast.Typedef): + if not decl.name: + raise CDefError("typedef does not declare any name", + decl) + quals = 0 + if (isinstance(decl.type.type, pycparser.c_ast.IdentifierType) and + decl.type.type.names[-1].startswith('__dotdotdot')): + realtype = self._get_unknown_type(decl) + elif (isinstance(decl.type, pycparser.c_ast.PtrDecl) and + isinstance(decl.type.type, pycparser.c_ast.TypeDecl) and + isinstance(decl.type.type.type, + pycparser.c_ast.IdentifierType) and + decl.type.type.type.names[-1].startswith('__dotdotdot')): + realtype = self._get_unknown_ptr_type(decl) + else: + realtype, quals = self._get_type_and_quals( + decl.type, name=decl.name, partial_length_ok=True, + typedef_example="*(%s *)0" % (decl.name,)) + self._declare('typedef ' + decl.name, realtype, quals=quals) + elif decl.__class__.__name__ == 'Pragma': + pass # skip pragma, only in pycparser 2.15 + else: + raise CDefError("unexpected <%s>: this construct is valid " + "C but not valid in cdef()" % + decl.__class__.__name__, decl) + except CDefError as e: + if len(e.args) == 1: + e.args = e.args + (current_decl,) + raise + except FFIError as e: + msg = self._convert_pycparser_error(e, csource) + if msg: + e.args = (e.args[0] + "\n *** Err: %s" % msg,) + raise + + def _add_constants(self, key, val): + if key in self._int_constants: + if self._int_constants[key] == val: + return # ignore identical double declarations + raise FFIError( + "multiple declarations of constant: %s" % (key,)) + self._int_constants[key] = val + + def _add_integer_constant(self, name, int_str): + int_str = int_str.lower().rstrip("ul") + neg = int_str.startswith('-') + if neg: + int_str = int_str[1:] + # "010" is not valid oct in py3 + if (int_str.startswith("0") and int_str != '0' + and not int_str.startswith("0x")): + int_str = "0o" + int_str[1:] + pyvalue = int(int_str, 0) + if neg: + pyvalue = -pyvalue + self._add_constants(name, pyvalue) + self._declare('macro ' + name, pyvalue) + + def _process_macros(self, macros): + for key, value in macros.items(): + value = value.strip() + if _r_int_literal.match(value): + self._add_integer_constant(key, value) + elif value == '...': + self._declare('macro ' + key, value) + else: + raise CDefError( + 'only supports one of the following syntax:\n' + ' #define %s ... (literally dot-dot-dot)\n' + ' #define %s NUMBER (with NUMBER an integer' + ' constant, decimal/hex/octal)\n' + 'got:\n' + ' #define %s %s' + % (key, key, key, value)) + + def _declare_function(self, tp, quals, decl): + tp = self._get_type_pointer(tp, quals) + if self._options.get('dllexport'): + tag = 'dllexport_python ' + elif self._inside_extern_python == '__cffi_extern_python_start': + tag = 'extern_python ' + elif self._inside_extern_python == '__cffi_extern_python_plus_c_start': + tag = 'extern_python_plus_c ' + else: + tag = 'function ' + self._declare(tag + decl.name, tp) + + def _parse_decl(self, decl): + node = decl.type + if isinstance(node, pycparser.c_ast.FuncDecl): + tp, quals = self._get_type_and_quals(node, name=decl.name) + assert isinstance(tp, model.RawFunctionType) + self._declare_function(tp, quals, decl) + else: + if isinstance(node, pycparser.c_ast.Struct): + self._get_struct_union_enum_type('struct', node) + elif isinstance(node, pycparser.c_ast.Union): + self._get_struct_union_enum_type('union', node) + elif isinstance(node, pycparser.c_ast.Enum): + self._get_struct_union_enum_type('enum', node) + elif not decl.name: + raise CDefError("construct does not declare any variable", + decl) + # + if decl.name: + tp, quals = self._get_type_and_quals(node, + partial_length_ok=True) + if tp.is_raw_function: + self._declare_function(tp, quals, decl) + elif (tp.is_integer_type() and + hasattr(decl, 'init') and + hasattr(decl.init, 'value') and + _r_int_literal.match(decl.init.value)): + self._add_integer_constant(decl.name, decl.init.value) + elif (tp.is_integer_type() and + isinstance(decl.init, pycparser.c_ast.UnaryOp) and + decl.init.op == '-' and + hasattr(decl.init.expr, 'value') and + _r_int_literal.match(decl.init.expr.value)): + self._add_integer_constant(decl.name, + '-' + decl.init.expr.value) + elif (tp is model.void_type and + decl.name.startswith('__cffi_extern_python_')): + # hack: `extern "Python"` in the C source is replaced + # with "void __cffi_extern_python_start;" and + # "void __cffi_extern_python_stop;" + self._inside_extern_python = decl.name + else: + if self._inside_extern_python !='__cffi_extern_python_stop': + raise CDefError( + "cannot declare constants or " + "variables with 'extern \"Python\"'") + if (quals & model.Q_CONST) and not tp.is_array_type: + self._declare('constant ' + decl.name, tp, quals=quals) + else: + _warn_for_non_extern_non_static_global_variable(decl) + self._declare('variable ' + decl.name, tp, quals=quals) + + def parse_type(self, cdecl): + return self.parse_type_and_quals(cdecl)[0] + + def parse_type_and_quals(self, cdecl): + ast, macros = self._parse('void __dummy(\n%s\n);' % cdecl)[:2] + assert not macros + exprnode = ast.ext[-1].type.args.params[0] + if isinstance(exprnode, pycparser.c_ast.ID): + raise CDefError("unknown identifier '%s'" % (exprnode.name,)) + return self._get_type_and_quals(exprnode.type) + + def _declare(self, name, obj, included=False, quals=0): + if name in self._declarations: + prevobj, prevquals = self._declarations[name] + if prevobj is obj and prevquals == quals: + return + if not self._options.get('override'): + raise FFIError( + "multiple declarations of %s (for interactive usage, " + "try cdef(xx, override=True))" % (name,)) + assert '__dotdotdot__' not in name.split() + self._declarations[name] = (obj, quals) + if included: + self._included_declarations.add(obj) + + def _extract_quals(self, type): + quals = 0 + if isinstance(type, (pycparser.c_ast.TypeDecl, + pycparser.c_ast.PtrDecl)): + if 'const' in type.quals: + quals |= model.Q_CONST + if 'volatile' in type.quals: + quals |= model.Q_VOLATILE + if 'restrict' in type.quals: + quals |= model.Q_RESTRICT + return quals + + def _get_type_pointer(self, type, quals, declname=None): + if isinstance(type, model.RawFunctionType): + return type.as_function_pointer() + if (isinstance(type, model.StructOrUnionOrEnum) and + type.name.startswith('$') and type.name[1:].isdigit() and + type.forcename is None and declname is not None): + return model.NamedPointerType(type, declname, quals) + return model.PointerType(type, quals) + + def _get_type_and_quals(self, typenode, name=None, partial_length_ok=False, + typedef_example=None): + # first, dereference typedefs, if we have it already parsed, we're good + if (isinstance(typenode, pycparser.c_ast.TypeDecl) and + isinstance(typenode.type, pycparser.c_ast.IdentifierType) and + len(typenode.type.names) == 1 and + ('typedef ' + typenode.type.names[0]) in self._declarations): + tp, quals = self._declarations['typedef ' + typenode.type.names[0]] + quals |= self._extract_quals(typenode) + return tp, quals + # + if isinstance(typenode, pycparser.c_ast.ArrayDecl): + # array type + if typenode.dim is None: + length = None + else: + length = self._parse_constant( + typenode.dim, partial_length_ok=partial_length_ok) + # a hack: in 'typedef int foo_t[...][...];', don't use '...' as + # the length but use directly the C expression that would be + # generated by recompiler.py. This lets the typedef be used in + # many more places within recompiler.py + if typedef_example is not None: + if length == '...': + length = '_cffi_array_len(%s)' % (typedef_example,) + typedef_example = "*" + typedef_example + # + tp, quals = self._get_type_and_quals(typenode.type, + partial_length_ok=partial_length_ok, + typedef_example=typedef_example) + return model.ArrayType(tp, length), quals + # + if isinstance(typenode, pycparser.c_ast.PtrDecl): + # pointer type + itemtype, itemquals = self._get_type_and_quals(typenode.type) + tp = self._get_type_pointer(itemtype, itemquals, declname=name) + quals = self._extract_quals(typenode) + return tp, quals + # + if isinstance(typenode, pycparser.c_ast.TypeDecl): + quals = self._extract_quals(typenode) + type = typenode.type + if isinstance(type, pycparser.c_ast.IdentifierType): + # assume a primitive type. get it from .names, but reduce + # synonyms to a single chosen combination + names = list(type.names) + if names != ['signed', 'char']: # keep this unmodified + prefixes = {} + while names: + name = names[0] + if name in ('short', 'long', 'signed', 'unsigned'): + prefixes[name] = prefixes.get(name, 0) + 1 + del names[0] + else: + break + # ignore the 'signed' prefix below, and reorder the others + newnames = [] + for prefix in ('unsigned', 'short', 'long'): + for i in range(prefixes.get(prefix, 0)): + newnames.append(prefix) + if not names: + names = ['int'] # implicitly + if names == ['int']: # but kill it if 'short' or 'long' + if 'short' in prefixes or 'long' in prefixes: + names = [] + names = newnames + names + ident = ' '.join(names) + if ident == 'void': + return model.void_type, quals + if ident == '__dotdotdot__': + raise FFIError(':%d: bad usage of "..."' % + typenode.coord.line) + tp0, quals0 = resolve_common_type(self, ident) + return tp0, (quals | quals0) + # + if isinstance(type, pycparser.c_ast.Struct): + # 'struct foobar' + tp = self._get_struct_union_enum_type('struct', type, name) + return tp, quals + # + if isinstance(type, pycparser.c_ast.Union): + # 'union foobar' + tp = self._get_struct_union_enum_type('union', type, name) + return tp, quals + # + if isinstance(type, pycparser.c_ast.Enum): + # 'enum foobar' + tp = self._get_struct_union_enum_type('enum', type, name) + return tp, quals + # + if isinstance(typenode, pycparser.c_ast.FuncDecl): + # a function type + return self._parse_function_type(typenode, name), 0 + # + # nested anonymous structs or unions end up here + if isinstance(typenode, pycparser.c_ast.Struct): + return self._get_struct_union_enum_type('struct', typenode, name, + nested=True), 0 + if isinstance(typenode, pycparser.c_ast.Union): + return self._get_struct_union_enum_type('union', typenode, name, + nested=True), 0 + # + raise FFIError(":%d: bad or unsupported type declaration" % + typenode.coord.line) + + def _parse_function_type(self, typenode, funcname=None): + params = list(getattr(typenode.args, 'params', [])) + for i, arg in enumerate(params): + if not hasattr(arg, 'type'): + raise CDefError("%s arg %d: unknown type '%s'" + " (if you meant to use the old C syntax of giving" + " untyped arguments, it is not supported)" + % (funcname or 'in expression', i + 1, + getattr(arg, 'name', '?'))) + ellipsis = ( + len(params) > 0 and + isinstance(params[-1].type, pycparser.c_ast.TypeDecl) and + isinstance(params[-1].type.type, + pycparser.c_ast.IdentifierType) and + params[-1].type.type.names == ['__dotdotdot__']) + if ellipsis: + params.pop() + if not params: + raise CDefError( + "%s: a function with only '(...)' as argument" + " is not correct C" % (funcname or 'in expression')) + args = [self._as_func_arg(*self._get_type_and_quals(argdeclnode.type)) + for argdeclnode in params] + if not ellipsis and args == [model.void_type]: + args = [] + result, quals = self._get_type_and_quals(typenode.type) + # the 'quals' on the result type are ignored. HACK: we absure them + # to detect __stdcall functions: we textually replace "__stdcall" + # with "volatile volatile const" above. + abi = None + if hasattr(typenode.type, 'quals'): # else, probable syntax error anyway + if typenode.type.quals[-3:] == ['volatile', 'volatile', 'const']: + abi = '__stdcall' + return model.RawFunctionType(tuple(args), result, ellipsis, abi) + + def _as_func_arg(self, type, quals): + if isinstance(type, model.ArrayType): + return model.PointerType(type.item, quals) + elif isinstance(type, model.RawFunctionType): + return type.as_function_pointer() + else: + return type + + def _get_struct_union_enum_type(self, kind, type, name=None, nested=False): + # First, a level of caching on the exact 'type' node of the AST. + # This is obscure, but needed because pycparser "unrolls" declarations + # such as "typedef struct { } foo_t, *foo_p" and we end up with + # an AST that is not a tree, but a DAG, with the "type" node of the + # two branches foo_t and foo_p of the trees being the same node. + # It's a bit silly but detecting "DAG-ness" in the AST tree seems + # to be the only way to distinguish this case from two independent + # structs. See test_struct_with_two_usages. + try: + return self._structnode2type[type] + except KeyError: + pass + # + # Note that this must handle parsing "struct foo" any number of + # times and always return the same StructType object. Additionally, + # one of these times (not necessarily the first), the fields of + # the struct can be specified with "struct foo { ...fields... }". + # If no name is given, then we have to create a new anonymous struct + # with no caching; in this case, the fields are either specified + # right now or never. + # + force_name = name + name = type.name + # + # get the type or create it if needed + if name is None: + # 'force_name' is used to guess a more readable name for + # anonymous structs, for the common case "typedef struct { } foo". + if force_name is not None: + explicit_name = '$%s' % force_name + else: + self._anonymous_counter += 1 + explicit_name = '$%d' % self._anonymous_counter + tp = None + else: + explicit_name = name + key = '%s %s' % (kind, name) + tp, _ = self._declarations.get(key, (None, None)) + # + if tp is None: + if kind == 'struct': + tp = model.StructType(explicit_name, None, None, None) + elif kind == 'union': + tp = model.UnionType(explicit_name, None, None, None) + elif kind == 'enum': + if explicit_name == '__dotdotdot__': + raise CDefError("Enums cannot be declared with ...") + tp = self._build_enum_type(explicit_name, type.values) + else: + raise AssertionError("kind = %r" % (kind,)) + if name is not None: + self._declare(key, tp) + else: + if kind == 'enum' and type.values is not None: + raise NotImplementedError( + "enum %s: the '{}' declaration should appear on the first " + "time the enum is mentioned, not later" % explicit_name) + if not tp.forcename: + tp.force_the_name(force_name) + if tp.forcename and '$' in tp.name: + self._declare('anonymous %s' % tp.forcename, tp) + # + self._structnode2type[type] = tp + # + # enums: done here + if kind == 'enum': + return tp + # + # is there a 'type.decls'? If yes, then this is the place in the + # C sources that declare the fields. If no, then just return the + # existing type, possibly still incomplete. + if type.decls is None: + return tp + # + if tp.fldnames is not None: + raise CDefError("duplicate declaration of struct %s" % name) + fldnames = [] + fldtypes = [] + fldbitsize = [] + fldquals = [] + for decl in type.decls: + if (isinstance(decl.type, pycparser.c_ast.IdentifierType) and + ''.join(decl.type.names) == '__dotdotdot__'): + # XXX pycparser is inconsistent: 'names' should be a list + # of strings, but is sometimes just one string. Use + # str.join() as a way to cope with both. + self._make_partial(tp, nested) + continue + if decl.bitsize is None: + bitsize = -1 + else: + bitsize = self._parse_constant(decl.bitsize) + self._partial_length = False + type, fqual = self._get_type_and_quals(decl.type, + partial_length_ok=True) + if self._partial_length: + self._make_partial(tp, nested) + if isinstance(type, model.StructType) and type.partial: + self._make_partial(tp, nested) + fldnames.append(decl.name or '') + fldtypes.append(type) + fldbitsize.append(bitsize) + fldquals.append(fqual) + tp.fldnames = tuple(fldnames) + tp.fldtypes = tuple(fldtypes) + tp.fldbitsize = tuple(fldbitsize) + tp.fldquals = tuple(fldquals) + if fldbitsize != [-1] * len(fldbitsize): + if isinstance(tp, model.StructType) and tp.partial: + raise NotImplementedError("%s: using both bitfields and '...;'" + % (tp,)) + tp.packed = self._options.get('packed') + if tp.completed: # must be re-completed: it is not opaque any more + tp.completed = 0 + self._recomplete.append(tp) + return tp + + def _make_partial(self, tp, nested): + if not isinstance(tp, model.StructOrUnion): + raise CDefError("%s cannot be partial" % (tp,)) + if not tp.has_c_name() and not nested: + raise NotImplementedError("%s is partial but has no C name" %(tp,)) + tp.partial = True + + def _parse_constant(self, exprnode, partial_length_ok=False): + # for now, limited to expressions that are an immediate number + # or positive/negative number + if isinstance(exprnode, pycparser.c_ast.Constant): + s = exprnode.value + if '0' <= s[0] <= '9': + s = s.rstrip('uUlL') + try: + if s.startswith('0'): + return int(s, 8) + else: + return int(s, 10) + except ValueError: + if len(s) > 1: + if s.lower()[0:2] == '0x': + return int(s, 16) + elif s.lower()[0:2] == '0b': + return int(s, 2) + raise CDefError("invalid constant %r" % (s,)) + elif s[0] == "'" and s[-1] == "'" and ( + len(s) == 3 or (len(s) == 4 and s[1] == "\\")): + return ord(s[-2]) + else: + raise CDefError("invalid constant %r" % (s,)) + # + if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and + exprnode.op == '+'): + return self._parse_constant(exprnode.expr) + # + if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and + exprnode.op == '-'): + return -self._parse_constant(exprnode.expr) + # load previously defined int constant + if (isinstance(exprnode, pycparser.c_ast.ID) and + exprnode.name in self._int_constants): + return self._int_constants[exprnode.name] + # + if (isinstance(exprnode, pycparser.c_ast.ID) and + exprnode.name == '__dotdotdotarray__'): + if partial_length_ok: + self._partial_length = True + return '...' + raise FFIError(":%d: unsupported '[...]' here, cannot derive " + "the actual array length in this context" + % exprnode.coord.line) + # + if isinstance(exprnode, pycparser.c_ast.BinaryOp): + left = self._parse_constant(exprnode.left) + right = self._parse_constant(exprnode.right) + if exprnode.op == '+': + return left + right + elif exprnode.op == '-': + return left - right + elif exprnode.op == '*': + return left * right + elif exprnode.op == '/': + return self._c_div(left, right) + elif exprnode.op == '%': + return left - self._c_div(left, right) * right + elif exprnode.op == '<<': + return left << right + elif exprnode.op == '>>': + return left >> right + elif exprnode.op == '&': + return left & right + elif exprnode.op == '|': + return left | right + elif exprnode.op == '^': + return left ^ right + # + raise FFIError(":%d: unsupported expression: expected a " + "simple numeric constant" % exprnode.coord.line) + + def _c_div(self, a, b): + result = a // b + if ((a < 0) ^ (b < 0)) and (a % b) != 0: + result += 1 + return result + + def _build_enum_type(self, explicit_name, decls): + if decls is not None: + partial = False + enumerators = [] + enumvalues = [] + nextenumvalue = 0 + for enum in decls.enumerators: + if _r_enum_dotdotdot.match(enum.name): + partial = True + continue + if enum.value is not None: + nextenumvalue = self._parse_constant(enum.value) + enumerators.append(enum.name) + enumvalues.append(nextenumvalue) + self._add_constants(enum.name, nextenumvalue) + nextenumvalue += 1 + enumerators = tuple(enumerators) + enumvalues = tuple(enumvalues) + tp = model.EnumType(explicit_name, enumerators, enumvalues) + tp.partial = partial + else: # opaque enum + tp = model.EnumType(explicit_name, (), ()) + return tp + + def include(self, other): + for name, (tp, quals) in other._declarations.items(): + if name.startswith('anonymous $enum_$'): + continue # fix for test_anonymous_enum_include + kind = name.split(' ', 1)[0] + if kind in ('struct', 'union', 'enum', 'anonymous', 'typedef'): + self._declare(name, tp, included=True, quals=quals) + for k, v in other._int_constants.items(): + self._add_constants(k, v) + + def _get_unknown_type(self, decl): + typenames = decl.type.type.names + if typenames == ['__dotdotdot__']: + return model.unknown_type(decl.name) + + if typenames == ['__dotdotdotint__']: + if self._uses_new_feature is None: + self._uses_new_feature = "'typedef int... %s'" % decl.name + return model.UnknownIntegerType(decl.name) + + if typenames == ['__dotdotdotfloat__']: + # note: not for 'long double' so far + if self._uses_new_feature is None: + self._uses_new_feature = "'typedef float... %s'" % decl.name + return model.UnknownFloatType(decl.name) + + raise FFIError(':%d: unsupported usage of "..." in typedef' + % decl.coord.line) + + def _get_unknown_ptr_type(self, decl): + if decl.type.type.type.names == ['__dotdotdot__']: + return model.unknown_ptr_type(decl.name) + raise FFIError(':%d: unsupported usage of "..." in typedef' + % decl.coord.line) diff --git a/.venv/Lib/site-packages/cffi/error.py b/.venv/Lib/site-packages/cffi/error.py new file mode 100644 index 00000000..0a27247c --- /dev/null +++ b/.venv/Lib/site-packages/cffi/error.py @@ -0,0 +1,31 @@ + +class FFIError(Exception): + __module__ = 'cffi' + +class CDefError(Exception): + __module__ = 'cffi' + def __str__(self): + try: + current_decl = self.args[1] + filename = current_decl.coord.file + linenum = current_decl.coord.line + prefix = '%s:%d: ' % (filename, linenum) + except (AttributeError, TypeError, IndexError): + prefix = '' + return '%s%s' % (prefix, self.args[0]) + +class VerificationError(Exception): + """ An error raised when verification fails + """ + __module__ = 'cffi' + +class VerificationMissing(Exception): + """ An error raised when incomplete structures are passed into + cdef, but no verification has been done + """ + __module__ = 'cffi' + +class PkgConfigError(Exception): + """ An error raised for missing modules in pkg-config + """ + __module__ = 'cffi' diff --git a/.venv/Lib/site-packages/cffi/ffiplatform.py b/.venv/Lib/site-packages/cffi/ffiplatform.py new file mode 100644 index 00000000..adca28f1 --- /dev/null +++ b/.venv/Lib/site-packages/cffi/ffiplatform.py @@ -0,0 +1,113 @@ +import sys, os +from .error import VerificationError + + +LIST_OF_FILE_NAMES = ['sources', 'include_dirs', 'library_dirs', + 'extra_objects', 'depends'] + +def get_extension(srcfilename, modname, sources=(), **kwds): + from cffi._shimmed_dist_utils import Extension + allsources = [srcfilename] + for src in sources: + allsources.append(os.path.normpath(src)) + return Extension(name=modname, sources=allsources, **kwds) + +def compile(tmpdir, ext, compiler_verbose=0, debug=None): + """Compile a C extension module using distutils.""" + + saved_environ = os.environ.copy() + try: + outputfilename = _build(tmpdir, ext, compiler_verbose, debug) + outputfilename = os.path.abspath(outputfilename) + finally: + # workaround for a distutils bugs where some env vars can + # become longer and longer every time it is used + for key, value in saved_environ.items(): + if os.environ.get(key) != value: + os.environ[key] = value + return outputfilename + +def _build(tmpdir, ext, compiler_verbose=0, debug=None): + # XXX compact but horrible :-( + from cffi._shimmed_dist_utils import Distribution, CompileError, LinkError, set_threshold, set_verbosity + + dist = Distribution({'ext_modules': [ext]}) + dist.parse_config_files() + options = dist.get_option_dict('build_ext') + if debug is None: + debug = sys.flags.debug + options['debug'] = ('ffiplatform', debug) + options['force'] = ('ffiplatform', True) + options['build_lib'] = ('ffiplatform', tmpdir) + options['build_temp'] = ('ffiplatform', tmpdir) + # + try: + old_level = set_threshold(0) or 0 + try: + set_verbosity(compiler_verbose) + dist.run_command('build_ext') + cmd_obj = dist.get_command_obj('build_ext') + [soname] = cmd_obj.get_outputs() + finally: + set_threshold(old_level) + except (CompileError, LinkError) as e: + raise VerificationError('%s: %s' % (e.__class__.__name__, e)) + # + return soname + +try: + from os.path import samefile +except ImportError: + def samefile(f1, f2): + return os.path.abspath(f1) == os.path.abspath(f2) + +def maybe_relative_path(path): + if not os.path.isabs(path): + return path # already relative + dir = path + names = [] + while True: + prevdir = dir + dir, name = os.path.split(prevdir) + if dir == prevdir or not dir: + return path # failed to make it relative + names.append(name) + try: + if samefile(dir, os.curdir): + names.reverse() + return os.path.join(*names) + except OSError: + pass + +# ____________________________________________________________ + +try: + int_or_long = (int, long) + import cStringIO +except NameError: + int_or_long = int # Python 3 + import io as cStringIO + +def _flatten(x, f): + if isinstance(x, str): + f.write('%ds%s' % (len(x), x)) + elif isinstance(x, dict): + keys = sorted(x.keys()) + f.write('%dd' % len(keys)) + for key in keys: + _flatten(key, f) + _flatten(x[key], f) + elif isinstance(x, (list, tuple)): + f.write('%dl' % len(x)) + for value in x: + _flatten(value, f) + elif isinstance(x, int_or_long): + f.write('%di' % (x,)) + else: + raise TypeError( + "the keywords to verify() contains unsupported object %r" % (x,)) + +def flatten(x): + f = cStringIO.StringIO() + _flatten(x, f) + return f.getvalue() diff --git a/.venv/Lib/site-packages/cffi/lock.py b/.venv/Lib/site-packages/cffi/lock.py new file mode 100644 index 00000000..db91b715 --- /dev/null +++ b/.venv/Lib/site-packages/cffi/lock.py @@ -0,0 +1,30 @@ +import sys + +if sys.version_info < (3,): + try: + from thread import allocate_lock + except ImportError: + from dummy_thread import allocate_lock +else: + try: + from _thread import allocate_lock + except ImportError: + from _dummy_thread import allocate_lock + + +##import sys +##l1 = allocate_lock + +##class allocate_lock(object): +## def __init__(self): +## self._real = l1() +## def __enter__(self): +## for i in range(4, 0, -1): +## print sys._getframe(i).f_code +## print +## return self._real.__enter__() +## def __exit__(self, *args): +## return self._real.__exit__(*args) +## def acquire(self, f): +## assert f is False +## return self._real.acquire(f) diff --git a/.venv/Lib/site-packages/cffi/model.py b/.venv/Lib/site-packages/cffi/model.py new file mode 100644 index 00000000..1708f43d --- /dev/null +++ b/.venv/Lib/site-packages/cffi/model.py @@ -0,0 +1,618 @@ +import types +import weakref + +from .lock import allocate_lock +from .error import CDefError, VerificationError, VerificationMissing + +# type qualifiers +Q_CONST = 0x01 +Q_RESTRICT = 0x02 +Q_VOLATILE = 0x04 + +def qualify(quals, replace_with): + if quals & Q_CONST: + replace_with = ' const ' + replace_with.lstrip() + if quals & Q_VOLATILE: + replace_with = ' volatile ' + replace_with.lstrip() + if quals & Q_RESTRICT: + # It seems that __restrict is supported by gcc and msvc. + # If you hit some different compiler, add a #define in + # _cffi_include.h for it (and in its copies, documented there) + replace_with = ' __restrict ' + replace_with.lstrip() + return replace_with + + +class BaseTypeByIdentity(object): + is_array_type = False + is_raw_function = False + + def get_c_name(self, replace_with='', context='a C file', quals=0): + result = self.c_name_with_marker + assert result.count('&') == 1 + # some logic duplication with ffi.getctype()... :-( + replace_with = replace_with.strip() + if replace_with: + if replace_with.startswith('*') and '&[' in result: + replace_with = '(%s)' % replace_with + elif not replace_with[0] in '[(': + replace_with = ' ' + replace_with + replace_with = qualify(quals, replace_with) + result = result.replace('&', replace_with) + if '$' in result: + raise VerificationError( + "cannot generate '%s' in %s: unknown type name" + % (self._get_c_name(), context)) + return result + + def _get_c_name(self): + return self.c_name_with_marker.replace('&', '') + + def has_c_name(self): + return '$' not in self._get_c_name() + + def is_integer_type(self): + return False + + def get_cached_btype(self, ffi, finishlist, can_delay=False): + try: + BType = ffi._cached_btypes[self] + except KeyError: + BType = self.build_backend_type(ffi, finishlist) + BType2 = ffi._cached_btypes.setdefault(self, BType) + assert BType2 is BType + return BType + + def __repr__(self): + return '<%s>' % (self._get_c_name(),) + + def _get_items(self): + return [(name, getattr(self, name)) for name in self._attrs_] + + +class BaseType(BaseTypeByIdentity): + + def __eq__(self, other): + return (self.__class__ == other.__class__ and + self._get_items() == other._get_items()) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.__class__, tuple(self._get_items()))) + + +class VoidType(BaseType): + _attrs_ = () + + def __init__(self): + self.c_name_with_marker = 'void&' + + def build_backend_type(self, ffi, finishlist): + return global_cache(self, ffi, 'new_void_type') + +void_type = VoidType() + + +class BasePrimitiveType(BaseType): + def is_complex_type(self): + return False + + +class PrimitiveType(BasePrimitiveType): + _attrs_ = ('name',) + + ALL_PRIMITIVE_TYPES = { + 'char': 'c', + 'short': 'i', + 'int': 'i', + 'long': 'i', + 'long long': 'i', + 'signed char': 'i', + 'unsigned char': 'i', + 'unsigned short': 'i', + 'unsigned int': 'i', + 'unsigned long': 'i', + 'unsigned long long': 'i', + 'float': 'f', + 'double': 'f', + 'long double': 'f', + 'float _Complex': 'j', + 'double _Complex': 'j', + '_Bool': 'i', + # the following types are not primitive in the C sense + 'wchar_t': 'c', + 'char16_t': 'c', + 'char32_t': 'c', + 'int8_t': 'i', + 'uint8_t': 'i', + 'int16_t': 'i', + 'uint16_t': 'i', + 'int32_t': 'i', + 'uint32_t': 'i', + 'int64_t': 'i', + 'uint64_t': 'i', + 'int_least8_t': 'i', + 'uint_least8_t': 'i', + 'int_least16_t': 'i', + 'uint_least16_t': 'i', + 'int_least32_t': 'i', + 'uint_least32_t': 'i', + 'int_least64_t': 'i', + 'uint_least64_t': 'i', + 'int_fast8_t': 'i', + 'uint_fast8_t': 'i', + 'int_fast16_t': 'i', + 'uint_fast16_t': 'i', + 'int_fast32_t': 'i', + 'uint_fast32_t': 'i', + 'int_fast64_t': 'i', + 'uint_fast64_t': 'i', + 'intptr_t': 'i', + 'uintptr_t': 'i', + 'intmax_t': 'i', + 'uintmax_t': 'i', + 'ptrdiff_t': 'i', + 'size_t': 'i', + 'ssize_t': 'i', + } + + def __init__(self, name): + assert name in self.ALL_PRIMITIVE_TYPES + self.name = name + self.c_name_with_marker = name + '&' + + def is_char_type(self): + return self.ALL_PRIMITIVE_TYPES[self.name] == 'c' + def is_integer_type(self): + return self.ALL_PRIMITIVE_TYPES[self.name] == 'i' + def is_float_type(self): + return self.ALL_PRIMITIVE_TYPES[self.name] == 'f' + def is_complex_type(self): + return self.ALL_PRIMITIVE_TYPES[self.name] == 'j' + + def build_backend_type(self, ffi, finishlist): + return global_cache(self, ffi, 'new_primitive_type', self.name) + + +class UnknownIntegerType(BasePrimitiveType): + _attrs_ = ('name',) + + def __init__(self, name): + self.name = name + self.c_name_with_marker = name + '&' + + def is_integer_type(self): + return True + + def build_backend_type(self, ffi, finishlist): + raise NotImplementedError("integer type '%s' can only be used after " + "compilation" % self.name) + +class UnknownFloatType(BasePrimitiveType): + _attrs_ = ('name', ) + + def __init__(self, name): + self.name = name + self.c_name_with_marker = name + '&' + + def build_backend_type(self, ffi, finishlist): + raise NotImplementedError("float type '%s' can only be used after " + "compilation" % self.name) + + +class BaseFunctionType(BaseType): + _attrs_ = ('args', 'result', 'ellipsis', 'abi') + + def __init__(self, args, result, ellipsis, abi=None): + self.args = args + self.result = result + self.ellipsis = ellipsis + self.abi = abi + # + reprargs = [arg._get_c_name() for arg in self.args] + if self.ellipsis: + reprargs.append('...') + reprargs = reprargs or ['void'] + replace_with = self._base_pattern % (', '.join(reprargs),) + if abi is not None: + replace_with = replace_with[:1] + abi + ' ' + replace_with[1:] + self.c_name_with_marker = ( + self.result.c_name_with_marker.replace('&', replace_with)) + + +class RawFunctionType(BaseFunctionType): + # Corresponds to a C type like 'int(int)', which is the C type of + # a function, but not a pointer-to-function. The backend has no + # notion of such a type; it's used temporarily by parsing. + _base_pattern = '(&)(%s)' + is_raw_function = True + + def build_backend_type(self, ffi, finishlist): + raise CDefError("cannot render the type %r: it is a function " + "type, not a pointer-to-function type" % (self,)) + + def as_function_pointer(self): + return FunctionPtrType(self.args, self.result, self.ellipsis, self.abi) + + +class FunctionPtrType(BaseFunctionType): + _base_pattern = '(*&)(%s)' + + def build_backend_type(self, ffi, finishlist): + result = self.result.get_cached_btype(ffi, finishlist) + args = [] + for tp in self.args: + args.append(tp.get_cached_btype(ffi, finishlist)) + abi_args = () + if self.abi == "__stdcall": + if not self.ellipsis: # __stdcall ignored for variadic funcs + try: + abi_args = (ffi._backend.FFI_STDCALL,) + except AttributeError: + pass + return global_cache(self, ffi, 'new_function_type', + tuple(args), result, self.ellipsis, *abi_args) + + def as_raw_function(self): + return RawFunctionType(self.args, self.result, self.ellipsis, self.abi) + + +class PointerType(BaseType): + _attrs_ = ('totype', 'quals') + + def __init__(self, totype, quals=0): + self.totype = totype + self.quals = quals + extra = " *&" + if totype.is_array_type: + extra = "(%s)" % (extra.lstrip(),) + extra = qualify(quals, extra) + self.c_name_with_marker = totype.c_name_with_marker.replace('&', extra) + + def build_backend_type(self, ffi, finishlist): + BItem = self.totype.get_cached_btype(ffi, finishlist, can_delay=True) + return global_cache(self, ffi, 'new_pointer_type', BItem) + +voidp_type = PointerType(void_type) + +def ConstPointerType(totype): + return PointerType(totype, Q_CONST) + +const_voidp_type = ConstPointerType(void_type) + + +class NamedPointerType(PointerType): + _attrs_ = ('totype', 'name') + + def __init__(self, totype, name, quals=0): + PointerType.__init__(self, totype, quals) + self.name = name + self.c_name_with_marker = name + '&' + + +class ArrayType(BaseType): + _attrs_ = ('item', 'length') + is_array_type = True + + def __init__(self, item, length): + self.item = item + self.length = length + # + if length is None: + brackets = '&[]' + elif length == '...': + brackets = '&[/*...*/]' + else: + brackets = '&[%s]' % length + self.c_name_with_marker = ( + self.item.c_name_with_marker.replace('&', brackets)) + + def length_is_unknown(self): + return isinstance(self.length, str) + + def resolve_length(self, newlength): + return ArrayType(self.item, newlength) + + def build_backend_type(self, ffi, finishlist): + if self.length_is_unknown(): + raise CDefError("cannot render the type %r: unknown length" % + (self,)) + self.item.get_cached_btype(ffi, finishlist) # force the item BType + BPtrItem = PointerType(self.item).get_cached_btype(ffi, finishlist) + return global_cache(self, ffi, 'new_array_type', BPtrItem, self.length) + +char_array_type = ArrayType(PrimitiveType('char'), None) + + +class StructOrUnionOrEnum(BaseTypeByIdentity): + _attrs_ = ('name',) + forcename = None + + def build_c_name_with_marker(self): + name = self.forcename or '%s %s' % (self.kind, self.name) + self.c_name_with_marker = name + '&' + + def force_the_name(self, forcename): + self.forcename = forcename + self.build_c_name_with_marker() + + def get_official_name(self): + assert self.c_name_with_marker.endswith('&') + return self.c_name_with_marker[:-1] + + +class StructOrUnion(StructOrUnionOrEnum): + fixedlayout = None + completed = 0 + partial = False + packed = 0 + + def __init__(self, name, fldnames, fldtypes, fldbitsize, fldquals=None): + self.name = name + self.fldnames = fldnames + self.fldtypes = fldtypes + self.fldbitsize = fldbitsize + self.fldquals = fldquals + self.build_c_name_with_marker() + + def anonymous_struct_fields(self): + if self.fldtypes is not None: + for name, type in zip(self.fldnames, self.fldtypes): + if name == '' and isinstance(type, StructOrUnion): + yield type + + def enumfields(self, expand_anonymous_struct_union=True): + fldquals = self.fldquals + if fldquals is None: + fldquals = (0,) * len(self.fldnames) + for name, type, bitsize, quals in zip(self.fldnames, self.fldtypes, + self.fldbitsize, fldquals): + if (name == '' and isinstance(type, StructOrUnion) + and expand_anonymous_struct_union): + # nested anonymous struct/union + for result in type.enumfields(): + yield result + else: + yield (name, type, bitsize, quals) + + def force_flatten(self): + # force the struct or union to have a declaration that lists + # directly all fields returned by enumfields(), flattening + # nested anonymous structs/unions. + names = [] + types = [] + bitsizes = [] + fldquals = [] + for name, type, bitsize, quals in self.enumfields(): + names.append(name) + types.append(type) + bitsizes.append(bitsize) + fldquals.append(quals) + self.fldnames = tuple(names) + self.fldtypes = tuple(types) + self.fldbitsize = tuple(bitsizes) + self.fldquals = tuple(fldquals) + + def get_cached_btype(self, ffi, finishlist, can_delay=False): + BType = StructOrUnionOrEnum.get_cached_btype(self, ffi, finishlist, + can_delay) + if not can_delay: + self.finish_backend_type(ffi, finishlist) + return BType + + def finish_backend_type(self, ffi, finishlist): + if self.completed: + if self.completed != 2: + raise NotImplementedError("recursive structure declaration " + "for '%s'" % (self.name,)) + return + BType = ffi._cached_btypes[self] + # + self.completed = 1 + # + if self.fldtypes is None: + pass # not completing it: it's an opaque struct + # + elif self.fixedlayout is None: + fldtypes = [tp.get_cached_btype(ffi, finishlist) + for tp in self.fldtypes] + lst = list(zip(self.fldnames, fldtypes, self.fldbitsize)) + extra_flags = () + if self.packed: + if self.packed == 1: + extra_flags = (8,) # SF_PACKED + else: + extra_flags = (0, self.packed) + ffi._backend.complete_struct_or_union(BType, lst, self, + -1, -1, *extra_flags) + # + else: + fldtypes = [] + fieldofs, fieldsize, totalsize, totalalignment = self.fixedlayout + for i in range(len(self.fldnames)): + fsize = fieldsize[i] + ftype = self.fldtypes[i] + # + if isinstance(ftype, ArrayType) and ftype.length_is_unknown(): + # fix the length to match the total size + BItemType = ftype.item.get_cached_btype(ffi, finishlist) + nlen, nrest = divmod(fsize, ffi.sizeof(BItemType)) + if nrest != 0: + self._verification_error( + "field '%s.%s' has a bogus size?" % ( + self.name, self.fldnames[i] or '{}')) + ftype = ftype.resolve_length(nlen) + self.fldtypes = (self.fldtypes[:i] + (ftype,) + + self.fldtypes[i+1:]) + # + BFieldType = ftype.get_cached_btype(ffi, finishlist) + if isinstance(ftype, ArrayType) and ftype.length is None: + assert fsize == 0 + else: + bitemsize = ffi.sizeof(BFieldType) + if bitemsize != fsize: + self._verification_error( + "field '%s.%s' is declared as %d bytes, but is " + "really %d bytes" % (self.name, + self.fldnames[i] or '{}', + bitemsize, fsize)) + fldtypes.append(BFieldType) + # + lst = list(zip(self.fldnames, fldtypes, self.fldbitsize, fieldofs)) + ffi._backend.complete_struct_or_union(BType, lst, self, + totalsize, totalalignment) + self.completed = 2 + + def _verification_error(self, msg): + raise VerificationError(msg) + + def check_not_partial(self): + if self.partial and self.fixedlayout is None: + raise VerificationMissing(self._get_c_name()) + + def build_backend_type(self, ffi, finishlist): + self.check_not_partial() + finishlist.append(self) + # + return global_cache(self, ffi, 'new_%s_type' % self.kind, + self.get_official_name(), key=self) + + +class StructType(StructOrUnion): + kind = 'struct' + + +class UnionType(StructOrUnion): + kind = 'union' + + +class EnumType(StructOrUnionOrEnum): + kind = 'enum' + partial = False + partial_resolved = False + + def __init__(self, name, enumerators, enumvalues, baseinttype=None): + self.name = name + self.enumerators = enumerators + self.enumvalues = enumvalues + self.baseinttype = baseinttype + self.build_c_name_with_marker() + + def force_the_name(self, forcename): + StructOrUnionOrEnum.force_the_name(self, forcename) + if self.forcename is None: + name = self.get_official_name() + self.forcename = '$' + name.replace(' ', '_') + + def check_not_partial(self): + if self.partial and not self.partial_resolved: + raise VerificationMissing(self._get_c_name()) + + def build_backend_type(self, ffi, finishlist): + self.check_not_partial() + base_btype = self.build_baseinttype(ffi, finishlist) + return global_cache(self, ffi, 'new_enum_type', + self.get_official_name(), + self.enumerators, self.enumvalues, + base_btype, key=self) + + def build_baseinttype(self, ffi, finishlist): + if self.baseinttype is not None: + return self.baseinttype.get_cached_btype(ffi, finishlist) + # + if self.enumvalues: + smallest_value = min(self.enumvalues) + largest_value = max(self.enumvalues) + else: + import warnings + try: + # XXX! The goal is to ensure that the warnings.warn() + # will not suppress the warning. We want to get it + # several times if we reach this point several times. + __warningregistry__.clear() + except NameError: + pass + warnings.warn("%r has no values explicitly defined; " + "guessing that it is equivalent to 'unsigned int'" + % self._get_c_name()) + smallest_value = largest_value = 0 + if smallest_value < 0: # needs a signed type + sign = 1 + candidate1 = PrimitiveType("int") + candidate2 = PrimitiveType("long") + else: + sign = 0 + candidate1 = PrimitiveType("unsigned int") + candidate2 = PrimitiveType("unsigned long") + btype1 = candidate1.get_cached_btype(ffi, finishlist) + btype2 = candidate2.get_cached_btype(ffi, finishlist) + size1 = ffi.sizeof(btype1) + size2 = ffi.sizeof(btype2) + if (smallest_value >= ((-1) << (8*size1-1)) and + largest_value < (1 << (8*size1-sign))): + return btype1 + if (smallest_value >= ((-1) << (8*size2-1)) and + largest_value < (1 << (8*size2-sign))): + return btype2 + raise CDefError("%s values don't all fit into either 'long' " + "or 'unsigned long'" % self._get_c_name()) + +def unknown_type(name, structname=None): + if structname is None: + structname = '$%s' % name + tp = StructType(structname, None, None, None) + tp.force_the_name(name) + tp.origin = "unknown_type" + return tp + +def unknown_ptr_type(name, structname=None): + if structname is None: + structname = '$$%s' % name + tp = StructType(structname, None, None, None) + return NamedPointerType(tp, name) + + +global_lock = allocate_lock() +_typecache_cffi_backend = weakref.WeakValueDictionary() + +def get_typecache(backend): + # returns _typecache_cffi_backend if backend is the _cffi_backend + # module, or type(backend).__typecache if backend is an instance of + # CTypesBackend (or some FakeBackend class during tests) + if isinstance(backend, types.ModuleType): + return _typecache_cffi_backend + with global_lock: + if not hasattr(type(backend), '__typecache'): + type(backend).__typecache = weakref.WeakValueDictionary() + return type(backend).__typecache + +def global_cache(srctype, ffi, funcname, *args, **kwds): + key = kwds.pop('key', (funcname, args)) + assert not kwds + try: + return ffi._typecache[key] + except KeyError: + pass + try: + res = getattr(ffi._backend, funcname)(*args) + except NotImplementedError as e: + raise NotImplementedError("%s: %r: %s" % (funcname, srctype, e)) + # note that setdefault() on WeakValueDictionary is not atomic + # and contains a rare bug (http://bugs.python.org/issue19542); + # we have to use a lock and do it ourselves + cache = ffi._typecache + with global_lock: + res1 = cache.get(key) + if res1 is None: + cache[key] = res + return res + else: + return res1 + +def pointer_cache(ffi, BType): + return global_cache('?', ffi, 'new_pointer_type', BType) + +def attach_exception_info(e, name): + if e.args and type(e.args[0]) is str: + e.args = ('%s: %s' % (name, e.args[0]),) + e.args[1:] diff --git a/.venv/Lib/site-packages/cffi/parse_c_type.h b/.venv/Lib/site-packages/cffi/parse_c_type.h new file mode 100644 index 00000000..84e4ef85 --- /dev/null +++ b/.venv/Lib/site-packages/cffi/parse_c_type.h @@ -0,0 +1,181 @@ + +/* This part is from file 'cffi/parse_c_type.h'. It is copied at the + beginning of C sources generated by CFFI's ffi.set_source(). */ + +typedef void *_cffi_opcode_t; + +#define _CFFI_OP(opcode, arg) (_cffi_opcode_t)(opcode | (((uintptr_t)(arg)) << 8)) +#define _CFFI_GETOP(cffi_opcode) ((unsigned char)(uintptr_t)cffi_opcode) +#define _CFFI_GETARG(cffi_opcode) (((intptr_t)cffi_opcode) >> 8) + +#define _CFFI_OP_PRIMITIVE 1 +#define _CFFI_OP_POINTER 3 +#define _CFFI_OP_ARRAY 5 +#define _CFFI_OP_OPEN_ARRAY 7 +#define _CFFI_OP_STRUCT_UNION 9 +#define _CFFI_OP_ENUM 11 +#define _CFFI_OP_FUNCTION 13 +#define _CFFI_OP_FUNCTION_END 15 +#define _CFFI_OP_NOOP 17 +#define _CFFI_OP_BITFIELD 19 +#define _CFFI_OP_TYPENAME 21 +#define _CFFI_OP_CPYTHON_BLTN_V 23 // varargs +#define _CFFI_OP_CPYTHON_BLTN_N 25 // noargs +#define _CFFI_OP_CPYTHON_BLTN_O 27 // O (i.e. a single arg) +#define _CFFI_OP_CONSTANT 29 +#define _CFFI_OP_CONSTANT_INT 31 +#define _CFFI_OP_GLOBAL_VAR 33 +#define _CFFI_OP_DLOPEN_FUNC 35 +#define _CFFI_OP_DLOPEN_CONST 37 +#define _CFFI_OP_GLOBAL_VAR_F 39 +#define _CFFI_OP_EXTERN_PYTHON 41 + +#define _CFFI_PRIM_VOID 0 +#define _CFFI_PRIM_BOOL 1 +#define _CFFI_PRIM_CHAR 2 +#define _CFFI_PRIM_SCHAR 3 +#define _CFFI_PRIM_UCHAR 4 +#define _CFFI_PRIM_SHORT 5 +#define _CFFI_PRIM_USHORT 6 +#define _CFFI_PRIM_INT 7 +#define _CFFI_PRIM_UINT 8 +#define _CFFI_PRIM_LONG 9 +#define _CFFI_PRIM_ULONG 10 +#define _CFFI_PRIM_LONGLONG 11 +#define _CFFI_PRIM_ULONGLONG 12 +#define _CFFI_PRIM_FLOAT 13 +#define _CFFI_PRIM_DOUBLE 14 +#define _CFFI_PRIM_LONGDOUBLE 15 + +#define _CFFI_PRIM_WCHAR 16 +#define _CFFI_PRIM_INT8 17 +#define _CFFI_PRIM_UINT8 18 +#define _CFFI_PRIM_INT16 19 +#define _CFFI_PRIM_UINT16 20 +#define _CFFI_PRIM_INT32 21 +#define _CFFI_PRIM_UINT32 22 +#define _CFFI_PRIM_INT64 23 +#define _CFFI_PRIM_UINT64 24 +#define _CFFI_PRIM_INTPTR 25 +#define _CFFI_PRIM_UINTPTR 26 +#define _CFFI_PRIM_PTRDIFF 27 +#define _CFFI_PRIM_SIZE 28 +#define _CFFI_PRIM_SSIZE 29 +#define _CFFI_PRIM_INT_LEAST8 30 +#define _CFFI_PRIM_UINT_LEAST8 31 +#define _CFFI_PRIM_INT_LEAST16 32 +#define _CFFI_PRIM_UINT_LEAST16 33 +#define _CFFI_PRIM_INT_LEAST32 34 +#define _CFFI_PRIM_UINT_LEAST32 35 +#define _CFFI_PRIM_INT_LEAST64 36 +#define _CFFI_PRIM_UINT_LEAST64 37 +#define _CFFI_PRIM_INT_FAST8 38 +#define _CFFI_PRIM_UINT_FAST8 39 +#define _CFFI_PRIM_INT_FAST16 40 +#define _CFFI_PRIM_UINT_FAST16 41 +#define _CFFI_PRIM_INT_FAST32 42 +#define _CFFI_PRIM_UINT_FAST32 43 +#define _CFFI_PRIM_INT_FAST64 44 +#define _CFFI_PRIM_UINT_FAST64 45 +#define _CFFI_PRIM_INTMAX 46 +#define _CFFI_PRIM_UINTMAX 47 +#define _CFFI_PRIM_FLOATCOMPLEX 48 +#define _CFFI_PRIM_DOUBLECOMPLEX 49 +#define _CFFI_PRIM_CHAR16 50 +#define _CFFI_PRIM_CHAR32 51 + +#define _CFFI__NUM_PRIM 52 +#define _CFFI__UNKNOWN_PRIM (-1) +#define _CFFI__UNKNOWN_FLOAT_PRIM (-2) +#define _CFFI__UNKNOWN_LONG_DOUBLE (-3) + +#define _CFFI__IO_FILE_STRUCT (-1) + + +struct _cffi_global_s { + const char *name; + void *address; + _cffi_opcode_t type_op; + void *size_or_direct_fn; // OP_GLOBAL_VAR: size, or 0 if unknown + // OP_CPYTHON_BLTN_*: addr of direct function +}; + +struct _cffi_getconst_s { + unsigned long long value; + const struct _cffi_type_context_s *ctx; + int gindex; +}; + +struct _cffi_struct_union_s { + const char *name; + int type_index; // -> _cffi_types, on a OP_STRUCT_UNION + int flags; // _CFFI_F_* flags below + size_t size; + int alignment; + int first_field_index; // -> _cffi_fields array + int num_fields; +}; +#define _CFFI_F_UNION 0x01 // is a union, not a struct +#define _CFFI_F_CHECK_FIELDS 0x02 // complain if fields are not in the + // "standard layout" or if some are missing +#define _CFFI_F_PACKED 0x04 // for CHECK_FIELDS, assume a packed struct +#define _CFFI_F_EXTERNAL 0x08 // in some other ffi.include() +#define _CFFI_F_OPAQUE 0x10 // opaque + +struct _cffi_field_s { + const char *name; + size_t field_offset; + size_t field_size; + _cffi_opcode_t field_type_op; +}; + +struct _cffi_enum_s { + const char *name; + int type_index; // -> _cffi_types, on a OP_ENUM + int type_prim; // _CFFI_PRIM_xxx + const char *enumerators; // comma-delimited string +}; + +struct _cffi_typename_s { + const char *name; + int type_index; /* if opaque, points to a possibly artificial + OP_STRUCT which is itself opaque */ +}; + +struct _cffi_type_context_s { + _cffi_opcode_t *types; + const struct _cffi_global_s *globals; + const struct _cffi_field_s *fields; + const struct _cffi_struct_union_s *struct_unions; + const struct _cffi_enum_s *enums; + const struct _cffi_typename_s *typenames; + int num_globals; + int num_struct_unions; + int num_enums; + int num_typenames; + const char *const *includes; + int num_types; + int flags; /* future extension */ +}; + +struct _cffi_parse_info_s { + const struct _cffi_type_context_s *ctx; + _cffi_opcode_t *output; + unsigned int output_size; + size_t error_location; + const char *error_message; +}; + +struct _cffi_externpy_s { + const char *name; + size_t size_of_result; + void *reserved1, *reserved2; +}; + +#ifdef _CFFI_INTERNAL +static int parse_c_type(struct _cffi_parse_info_s *info, const char *input); +static int search_in_globals(const struct _cffi_type_context_s *ctx, + const char *search, size_t search_len); +static int search_in_struct_unions(const struct _cffi_type_context_s *ctx, + const char *search, size_t search_len); +#endif diff --git a/.venv/Lib/site-packages/cffi/pkgconfig.py b/.venv/Lib/site-packages/cffi/pkgconfig.py new file mode 100644 index 00000000..5c93f15a --- /dev/null +++ b/.venv/Lib/site-packages/cffi/pkgconfig.py @@ -0,0 +1,121 @@ +# pkg-config, https://www.freedesktop.org/wiki/Software/pkg-config/ integration for cffi +import sys, os, subprocess + +from .error import PkgConfigError + + +def merge_flags(cfg1, cfg2): + """Merge values from cffi config flags cfg2 to cf1 + + Example: + merge_flags({"libraries": ["one"]}, {"libraries": ["two"]}) + {"libraries": ["one", "two"]} + """ + for key, value in cfg2.items(): + if key not in cfg1: + cfg1[key] = value + else: + if not isinstance(cfg1[key], list): + raise TypeError("cfg1[%r] should be a list of strings" % (key,)) + if not isinstance(value, list): + raise TypeError("cfg2[%r] should be a list of strings" % (key,)) + cfg1[key].extend(value) + return cfg1 + + +def call(libname, flag, encoding=sys.getfilesystemencoding()): + """Calls pkg-config and returns the output if found + """ + a = ["pkg-config", "--print-errors"] + a.append(flag) + a.append(libname) + try: + pc = subprocess.Popen(a, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + except EnvironmentError as e: + raise PkgConfigError("cannot run pkg-config: %s" % (str(e).strip(),)) + + bout, berr = pc.communicate() + if pc.returncode != 0: + try: + berr = berr.decode(encoding) + except Exception: + pass + raise PkgConfigError(berr.strip()) + + if sys.version_info >= (3,) and not isinstance(bout, str): # Python 3.x + try: + bout = bout.decode(encoding) + except UnicodeDecodeError: + raise PkgConfigError("pkg-config %s %s returned bytes that cannot " + "be decoded with encoding %r:\n%r" % + (flag, libname, encoding, bout)) + + if os.altsep != '\\' and '\\' in bout: + raise PkgConfigError("pkg-config %s %s returned an unsupported " + "backslash-escaped output:\n%r" % + (flag, libname, bout)) + return bout + + +def flags_from_pkgconfig(libs): + r"""Return compiler line flags for FFI.set_source based on pkg-config output + + Usage + ... + ffibuilder.set_source("_foo", pkgconfig = ["libfoo", "libbar >= 1.8.3"]) + + If pkg-config is installed on build machine, then arguments include_dirs, + library_dirs, libraries, define_macros, extra_compile_args and + extra_link_args are extended with an output of pkg-config for libfoo and + libbar. + + Raises PkgConfigError in case the pkg-config call fails. + """ + + def get_include_dirs(string): + return [x[2:] for x in string.split() if x.startswith("-I")] + + def get_library_dirs(string): + return [x[2:] for x in string.split() if x.startswith("-L")] + + def get_libraries(string): + return [x[2:] for x in string.split() if x.startswith("-l")] + + # convert -Dfoo=bar to list of tuples [("foo", "bar")] expected by distutils + def get_macros(string): + def _macro(x): + x = x[2:] # drop "-D" + if '=' in x: + return tuple(x.split("=", 1)) # "-Dfoo=bar" => ("foo", "bar") + else: + return (x, None) # "-Dfoo" => ("foo", None) + return [_macro(x) for x in string.split() if x.startswith("-D")] + + def get_other_cflags(string): + return [x for x in string.split() if not x.startswith("-I") and + not x.startswith("-D")] + + def get_other_libs(string): + return [x for x in string.split() if not x.startswith("-L") and + not x.startswith("-l")] + + # return kwargs for given libname + def kwargs(libname): + fse = sys.getfilesystemencoding() + all_cflags = call(libname, "--cflags") + all_libs = call(libname, "--libs") + return { + "include_dirs": get_include_dirs(all_cflags), + "library_dirs": get_library_dirs(all_libs), + "libraries": get_libraries(all_libs), + "define_macros": get_macros(all_cflags), + "extra_compile_args": get_other_cflags(all_cflags), + "extra_link_args": get_other_libs(all_libs), + } + + # merge all arguments together + ret = {} + for libname in libs: + lib_flags = kwargs(libname) + merge_flags(ret, lib_flags) + return ret diff --git a/.venv/Lib/site-packages/cffi/recompiler.py b/.venv/Lib/site-packages/cffi/recompiler.py new file mode 100644 index 00000000..4167bc05 --- /dev/null +++ b/.venv/Lib/site-packages/cffi/recompiler.py @@ -0,0 +1,1581 @@ +import os, sys, io +from . import ffiplatform, model +from .error import VerificationError +from .cffi_opcode import * + +VERSION_BASE = 0x2601 +VERSION_EMBEDDED = 0x2701 +VERSION_CHAR16CHAR32 = 0x2801 + +USE_LIMITED_API = (sys.platform != 'win32' or sys.version_info < (3, 0) or + sys.version_info >= (3, 5)) + + +class GlobalExpr: + def __init__(self, name, address, type_op, size=0, check_value=0): + self.name = name + self.address = address + self.type_op = type_op + self.size = size + self.check_value = check_value + + def as_c_expr(self): + return ' { "%s", (void *)%s, %s, (void *)%s },' % ( + self.name, self.address, self.type_op.as_c_expr(), self.size) + + def as_python_expr(self): + return "b'%s%s',%d" % (self.type_op.as_python_bytes(), self.name, + self.check_value) + +class FieldExpr: + def __init__(self, name, field_offset, field_size, fbitsize, field_type_op): + self.name = name + self.field_offset = field_offset + self.field_size = field_size + self.fbitsize = fbitsize + self.field_type_op = field_type_op + + def as_c_expr(self): + spaces = " " * len(self.name) + return (' { "%s", %s,\n' % (self.name, self.field_offset) + + ' %s %s,\n' % (spaces, self.field_size) + + ' %s %s },' % (spaces, self.field_type_op.as_c_expr())) + + def as_python_expr(self): + raise NotImplementedError + + def as_field_python_expr(self): + if self.field_type_op.op == OP_NOOP: + size_expr = '' + elif self.field_type_op.op == OP_BITFIELD: + size_expr = format_four_bytes(self.fbitsize) + else: + raise NotImplementedError + return "b'%s%s%s'" % (self.field_type_op.as_python_bytes(), + size_expr, + self.name) + +class StructUnionExpr: + def __init__(self, name, type_index, flags, size, alignment, comment, + first_field_index, c_fields): + self.name = name + self.type_index = type_index + self.flags = flags + self.size = size + self.alignment = alignment + self.comment = comment + self.first_field_index = first_field_index + self.c_fields = c_fields + + def as_c_expr(self): + return (' { "%s", %d, %s,' % (self.name, self.type_index, self.flags) + + '\n %s, %s, ' % (self.size, self.alignment) + + '%d, %d ' % (self.first_field_index, len(self.c_fields)) + + ('/* %s */ ' % self.comment if self.comment else '') + + '},') + + def as_python_expr(self): + flags = eval(self.flags, G_FLAGS) + fields_expr = [c_field.as_field_python_expr() + for c_field in self.c_fields] + return "(b'%s%s%s',%s)" % ( + format_four_bytes(self.type_index), + format_four_bytes(flags), + self.name, + ','.join(fields_expr)) + +class EnumExpr: + def __init__(self, name, type_index, size, signed, allenums): + self.name = name + self.type_index = type_index + self.size = size + self.signed = signed + self.allenums = allenums + + def as_c_expr(self): + return (' { "%s", %d, _cffi_prim_int(%s, %s),\n' + ' "%s" },' % (self.name, self.type_index, + self.size, self.signed, self.allenums)) + + def as_python_expr(self): + prim_index = { + (1, 0): PRIM_UINT8, (1, 1): PRIM_INT8, + (2, 0): PRIM_UINT16, (2, 1): PRIM_INT16, + (4, 0): PRIM_UINT32, (4, 1): PRIM_INT32, + (8, 0): PRIM_UINT64, (8, 1): PRIM_INT64, + }[self.size, self.signed] + return "b'%s%s%s\\x00%s'" % (format_four_bytes(self.type_index), + format_four_bytes(prim_index), + self.name, self.allenums) + +class TypenameExpr: + def __init__(self, name, type_index): + self.name = name + self.type_index = type_index + + def as_c_expr(self): + return ' { "%s", %d },' % (self.name, self.type_index) + + def as_python_expr(self): + return "b'%s%s'" % (format_four_bytes(self.type_index), self.name) + + +# ____________________________________________________________ + + +class Recompiler: + _num_externpy = 0 + + def __init__(self, ffi, module_name, target_is_python=False): + self.ffi = ffi + self.module_name = module_name + self.target_is_python = target_is_python + self._version = VERSION_BASE + + def needs_version(self, ver): + self._version = max(self._version, ver) + + def collect_type_table(self): + self._typesdict = {} + self._generate("collecttype") + # + all_decls = sorted(self._typesdict, key=str) + # + # prepare all FUNCTION bytecode sequences first + self.cffi_types = [] + for tp in all_decls: + if tp.is_raw_function: + assert self._typesdict[tp] is None + self._typesdict[tp] = len(self.cffi_types) + self.cffi_types.append(tp) # placeholder + for tp1 in tp.args: + assert isinstance(tp1, (model.VoidType, + model.BasePrimitiveType, + model.PointerType, + model.StructOrUnionOrEnum, + model.FunctionPtrType)) + if self._typesdict[tp1] is None: + self._typesdict[tp1] = len(self.cffi_types) + self.cffi_types.append(tp1) # placeholder + self.cffi_types.append('END') # placeholder + # + # prepare all OTHER bytecode sequences + for tp in all_decls: + if not tp.is_raw_function and self._typesdict[tp] is None: + self._typesdict[tp] = len(self.cffi_types) + self.cffi_types.append(tp) # placeholder + if tp.is_array_type and tp.length is not None: + self.cffi_types.append('LEN') # placeholder + assert None not in self._typesdict.values() + # + # collect all structs and unions and enums + self._struct_unions = {} + self._enums = {} + for tp in all_decls: + if isinstance(tp, model.StructOrUnion): + self._struct_unions[tp] = None + elif isinstance(tp, model.EnumType): + self._enums[tp] = None + for i, tp in enumerate(sorted(self._struct_unions, + key=lambda tp: tp.name)): + self._struct_unions[tp] = i + for i, tp in enumerate(sorted(self._enums, + key=lambda tp: tp.name)): + self._enums[tp] = i + # + # emit all bytecode sequences now + for tp in all_decls: + method = getattr(self, '_emit_bytecode_' + tp.__class__.__name__) + method(tp, self._typesdict[tp]) + # + # consistency check + for op in self.cffi_types: + assert isinstance(op, CffiOp) + self.cffi_types = tuple(self.cffi_types) # don't change any more + + def _enum_fields(self, tp): + # When producing C, expand all anonymous struct/union fields. + # That's necessary to have C code checking the offsets of the + # individual fields contained in them. When producing Python, + # don't do it and instead write it like it is, with the + # corresponding fields having an empty name. Empty names are + # recognized at runtime when we import the generated Python + # file. + expand_anonymous_struct_union = not self.target_is_python + return tp.enumfields(expand_anonymous_struct_union) + + def _do_collect_type(self, tp): + if not isinstance(tp, model.BaseTypeByIdentity): + if isinstance(tp, tuple): + for x in tp: + self._do_collect_type(x) + return + if tp not in self._typesdict: + self._typesdict[tp] = None + if isinstance(tp, model.FunctionPtrType): + self._do_collect_type(tp.as_raw_function()) + elif isinstance(tp, model.StructOrUnion): + if tp.fldtypes is not None and ( + tp not in self.ffi._parser._included_declarations): + for name1, tp1, _, _ in self._enum_fields(tp): + self._do_collect_type(self._field_type(tp, name1, tp1)) + else: + for _, x in tp._get_items(): + self._do_collect_type(x) + + def _generate(self, step_name): + lst = self.ffi._parser._declarations.items() + for name, (tp, quals) in sorted(lst): + kind, realname = name.split(' ', 1) + try: + method = getattr(self, '_generate_cpy_%s_%s' % (kind, + step_name)) + except AttributeError: + raise VerificationError( + "not implemented in recompile(): %r" % name) + try: + self._current_quals = quals + method(tp, realname) + except Exception as e: + model.attach_exception_info(e, name) + raise + + # ---------- + + ALL_STEPS = ["global", "field", "struct_union", "enum", "typename"] + + def collect_step_tables(self): + # collect the declarations for '_cffi_globals', '_cffi_typenames', etc. + self._lsts = {} + for step_name in self.ALL_STEPS: + self._lsts[step_name] = [] + self._seen_struct_unions = set() + self._generate("ctx") + self._add_missing_struct_unions() + # + for step_name in self.ALL_STEPS: + lst = self._lsts[step_name] + if step_name != "field": + lst.sort(key=lambda entry: entry.name) + self._lsts[step_name] = tuple(lst) # don't change any more + # + # check for a possible internal inconsistency: _cffi_struct_unions + # should have been generated with exactly self._struct_unions + lst = self._lsts["struct_union"] + for tp, i in self._struct_unions.items(): + assert i < len(lst) + assert lst[i].name == tp.name + assert len(lst) == len(self._struct_unions) + # same with enums + lst = self._lsts["enum"] + for tp, i in self._enums.items(): + assert i < len(lst) + assert lst[i].name == tp.name + assert len(lst) == len(self._enums) + + # ---------- + + def _prnt(self, what=''): + self._f.write(what + '\n') + + def write_source_to_f(self, f, preamble): + if self.target_is_python: + assert preamble is None + self.write_py_source_to_f(f) + else: + assert preamble is not None + self.write_c_source_to_f(f, preamble) + + def _rel_readlines(self, filename): + g = open(os.path.join(os.path.dirname(__file__), filename), 'r') + lines = g.readlines() + g.close() + return lines + + def write_c_source_to_f(self, f, preamble): + self._f = f + prnt = self._prnt + if self.ffi._embedding is not None: + prnt('#define _CFFI_USE_EMBEDDING') + if not USE_LIMITED_API: + prnt('#define _CFFI_NO_LIMITED_API') + # + # first the '#include' (actually done by inlining the file's content) + lines = self._rel_readlines('_cffi_include.h') + i = lines.index('#include "parse_c_type.h"\n') + lines[i:i+1] = self._rel_readlines('parse_c_type.h') + prnt(''.join(lines)) + # + # if we have ffi._embedding != None, we give it here as a macro + # and include an extra file + base_module_name = self.module_name.split('.')[-1] + if self.ffi._embedding is not None: + prnt('#define _CFFI_MODULE_NAME "%s"' % (self.module_name,)) + prnt('static const char _CFFI_PYTHON_STARTUP_CODE[] = {') + self._print_string_literal_in_array(self.ffi._embedding) + prnt('0 };') + prnt('#ifdef PYPY_VERSION') + prnt('# define _CFFI_PYTHON_STARTUP_FUNC _cffi_pypyinit_%s' % ( + base_module_name,)) + prnt('#elif PY_MAJOR_VERSION >= 3') + prnt('# define _CFFI_PYTHON_STARTUP_FUNC PyInit_%s' % ( + base_module_name,)) + prnt('#else') + prnt('# define _CFFI_PYTHON_STARTUP_FUNC init%s' % ( + base_module_name,)) + prnt('#endif') + lines = self._rel_readlines('_embedding.h') + i = lines.index('#include "_cffi_errors.h"\n') + lines[i:i+1] = self._rel_readlines('_cffi_errors.h') + prnt(''.join(lines)) + self.needs_version(VERSION_EMBEDDED) + # + # then paste the C source given by the user, verbatim. + prnt('/************************************************************/') + prnt() + prnt(preamble) + prnt() + prnt('/************************************************************/') + prnt() + # + # the declaration of '_cffi_types' + prnt('static void *_cffi_types[] = {') + typeindex2type = dict([(i, tp) for (tp, i) in self._typesdict.items()]) + for i, op in enumerate(self.cffi_types): + comment = '' + if i in typeindex2type: + comment = ' // ' + typeindex2type[i]._get_c_name() + prnt('/* %2d */ %s,%s' % (i, op.as_c_expr(), comment)) + if not self.cffi_types: + prnt(' 0') + prnt('};') + prnt() + # + # call generate_cpy_xxx_decl(), for every xxx found from + # ffi._parser._declarations. This generates all the functions. + self._seen_constants = set() + self._generate("decl") + # + # the declaration of '_cffi_globals' and '_cffi_typenames' + nums = {} + for step_name in self.ALL_STEPS: + lst = self._lsts[step_name] + nums[step_name] = len(lst) + if nums[step_name] > 0: + prnt('static const struct _cffi_%s_s _cffi_%ss[] = {' % ( + step_name, step_name)) + for entry in lst: + prnt(entry.as_c_expr()) + prnt('};') + prnt() + # + # the declaration of '_cffi_includes' + if self.ffi._included_ffis: + prnt('static const char * const _cffi_includes[] = {') + for ffi_to_include in self.ffi._included_ffis: + try: + included_module_name, included_source = ( + ffi_to_include._assigned_source[:2]) + except AttributeError: + raise VerificationError( + "ffi object %r includes %r, but the latter has not " + "been prepared with set_source()" % ( + self.ffi, ffi_to_include,)) + if included_source is None: + raise VerificationError( + "not implemented yet: ffi.include() of a Python-based " + "ffi inside a C-based ffi") + prnt(' "%s",' % (included_module_name,)) + prnt(' NULL') + prnt('};') + prnt() + # + # the declaration of '_cffi_type_context' + prnt('static const struct _cffi_type_context_s _cffi_type_context = {') + prnt(' _cffi_types,') + for step_name in self.ALL_STEPS: + if nums[step_name] > 0: + prnt(' _cffi_%ss,' % step_name) + else: + prnt(' NULL, /* no %ss */' % step_name) + for step_name in self.ALL_STEPS: + if step_name != "field": + prnt(' %d, /* num_%ss */' % (nums[step_name], step_name)) + if self.ffi._included_ffis: + prnt(' _cffi_includes,') + else: + prnt(' NULL, /* no includes */') + prnt(' %d, /* num_types */' % (len(self.cffi_types),)) + flags = 0 + if self._num_externpy > 0 or self.ffi._embedding is not None: + flags |= 1 # set to mean that we use extern "Python" + prnt(' %d, /* flags */' % flags) + prnt('};') + prnt() + # + # the init function + prnt('#ifdef __GNUC__') + prnt('# pragma GCC visibility push(default) /* for -fvisibility= */') + prnt('#endif') + prnt() + prnt('#ifdef PYPY_VERSION') + prnt('PyMODINIT_FUNC') + prnt('_cffi_pypyinit_%s(const void *p[])' % (base_module_name,)) + prnt('{') + if flags & 1: + prnt(' if (((intptr_t)p[0]) >= 0x0A03) {') + prnt(' _cffi_call_python_org = ' + '(void(*)(struct _cffi_externpy_s *, char *))p[1];') + prnt(' }') + prnt(' p[0] = (const void *)0x%x;' % self._version) + prnt(' p[1] = &_cffi_type_context;') + prnt('#if PY_MAJOR_VERSION >= 3') + prnt(' return NULL;') + prnt('#endif') + prnt('}') + # on Windows, distutils insists on putting init_cffi_xyz in + # 'export_symbols', so instead of fighting it, just give up and + # give it one + prnt('# ifdef _MSC_VER') + prnt(' PyMODINIT_FUNC') + prnt('# if PY_MAJOR_VERSION >= 3') + prnt(' PyInit_%s(void) { return NULL; }' % (base_module_name,)) + prnt('# else') + prnt(' init%s(void) { }' % (base_module_name,)) + prnt('# endif') + prnt('# endif') + prnt('#elif PY_MAJOR_VERSION >= 3') + prnt('PyMODINIT_FUNC') + prnt('PyInit_%s(void)' % (base_module_name,)) + prnt('{') + prnt(' return _cffi_init("%s", 0x%x, &_cffi_type_context);' % ( + self.module_name, self._version)) + prnt('}') + prnt('#else') + prnt('PyMODINIT_FUNC') + prnt('init%s(void)' % (base_module_name,)) + prnt('{') + prnt(' _cffi_init("%s", 0x%x, &_cffi_type_context);' % ( + self.module_name, self._version)) + prnt('}') + prnt('#endif') + prnt() + prnt('#ifdef __GNUC__') + prnt('# pragma GCC visibility pop') + prnt('#endif') + self._version = None + + def _to_py(self, x): + if isinstance(x, str): + return "b'%s'" % (x,) + if isinstance(x, (list, tuple)): + rep = [self._to_py(item) for item in x] + if len(rep) == 1: + rep.append('') + return "(%s)" % (','.join(rep),) + return x.as_python_expr() # Py2: unicode unexpected; Py3: bytes unexp. + + def write_py_source_to_f(self, f): + self._f = f + prnt = self._prnt + # + # header + prnt("# auto-generated file") + prnt("import _cffi_backend") + # + # the 'import' of the included ffis + num_includes = len(self.ffi._included_ffis or ()) + for i in range(num_includes): + ffi_to_include = self.ffi._included_ffis[i] + try: + included_module_name, included_source = ( + ffi_to_include._assigned_source[:2]) + except AttributeError: + raise VerificationError( + "ffi object %r includes %r, but the latter has not " + "been prepared with set_source()" % ( + self.ffi, ffi_to_include,)) + if included_source is not None: + raise VerificationError( + "not implemented yet: ffi.include() of a C-based " + "ffi inside a Python-based ffi") + prnt('from %s import ffi as _ffi%d' % (included_module_name, i)) + prnt() + prnt("ffi = _cffi_backend.FFI('%s'," % (self.module_name,)) + prnt(" _version = 0x%x," % (self._version,)) + self._version = None + # + # the '_types' keyword argument + self.cffi_types = tuple(self.cffi_types) # don't change any more + types_lst = [op.as_python_bytes() for op in self.cffi_types] + prnt(' _types = %s,' % (self._to_py(''.join(types_lst)),)) + typeindex2type = dict([(i, tp) for (tp, i) in self._typesdict.items()]) + # + # the keyword arguments from ALL_STEPS + for step_name in self.ALL_STEPS: + lst = self._lsts[step_name] + if len(lst) > 0 and step_name != "field": + prnt(' _%ss = %s,' % (step_name, self._to_py(lst))) + # + # the '_includes' keyword argument + if num_includes > 0: + prnt(' _includes = (%s,),' % ( + ', '.join(['_ffi%d' % i for i in range(num_includes)]),)) + # + # the footer + prnt(')') + + # ---------- + + def _gettypenum(self, type): + # a KeyError here is a bug. please report it! :-) + return self._typesdict[type] + + def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode): + extraarg = '' + if isinstance(tp, model.BasePrimitiveType) and not tp.is_complex_type(): + if tp.is_integer_type() and tp.name != '_Bool': + converter = '_cffi_to_c_int' + extraarg = ', %s' % tp.name + elif isinstance(tp, model.UnknownFloatType): + # don't check with is_float_type(): it may be a 'long + # double' here, and _cffi_to_c_double would loose precision + converter = '(%s)_cffi_to_c_double' % (tp.get_c_name(''),) + else: + cname = tp.get_c_name('') + converter = '(%s)_cffi_to_c_%s' % (cname, + tp.name.replace(' ', '_')) + if cname in ('char16_t', 'char32_t'): + self.needs_version(VERSION_CHAR16CHAR32) + errvalue = '-1' + # + elif isinstance(tp, model.PointerType): + self._convert_funcarg_to_c_ptr_or_array(tp, fromvar, + tovar, errcode) + return + # + elif (isinstance(tp, model.StructOrUnionOrEnum) or + isinstance(tp, model.BasePrimitiveType)): + # a struct (not a struct pointer) as a function argument; + # or, a complex (the same code works) + self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)' + % (tovar, self._gettypenum(tp), fromvar)) + self._prnt(' %s;' % errcode) + return + # + elif isinstance(tp, model.FunctionPtrType): + converter = '(%s)_cffi_to_c_pointer' % tp.get_c_name('') + extraarg = ', _cffi_type(%d)' % self._gettypenum(tp) + errvalue = 'NULL' + # + else: + raise NotImplementedError(tp) + # + self._prnt(' %s = %s(%s%s);' % (tovar, converter, fromvar, extraarg)) + self._prnt(' if (%s == (%s)%s && PyErr_Occurred())' % ( + tovar, tp.get_c_name(''), errvalue)) + self._prnt(' %s;' % errcode) + + def _extra_local_variables(self, tp, localvars, freelines): + if isinstance(tp, model.PointerType): + localvars.add('Py_ssize_t datasize') + localvars.add('struct _cffi_freeme_s *large_args_free = NULL') + freelines.add('if (large_args_free != NULL)' + ' _cffi_free_array_arguments(large_args_free);') + + def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode): + self._prnt(' datasize = _cffi_prepare_pointer_call_argument(') + self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % ( + self._gettypenum(tp), fromvar, tovar)) + self._prnt(' if (datasize != 0) {') + self._prnt(' %s = ((size_t)datasize) <= 640 ? ' + '(%s)alloca((size_t)datasize) : NULL;' % ( + tovar, tp.get_c_name(''))) + self._prnt(' if (_cffi_convert_array_argument(_cffi_type(%d), %s, ' + '(char **)&%s,' % (self._gettypenum(tp), fromvar, tovar)) + self._prnt(' datasize, &large_args_free) < 0)') + self._prnt(' %s;' % errcode) + self._prnt(' }') + + def _convert_expr_from_c(self, tp, var, context): + if isinstance(tp, model.BasePrimitiveType): + if tp.is_integer_type() and tp.name != '_Bool': + return '_cffi_from_c_int(%s, %s)' % (var, tp.name) + elif isinstance(tp, model.UnknownFloatType): + return '_cffi_from_c_double(%s)' % (var,) + elif tp.name != 'long double' and not tp.is_complex_type(): + cname = tp.name.replace(' ', '_') + if cname in ('char16_t', 'char32_t'): + self.needs_version(VERSION_CHAR16CHAR32) + return '_cffi_from_c_%s(%s)' % (cname, var) + else: + return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( + var, self._gettypenum(tp)) + elif isinstance(tp, (model.PointerType, model.FunctionPtrType)): + return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( + var, self._gettypenum(tp)) + elif isinstance(tp, model.ArrayType): + return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( + var, self._gettypenum(model.PointerType(tp.item))) + elif isinstance(tp, model.StructOrUnion): + if tp.fldnames is None: + raise TypeError("'%s' is used as %s, but is opaque" % ( + tp._get_c_name(), context)) + return '_cffi_from_c_struct((char *)&%s, _cffi_type(%d))' % ( + var, self._gettypenum(tp)) + elif isinstance(tp, model.EnumType): + return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( + var, self._gettypenum(tp)) + else: + raise NotImplementedError(tp) + + # ---------- + # typedefs + + def _typedef_type(self, tp, name): + return self._global_type(tp, "(*(%s *)0)" % (name,)) + + def _generate_cpy_typedef_collecttype(self, tp, name): + self._do_collect_type(self._typedef_type(tp, name)) + + def _generate_cpy_typedef_decl(self, tp, name): + pass + + def _typedef_ctx(self, tp, name): + type_index = self._typesdict[tp] + self._lsts["typename"].append(TypenameExpr(name, type_index)) + + def _generate_cpy_typedef_ctx(self, tp, name): + tp = self._typedef_type(tp, name) + self._typedef_ctx(tp, name) + if getattr(tp, "origin", None) == "unknown_type": + self._struct_ctx(tp, tp.name, approxname=None) + elif isinstance(tp, model.NamedPointerType): + self._struct_ctx(tp.totype, tp.totype.name, approxname=tp.name, + named_ptr=tp) + + # ---------- + # function declarations + + def _generate_cpy_function_collecttype(self, tp, name): + self._do_collect_type(tp.as_raw_function()) + if tp.ellipsis and not self.target_is_python: + self._do_collect_type(tp) + + def _generate_cpy_function_decl(self, tp, name): + assert not self.target_is_python + assert isinstance(tp, model.FunctionPtrType) + if tp.ellipsis: + # cannot support vararg functions better than this: check for its + # exact type (including the fixed arguments), and build it as a + # constant function pointer (no CPython wrapper) + self._generate_cpy_constant_decl(tp, name) + return + prnt = self._prnt + numargs = len(tp.args) + if numargs == 0: + argname = 'noarg' + elif numargs == 1: + argname = 'arg0' + else: + argname = 'args' + # + # ------------------------------ + # the 'd' version of the function, only for addressof(lib, 'func') + arguments = [] + call_arguments = [] + context = 'argument of %s' % name + for i, type in enumerate(tp.args): + arguments.append(type.get_c_name(' x%d' % i, context)) + call_arguments.append('x%d' % i) + repr_arguments = ', '.join(arguments) + repr_arguments = repr_arguments or 'void' + if tp.abi: + abi = tp.abi + ' ' + else: + abi = '' + name_and_arguments = '%s_cffi_d_%s(%s)' % (abi, name, repr_arguments) + prnt('static %s' % (tp.result.get_c_name(name_and_arguments),)) + prnt('{') + call_arguments = ', '.join(call_arguments) + result_code = 'return ' + if isinstance(tp.result, model.VoidType): + result_code = '' + prnt(' %s%s(%s);' % (result_code, name, call_arguments)) + prnt('}') + # + prnt('#ifndef PYPY_VERSION') # ------------------------------ + # + prnt('static PyObject *') + prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname)) + prnt('{') + # + context = 'argument of %s' % name + for i, type in enumerate(tp.args): + arg = type.get_c_name(' x%d' % i, context) + prnt(' %s;' % arg) + # + localvars = set() + freelines = set() + for type in tp.args: + self._extra_local_variables(type, localvars, freelines) + for decl in sorted(localvars): + prnt(' %s;' % (decl,)) + # + if not isinstance(tp.result, model.VoidType): + result_code = 'result = ' + context = 'result of %s' % name + result_decl = ' %s;' % tp.result.get_c_name(' result', context) + prnt(result_decl) + prnt(' PyObject *pyresult;') + else: + result_decl = None + result_code = '' + # + if len(tp.args) > 1: + rng = range(len(tp.args)) + for i in rng: + prnt(' PyObject *arg%d;' % i) + prnt() + prnt(' if (!PyArg_UnpackTuple(args, "%s", %d, %d, %s))' % ( + name, len(rng), len(rng), + ', '.join(['&arg%d' % i for i in rng]))) + prnt(' return NULL;') + prnt() + # + for i, type in enumerate(tp.args): + self._convert_funcarg_to_c(type, 'arg%d' % i, 'x%d' % i, + 'return NULL') + prnt() + # + prnt(' Py_BEGIN_ALLOW_THREADS') + prnt(' _cffi_restore_errno();') + call_arguments = ['x%d' % i for i in range(len(tp.args))] + call_arguments = ', '.join(call_arguments) + prnt(' { %s%s(%s); }' % (result_code, name, call_arguments)) + prnt(' _cffi_save_errno();') + prnt(' Py_END_ALLOW_THREADS') + prnt() + # + prnt(' (void)self; /* unused */') + if numargs == 0: + prnt(' (void)noarg; /* unused */') + if result_code: + prnt(' pyresult = %s;' % + self._convert_expr_from_c(tp.result, 'result', 'result type')) + for freeline in freelines: + prnt(' ' + freeline) + prnt(' return pyresult;') + else: + for freeline in freelines: + prnt(' ' + freeline) + prnt(' Py_INCREF(Py_None);') + prnt(' return Py_None;') + prnt('}') + # + prnt('#else') # ------------------------------ + # + # the PyPy version: need to replace struct/union arguments with + # pointers, and if the result is a struct/union, insert a first + # arg that is a pointer to the result. We also do that for + # complex args and return type. + def need_indirection(type): + return (isinstance(type, model.StructOrUnion) or + (isinstance(type, model.PrimitiveType) and + type.is_complex_type())) + difference = False + arguments = [] + call_arguments = [] + context = 'argument of %s' % name + for i, type in enumerate(tp.args): + indirection = '' + if need_indirection(type): + indirection = '*' + difference = True + arg = type.get_c_name(' %sx%d' % (indirection, i), context) + arguments.append(arg) + call_arguments.append('%sx%d' % (indirection, i)) + tp_result = tp.result + if need_indirection(tp_result): + context = 'result of %s' % name + arg = tp_result.get_c_name(' *result', context) + arguments.insert(0, arg) + tp_result = model.void_type + result_decl = None + result_code = '*result = ' + difference = True + if difference: + repr_arguments = ', '.join(arguments) + repr_arguments = repr_arguments or 'void' + name_and_arguments = '%s_cffi_f_%s(%s)' % (abi, name, + repr_arguments) + prnt('static %s' % (tp_result.get_c_name(name_and_arguments),)) + prnt('{') + if result_decl: + prnt(result_decl) + call_arguments = ', '.join(call_arguments) + prnt(' { %s%s(%s); }' % (result_code, name, call_arguments)) + if result_decl: + prnt(' return result;') + prnt('}') + else: + prnt('# define _cffi_f_%s _cffi_d_%s' % (name, name)) + # + prnt('#endif') # ------------------------------ + prnt() + + def _generate_cpy_function_ctx(self, tp, name): + if tp.ellipsis and not self.target_is_python: + self._generate_cpy_constant_ctx(tp, name) + return + type_index = self._typesdict[tp.as_raw_function()] + numargs = len(tp.args) + if self.target_is_python: + meth_kind = OP_DLOPEN_FUNC + elif numargs == 0: + meth_kind = OP_CPYTHON_BLTN_N # 'METH_NOARGS' + elif numargs == 1: + meth_kind = OP_CPYTHON_BLTN_O # 'METH_O' + else: + meth_kind = OP_CPYTHON_BLTN_V # 'METH_VARARGS' + self._lsts["global"].append( + GlobalExpr(name, '_cffi_f_%s' % name, + CffiOp(meth_kind, type_index), + size='_cffi_d_%s' % name)) + + # ---------- + # named structs or unions + + def _field_type(self, tp_struct, field_name, tp_field): + if isinstance(tp_field, model.ArrayType): + actual_length = tp_field.length + if actual_length == '...': + ptr_struct_name = tp_struct.get_c_name('*') + actual_length = '_cffi_array_len(((%s)0)->%s)' % ( + ptr_struct_name, field_name) + tp_item = self._field_type(tp_struct, '%s[0]' % field_name, + tp_field.item) + tp_field = model.ArrayType(tp_item, actual_length) + return tp_field + + def _struct_collecttype(self, tp): + self._do_collect_type(tp) + if self.target_is_python: + # also requires nested anon struct/unions in ABI mode, recursively + for fldtype in tp.anonymous_struct_fields(): + self._struct_collecttype(fldtype) + + def _struct_decl(self, tp, cname, approxname): + if tp.fldtypes is None: + return + prnt = self._prnt + checkfuncname = '_cffi_checkfld_%s' % (approxname,) + prnt('_CFFI_UNUSED_FN') + prnt('static void %s(%s *p)' % (checkfuncname, cname)) + prnt('{') + prnt(' /* only to generate compile-time warnings or errors */') + prnt(' (void)p;') + for fname, ftype, fbitsize, fqual in self._enum_fields(tp): + try: + if ftype.is_integer_type() or fbitsize >= 0: + # accept all integers, but complain on float or double + if fname != '': + prnt(" (void)((p->%s) | 0); /* check that '%s.%s' is " + "an integer */" % (fname, cname, fname)) + continue + # only accept exactly the type declared, except that '[]' + # is interpreted as a '*' and so will match any array length. + # (It would also match '*', but that's harder to detect...) + while (isinstance(ftype, model.ArrayType) + and (ftype.length is None or ftype.length == '...')): + ftype = ftype.item + fname = fname + '[0]' + prnt(' { %s = &p->%s; (void)tmp; }' % ( + ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual), + fname)) + except VerificationError as e: + prnt(' /* %s */' % str(e)) # cannot verify it, ignore + prnt('}') + prnt('struct _cffi_align_%s { char x; %s y; };' % (approxname, cname)) + prnt() + + def _struct_ctx(self, tp, cname, approxname, named_ptr=None): + type_index = self._typesdict[tp] + reason_for_not_expanding = None + flags = [] + if isinstance(tp, model.UnionType): + flags.append("_CFFI_F_UNION") + if tp.fldtypes is None: + flags.append("_CFFI_F_OPAQUE") + reason_for_not_expanding = "opaque" + if (tp not in self.ffi._parser._included_declarations and + (named_ptr is None or + named_ptr not in self.ffi._parser._included_declarations)): + if tp.fldtypes is None: + pass # opaque + elif tp.partial or any(tp.anonymous_struct_fields()): + pass # field layout obtained silently from the C compiler + else: + flags.append("_CFFI_F_CHECK_FIELDS") + if tp.packed: + if tp.packed > 1: + raise NotImplementedError( + "%r is declared with 'pack=%r'; only 0 or 1 are " + "supported in API mode (try to use \"...;\", which " + "does not require a 'pack' declaration)" % + (tp, tp.packed)) + flags.append("_CFFI_F_PACKED") + else: + flags.append("_CFFI_F_EXTERNAL") + reason_for_not_expanding = "external" + flags = '|'.join(flags) or '0' + c_fields = [] + if reason_for_not_expanding is None: + enumfields = list(self._enum_fields(tp)) + for fldname, fldtype, fbitsize, fqual in enumfields: + fldtype = self._field_type(tp, fldname, fldtype) + self._check_not_opaque(fldtype, + "field '%s.%s'" % (tp.name, fldname)) + # cname is None for _add_missing_struct_unions() only + op = OP_NOOP + if fbitsize >= 0: + op = OP_BITFIELD + size = '%d /* bits */' % fbitsize + elif cname is None or ( + isinstance(fldtype, model.ArrayType) and + fldtype.length is None): + size = '(size_t)-1' + else: + size = 'sizeof(((%s)0)->%s)' % ( + tp.get_c_name('*') if named_ptr is None + else named_ptr.name, + fldname) + if cname is None or fbitsize >= 0: + offset = '(size_t)-1' + elif named_ptr is not None: + offset = '((char *)&((%s)0)->%s) - (char *)0' % ( + named_ptr.name, fldname) + else: + offset = 'offsetof(%s, %s)' % (tp.get_c_name(''), fldname) + c_fields.append( + FieldExpr(fldname, offset, size, fbitsize, + CffiOp(op, self._typesdict[fldtype]))) + first_field_index = len(self._lsts["field"]) + self._lsts["field"].extend(c_fields) + # + if cname is None: # unknown name, for _add_missing_struct_unions + size = '(size_t)-2' + align = -2 + comment = "unnamed" + else: + if named_ptr is not None: + size = 'sizeof(*(%s)0)' % (named_ptr.name,) + align = '-1 /* unknown alignment */' + else: + size = 'sizeof(%s)' % (cname,) + align = 'offsetof(struct _cffi_align_%s, y)' % (approxname,) + comment = None + else: + size = '(size_t)-1' + align = -1 + first_field_index = -1 + comment = reason_for_not_expanding + self._lsts["struct_union"].append( + StructUnionExpr(tp.name, type_index, flags, size, align, comment, + first_field_index, c_fields)) + self._seen_struct_unions.add(tp) + + def _check_not_opaque(self, tp, location): + while isinstance(tp, model.ArrayType): + tp = tp.item + if isinstance(tp, model.StructOrUnion) and tp.fldtypes is None: + raise TypeError( + "%s is of an opaque type (not declared in cdef())" % location) + + def _add_missing_struct_unions(self): + # not very nice, but some struct declarations might be missing + # because they don't have any known C name. Check that they are + # not partial (we can't complete or verify them!) and emit them + # anonymously. + lst = list(self._struct_unions.items()) + lst.sort(key=lambda tp_order: tp_order[1]) + for tp, order in lst: + if tp not in self._seen_struct_unions: + if tp.partial: + raise NotImplementedError("internal inconsistency: %r is " + "partial but was not seen at " + "this point" % (tp,)) + if tp.name.startswith('$') and tp.name[1:].isdigit(): + approxname = tp.name[1:] + elif tp.name == '_IO_FILE' and tp.forcename == 'FILE': + approxname = 'FILE' + self._typedef_ctx(tp, 'FILE') + else: + raise NotImplementedError("internal inconsistency: %r" % + (tp,)) + self._struct_ctx(tp, None, approxname) + + def _generate_cpy_struct_collecttype(self, tp, name): + self._struct_collecttype(tp) + _generate_cpy_union_collecttype = _generate_cpy_struct_collecttype + + def _struct_names(self, tp): + cname = tp.get_c_name('') + if ' ' in cname: + return cname, cname.replace(' ', '_') + else: + return cname, '_' + cname + + def _generate_cpy_struct_decl(self, tp, name): + self._struct_decl(tp, *self._struct_names(tp)) + _generate_cpy_union_decl = _generate_cpy_struct_decl + + def _generate_cpy_struct_ctx(self, tp, name): + self._struct_ctx(tp, *self._struct_names(tp)) + _generate_cpy_union_ctx = _generate_cpy_struct_ctx + + # ---------- + # 'anonymous' declarations. These are produced for anonymous structs + # or unions; the 'name' is obtained by a typedef. + + def _generate_cpy_anonymous_collecttype(self, tp, name): + if isinstance(tp, model.EnumType): + self._generate_cpy_enum_collecttype(tp, name) + else: + self._struct_collecttype(tp) + + def _generate_cpy_anonymous_decl(self, tp, name): + if isinstance(tp, model.EnumType): + self._generate_cpy_enum_decl(tp) + else: + self._struct_decl(tp, name, 'typedef_' + name) + + def _generate_cpy_anonymous_ctx(self, tp, name): + if isinstance(tp, model.EnumType): + self._enum_ctx(tp, name) + else: + self._struct_ctx(tp, name, 'typedef_' + name) + + # ---------- + # constants, declared with "static const ..." + + def _generate_cpy_const(self, is_int, name, tp=None, category='const', + check_value=None): + if (category, name) in self._seen_constants: + raise VerificationError( + "duplicate declaration of %s '%s'" % (category, name)) + self._seen_constants.add((category, name)) + # + prnt = self._prnt + funcname = '_cffi_%s_%s' % (category, name) + if is_int: + prnt('static int %s(unsigned long long *o)' % funcname) + prnt('{') + prnt(' int n = (%s) <= 0;' % (name,)) + prnt(' *o = (unsigned long long)((%s) | 0);' + ' /* check that %s is an integer */' % (name, name)) + if check_value is not None: + if check_value > 0: + check_value = '%dU' % (check_value,) + prnt(' if (!_cffi_check_int(*o, n, %s))' % (check_value,)) + prnt(' n |= 2;') + prnt(' return n;') + prnt('}') + else: + assert check_value is None + prnt('static void %s(char *o)' % funcname) + prnt('{') + prnt(' *(%s)o = %s;' % (tp.get_c_name('*'), name)) + prnt('}') + prnt() + + def _generate_cpy_constant_collecttype(self, tp, name): + is_int = tp.is_integer_type() + if not is_int or self.target_is_python: + self._do_collect_type(tp) + + def _generate_cpy_constant_decl(self, tp, name): + is_int = tp.is_integer_type() + self._generate_cpy_const(is_int, name, tp) + + def _generate_cpy_constant_ctx(self, tp, name): + if not self.target_is_python and tp.is_integer_type(): + type_op = CffiOp(OP_CONSTANT_INT, -1) + else: + if self.target_is_python: + const_kind = OP_DLOPEN_CONST + else: + const_kind = OP_CONSTANT + type_index = self._typesdict[tp] + type_op = CffiOp(const_kind, type_index) + self._lsts["global"].append( + GlobalExpr(name, '_cffi_const_%s' % name, type_op)) + + # ---------- + # enums + + def _generate_cpy_enum_collecttype(self, tp, name): + self._do_collect_type(tp) + + def _generate_cpy_enum_decl(self, tp, name=None): + for enumerator in tp.enumerators: + self._generate_cpy_const(True, enumerator) + + def _enum_ctx(self, tp, cname): + type_index = self._typesdict[tp] + type_op = CffiOp(OP_ENUM, -1) + if self.target_is_python: + tp.check_not_partial() + for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): + self._lsts["global"].append( + GlobalExpr(enumerator, '_cffi_const_%s' % enumerator, type_op, + check_value=enumvalue)) + # + if cname is not None and '$' not in cname and not self.target_is_python: + size = "sizeof(%s)" % cname + signed = "((%s)-1) <= 0" % cname + else: + basetp = tp.build_baseinttype(self.ffi, []) + size = self.ffi.sizeof(basetp) + signed = int(int(self.ffi.cast(basetp, -1)) < 0) + allenums = ",".join(tp.enumerators) + self._lsts["enum"].append( + EnumExpr(tp.name, type_index, size, signed, allenums)) + + def _generate_cpy_enum_ctx(self, tp, name): + self._enum_ctx(tp, tp._get_c_name()) + + # ---------- + # macros: for now only for integers + + def _generate_cpy_macro_collecttype(self, tp, name): + pass + + def _generate_cpy_macro_decl(self, tp, name): + if tp == '...': + check_value = None + else: + check_value = tp # an integer + self._generate_cpy_const(True, name, check_value=check_value) + + def _generate_cpy_macro_ctx(self, tp, name): + if tp == '...': + if self.target_is_python: + raise VerificationError( + "cannot use the syntax '...' in '#define %s ...' when " + "using the ABI mode" % (name,)) + check_value = None + else: + check_value = tp # an integer + type_op = CffiOp(OP_CONSTANT_INT, -1) + self._lsts["global"].append( + GlobalExpr(name, '_cffi_const_%s' % name, type_op, + check_value=check_value)) + + # ---------- + # global variables + + def _global_type(self, tp, global_name): + if isinstance(tp, model.ArrayType): + actual_length = tp.length + if actual_length == '...': + actual_length = '_cffi_array_len(%s)' % (global_name,) + tp_item = self._global_type(tp.item, '%s[0]' % global_name) + tp = model.ArrayType(tp_item, actual_length) + return tp + + def _generate_cpy_variable_collecttype(self, tp, name): + self._do_collect_type(self._global_type(tp, name)) + + def _generate_cpy_variable_decl(self, tp, name): + prnt = self._prnt + tp = self._global_type(tp, name) + if isinstance(tp, model.ArrayType) and tp.length is None: + tp = tp.item + ampersand = '' + else: + ampersand = '&' + # This code assumes that casts from "tp *" to "void *" is a + # no-op, i.e. a function that returns a "tp *" can be called + # as if it returned a "void *". This should be generally true + # on any modern machine. The only exception to that rule (on + # uncommon architectures, and as far as I can tell) might be + # if 'tp' were a function type, but that is not possible here. + # (If 'tp' is a function _pointer_ type, then casts from "fn_t + # **" to "void *" are again no-ops, as far as I can tell.) + decl = '*_cffi_var_%s(void)' % (name,) + prnt('static ' + tp.get_c_name(decl, quals=self._current_quals)) + prnt('{') + prnt(' return %s(%s);' % (ampersand, name)) + prnt('}') + prnt() + + def _generate_cpy_variable_ctx(self, tp, name): + tp = self._global_type(tp, name) + type_index = self._typesdict[tp] + if self.target_is_python: + op = OP_GLOBAL_VAR + else: + op = OP_GLOBAL_VAR_F + self._lsts["global"].append( + GlobalExpr(name, '_cffi_var_%s' % name, CffiOp(op, type_index))) + + # ---------- + # extern "Python" + + def _generate_cpy_extern_python_collecttype(self, tp, name): + assert isinstance(tp, model.FunctionPtrType) + self._do_collect_type(tp) + _generate_cpy_dllexport_python_collecttype = \ + _generate_cpy_extern_python_plus_c_collecttype = \ + _generate_cpy_extern_python_collecttype + + def _extern_python_decl(self, tp, name, tag_and_space): + prnt = self._prnt + if isinstance(tp.result, model.VoidType): + size_of_result = '0' + else: + context = 'result of %s' % name + size_of_result = '(int)sizeof(%s)' % ( + tp.result.get_c_name('', context),) + prnt('static struct _cffi_externpy_s _cffi_externpy__%s =' % name) + prnt(' { "%s.%s", %s, 0, 0 };' % ( + self.module_name, name, size_of_result)) + prnt() + # + arguments = [] + context = 'argument of %s' % name + for i, type in enumerate(tp.args): + arg = type.get_c_name(' a%d' % i, context) + arguments.append(arg) + # + repr_arguments = ', '.join(arguments) + repr_arguments = repr_arguments or 'void' + name_and_arguments = '%s(%s)' % (name, repr_arguments) + if tp.abi == "__stdcall": + name_and_arguments = '_cffi_stdcall ' + name_and_arguments + # + def may_need_128_bits(tp): + return (isinstance(tp, model.PrimitiveType) and + tp.name == 'long double') + # + size_of_a = max(len(tp.args)*8, 8) + if may_need_128_bits(tp.result): + size_of_a = max(size_of_a, 16) + if isinstance(tp.result, model.StructOrUnion): + size_of_a = 'sizeof(%s) > %d ? sizeof(%s) : %d' % ( + tp.result.get_c_name(''), size_of_a, + tp.result.get_c_name(''), size_of_a) + prnt('%s%s' % (tag_and_space, tp.result.get_c_name(name_and_arguments))) + prnt('{') + prnt(' char a[%s];' % size_of_a) + prnt(' char *p = a;') + for i, type in enumerate(tp.args): + arg = 'a%d' % i + if (isinstance(type, model.StructOrUnion) or + may_need_128_bits(type)): + arg = '&' + arg + type = model.PointerType(type) + prnt(' *(%s)(p + %d) = %s;' % (type.get_c_name('*'), i*8, arg)) + prnt(' _cffi_call_python(&_cffi_externpy__%s, p);' % name) + if not isinstance(tp.result, model.VoidType): + prnt(' return *(%s)p;' % (tp.result.get_c_name('*'),)) + prnt('}') + prnt() + self._num_externpy += 1 + + def _generate_cpy_extern_python_decl(self, tp, name): + self._extern_python_decl(tp, name, 'static ') + + def _generate_cpy_dllexport_python_decl(self, tp, name): + self._extern_python_decl(tp, name, 'CFFI_DLLEXPORT ') + + def _generate_cpy_extern_python_plus_c_decl(self, tp, name): + self._extern_python_decl(tp, name, '') + + def _generate_cpy_extern_python_ctx(self, tp, name): + if self.target_is_python: + raise VerificationError( + "cannot use 'extern \"Python\"' in the ABI mode") + if tp.ellipsis: + raise NotImplementedError("a vararg function is extern \"Python\"") + type_index = self._typesdict[tp] + type_op = CffiOp(OP_EXTERN_PYTHON, type_index) + self._lsts["global"].append( + GlobalExpr(name, '&_cffi_externpy__%s' % name, type_op, name)) + + _generate_cpy_dllexport_python_ctx = \ + _generate_cpy_extern_python_plus_c_ctx = \ + _generate_cpy_extern_python_ctx + + def _print_string_literal_in_array(self, s): + prnt = self._prnt + prnt('// # NB. this is not a string because of a size limit in MSVC') + if not isinstance(s, bytes): # unicode + s = s.encode('utf-8') # -> bytes + else: + s.decode('utf-8') # got bytes, check for valid utf-8 + try: + s.decode('ascii') + except UnicodeDecodeError: + s = b'# -*- encoding: utf8 -*-\n' + s + for line in s.splitlines(True): + comment = line + if type('//') is bytes: # python2 + line = map(ord, line) # make a list of integers + else: # python3 + # type(line) is bytes, which enumerates like a list of integers + comment = ascii(comment)[1:-1] + prnt(('// ' + comment).rstrip()) + printed_line = '' + for c in line: + if len(printed_line) >= 76: + prnt(printed_line) + printed_line = '' + printed_line += '%d,' % (c,) + prnt(printed_line) + + # ---------- + # emitting the opcodes for individual types + + def _emit_bytecode_VoidType(self, tp, index): + self.cffi_types[index] = CffiOp(OP_PRIMITIVE, PRIM_VOID) + + def _emit_bytecode_PrimitiveType(self, tp, index): + prim_index = PRIMITIVE_TO_INDEX[tp.name] + self.cffi_types[index] = CffiOp(OP_PRIMITIVE, prim_index) + + def _emit_bytecode_UnknownIntegerType(self, tp, index): + s = ('_cffi_prim_int(sizeof(%s), (\n' + ' ((%s)-1) | 0 /* check that %s is an integer type */\n' + ' ) <= 0)' % (tp.name, tp.name, tp.name)) + self.cffi_types[index] = CffiOp(OP_PRIMITIVE, s) + + def _emit_bytecode_UnknownFloatType(self, tp, index): + s = ('_cffi_prim_float(sizeof(%s) *\n' + ' (((%s)1) / 2) * 2 /* integer => 0, float => 1 */\n' + ' )' % (tp.name, tp.name)) + self.cffi_types[index] = CffiOp(OP_PRIMITIVE, s) + + def _emit_bytecode_RawFunctionType(self, tp, index): + self.cffi_types[index] = CffiOp(OP_FUNCTION, self._typesdict[tp.result]) + index += 1 + for tp1 in tp.args: + realindex = self._typesdict[tp1] + if index != realindex: + if isinstance(tp1, model.PrimitiveType): + self._emit_bytecode_PrimitiveType(tp1, index) + else: + self.cffi_types[index] = CffiOp(OP_NOOP, realindex) + index += 1 + flags = int(tp.ellipsis) + if tp.abi is not None: + if tp.abi == '__stdcall': + flags |= 2 + else: + raise NotImplementedError("abi=%r" % (tp.abi,)) + self.cffi_types[index] = CffiOp(OP_FUNCTION_END, flags) + + def _emit_bytecode_PointerType(self, tp, index): + self.cffi_types[index] = CffiOp(OP_POINTER, self._typesdict[tp.totype]) + + _emit_bytecode_ConstPointerType = _emit_bytecode_PointerType + _emit_bytecode_NamedPointerType = _emit_bytecode_PointerType + + def _emit_bytecode_FunctionPtrType(self, tp, index): + raw = tp.as_raw_function() + self.cffi_types[index] = CffiOp(OP_POINTER, self._typesdict[raw]) + + def _emit_bytecode_ArrayType(self, tp, index): + item_index = self._typesdict[tp.item] + if tp.length is None: + self.cffi_types[index] = CffiOp(OP_OPEN_ARRAY, item_index) + elif tp.length == '...': + raise VerificationError( + "type %s badly placed: the '...' array length can only be " + "used on global arrays or on fields of structures" % ( + str(tp).replace('/*...*/', '...'),)) + else: + assert self.cffi_types[index + 1] == 'LEN' + self.cffi_types[index] = CffiOp(OP_ARRAY, item_index) + self.cffi_types[index + 1] = CffiOp(None, str(tp.length)) + + def _emit_bytecode_StructType(self, tp, index): + struct_index = self._struct_unions[tp] + self.cffi_types[index] = CffiOp(OP_STRUCT_UNION, struct_index) + _emit_bytecode_UnionType = _emit_bytecode_StructType + + def _emit_bytecode_EnumType(self, tp, index): + enum_index = self._enums[tp] + self.cffi_types[index] = CffiOp(OP_ENUM, enum_index) + + +if sys.version_info >= (3,): + NativeIO = io.StringIO +else: + class NativeIO(io.BytesIO): + def write(self, s): + if isinstance(s, unicode): + s = s.encode('ascii') + super(NativeIO, self).write(s) + +def _make_c_or_py_source(ffi, module_name, preamble, target_file, verbose): + if verbose: + print("generating %s" % (target_file,)) + recompiler = Recompiler(ffi, module_name, + target_is_python=(preamble is None)) + recompiler.collect_type_table() + recompiler.collect_step_tables() + f = NativeIO() + recompiler.write_source_to_f(f, preamble) + output = f.getvalue() + try: + with open(target_file, 'r') as f1: + if f1.read(len(output) + 1) != output: + raise IOError + if verbose: + print("(already up-to-date)") + return False # already up-to-date + except IOError: + tmp_file = '%s.~%d' % (target_file, os.getpid()) + with open(tmp_file, 'w') as f1: + f1.write(output) + try: + os.rename(tmp_file, target_file) + except OSError: + os.unlink(target_file) + os.rename(tmp_file, target_file) + return True + +def make_c_source(ffi, module_name, preamble, target_c_file, verbose=False): + assert preamble is not None + return _make_c_or_py_source(ffi, module_name, preamble, target_c_file, + verbose) + +def make_py_source(ffi, module_name, target_py_file, verbose=False): + return _make_c_or_py_source(ffi, module_name, None, target_py_file, + verbose) + +def _modname_to_file(outputdir, modname, extension): + parts = modname.split('.') + try: + os.makedirs(os.path.join(outputdir, *parts[:-1])) + except OSError: + pass + parts[-1] += extension + return os.path.join(outputdir, *parts), parts + + +# Aaargh. Distutils is not tested at all for the purpose of compiling +# DLLs that are not extension modules. Here are some hacks to work +# around that, in the _patch_for_*() functions... + +def _patch_meth(patchlist, cls, name, new_meth): + old = getattr(cls, name) + patchlist.append((cls, name, old)) + setattr(cls, name, new_meth) + return old + +def _unpatch_meths(patchlist): + for cls, name, old_meth in reversed(patchlist): + setattr(cls, name, old_meth) + +def _patch_for_embedding(patchlist): + if sys.platform == 'win32': + # we must not remove the manifest when building for embedding! + from cffi._shimmed_dist_utils import MSVCCompiler + _patch_meth(patchlist, MSVCCompiler, '_remove_visual_c_ref', + lambda self, manifest_file: manifest_file) + + if sys.platform == 'darwin': + # we must not make a '-bundle', but a '-dynamiclib' instead + from cffi._shimmed_dist_utils import CCompiler + def my_link_shared_object(self, *args, **kwds): + if '-bundle' in self.linker_so: + self.linker_so = list(self.linker_so) + i = self.linker_so.index('-bundle') + self.linker_so[i] = '-dynamiclib' + return old_link_shared_object(self, *args, **kwds) + old_link_shared_object = _patch_meth(patchlist, CCompiler, + 'link_shared_object', + my_link_shared_object) + +def _patch_for_target(patchlist, target): + from cffi._shimmed_dist_utils import build_ext + # if 'target' is different from '*', we need to patch some internal + # method to just return this 'target' value, instead of having it + # built from module_name + if target.endswith('.*'): + target = target[:-2] + if sys.platform == 'win32': + target += '.dll' + elif sys.platform == 'darwin': + target += '.dylib' + else: + target += '.so' + _patch_meth(patchlist, build_ext, 'get_ext_filename', + lambda self, ext_name: target) + + +def recompile(ffi, module_name, preamble, tmpdir='.', call_c_compiler=True, + c_file=None, source_extension='.c', extradir=None, + compiler_verbose=1, target=None, debug=None, **kwds): + if not isinstance(module_name, str): + module_name = module_name.encode('ascii') + if ffi._windows_unicode: + ffi._apply_windows_unicode(kwds) + if preamble is not None: + embedding = (ffi._embedding is not None) + if embedding: + ffi._apply_embedding_fix(kwds) + if c_file is None: + c_file, parts = _modname_to_file(tmpdir, module_name, + source_extension) + if extradir: + parts = [extradir] + parts + ext_c_file = os.path.join(*parts) + else: + ext_c_file = c_file + # + if target is None: + if embedding: + target = '%s.*' % module_name + else: + target = '*' + # + ext = ffiplatform.get_extension(ext_c_file, module_name, **kwds) + updated = make_c_source(ffi, module_name, preamble, c_file, + verbose=compiler_verbose) + if call_c_compiler: + patchlist = [] + cwd = os.getcwd() + try: + if embedding: + _patch_for_embedding(patchlist) + if target != '*': + _patch_for_target(patchlist, target) + if compiler_verbose: + if tmpdir == '.': + msg = 'the current directory is' + else: + msg = 'setting the current directory to' + print('%s %r' % (msg, os.path.abspath(tmpdir))) + os.chdir(tmpdir) + outputfilename = ffiplatform.compile('.', ext, + compiler_verbose, debug) + finally: + os.chdir(cwd) + _unpatch_meths(patchlist) + return outputfilename + else: + return ext, updated + else: + if c_file is None: + c_file, _ = _modname_to_file(tmpdir, module_name, '.py') + updated = make_py_source(ffi, module_name, c_file, + verbose=compiler_verbose) + if call_c_compiler: + return c_file + else: + return None, updated + diff --git a/.venv/Lib/site-packages/cffi/setuptools_ext.py b/.venv/Lib/site-packages/cffi/setuptools_ext.py new file mode 100644 index 00000000..681b49d7 --- /dev/null +++ b/.venv/Lib/site-packages/cffi/setuptools_ext.py @@ -0,0 +1,216 @@ +import os +import sys + +try: + basestring +except NameError: + # Python 3.x + basestring = str + +def error(msg): + from cffi._shimmed_dist_utils import DistutilsSetupError + raise DistutilsSetupError(msg) + + +def execfile(filename, glob): + # We use execfile() (here rewritten for Python 3) instead of + # __import__() to load the build script. The problem with + # a normal import is that in some packages, the intermediate + # __init__.py files may already try to import the file that + # we are generating. + with open(filename) as f: + src = f.read() + src += '\n' # Python 2.6 compatibility + code = compile(src, filename, 'exec') + exec(code, glob, glob) + + +def add_cffi_module(dist, mod_spec): + from cffi.api import FFI + + if not isinstance(mod_spec, basestring): + error("argument to 'cffi_modules=...' must be a str or a list of str," + " not %r" % (type(mod_spec).__name__,)) + mod_spec = str(mod_spec) + try: + build_file_name, ffi_var_name = mod_spec.split(':') + except ValueError: + error("%r must be of the form 'path/build.py:ffi_variable'" % + (mod_spec,)) + if not os.path.exists(build_file_name): + ext = '' + rewritten = build_file_name.replace('.', '/') + '.py' + if os.path.exists(rewritten): + ext = ' (rewrite cffi_modules to [%r])' % ( + rewritten + ':' + ffi_var_name,) + error("%r does not name an existing file%s" % (build_file_name, ext)) + + mod_vars = {'__name__': '__cffi__', '__file__': build_file_name} + execfile(build_file_name, mod_vars) + + try: + ffi = mod_vars[ffi_var_name] + except KeyError: + error("%r: object %r not found in module" % (mod_spec, + ffi_var_name)) + if not isinstance(ffi, FFI): + ffi = ffi() # maybe it's a function instead of directly an ffi + if not isinstance(ffi, FFI): + error("%r is not an FFI instance (got %r)" % (mod_spec, + type(ffi).__name__)) + if not hasattr(ffi, '_assigned_source'): + error("%r: the set_source() method was not called" % (mod_spec,)) + module_name, source, source_extension, kwds = ffi._assigned_source + if ffi._windows_unicode: + kwds = kwds.copy() + ffi._apply_windows_unicode(kwds) + + if source is None: + _add_py_module(dist, ffi, module_name) + else: + _add_c_module(dist, ffi, module_name, source, source_extension, kwds) + +def _set_py_limited_api(Extension, kwds): + """ + Add py_limited_api to kwds if setuptools >= 26 is in use. + Do not alter the setting if it already exists. + Setuptools takes care of ignoring the flag on Python 2 and PyPy. + + CPython itself should ignore the flag in a debugging version + (by not listing .abi3.so in the extensions it supports), but + it doesn't so far, creating troubles. That's why we check + for "not hasattr(sys, 'gettotalrefcount')" (the 2.7 compatible equivalent + of 'd' not in sys.abiflags). (http://bugs.python.org/issue28401) + + On Windows, with CPython <= 3.4, it's better not to use py_limited_api + because virtualenv *still* doesn't copy PYTHON3.DLL on these versions. + Recently (2020) we started shipping only >= 3.5 wheels, though. So + we'll give it another try and set py_limited_api on Windows >= 3.5. + """ + from cffi import recompiler + + if ('py_limited_api' not in kwds and not hasattr(sys, 'gettotalrefcount') + and recompiler.USE_LIMITED_API): + import setuptools + try: + setuptools_major_version = int(setuptools.__version__.partition('.')[0]) + if setuptools_major_version >= 26: + kwds['py_limited_api'] = True + except ValueError: # certain development versions of setuptools + # If we don't know the version number of setuptools, we + # try to set 'py_limited_api' anyway. At worst, we get a + # warning. + kwds['py_limited_api'] = True + return kwds + +def _add_c_module(dist, ffi, module_name, source, source_extension, kwds): + # We are a setuptools extension. Need this build_ext for py_limited_api. + from setuptools.command.build_ext import build_ext + from cffi._shimmed_dist_utils import Extension, log, mkpath + from cffi import recompiler + + allsources = ['$PLACEHOLDER'] + allsources.extend(kwds.pop('sources', [])) + kwds = _set_py_limited_api(Extension, kwds) + ext = Extension(name=module_name, sources=allsources, **kwds) + + def make_mod(tmpdir, pre_run=None): + c_file = os.path.join(tmpdir, module_name + source_extension) + log.info("generating cffi module %r" % c_file) + mkpath(tmpdir) + # a setuptools-only, API-only hook: called with the "ext" and "ffi" + # arguments just before we turn the ffi into C code. To use it, + # subclass the 'distutils.command.build_ext.build_ext' class and + # add a method 'def pre_run(self, ext, ffi)'. + if pre_run is not None: + pre_run(ext, ffi) + updated = recompiler.make_c_source(ffi, module_name, source, c_file) + if not updated: + log.info("already up-to-date") + return c_file + + if dist.ext_modules is None: + dist.ext_modules = [] + dist.ext_modules.append(ext) + + base_class = dist.cmdclass.get('build_ext', build_ext) + class build_ext_make_mod(base_class): + def run(self): + if ext.sources[0] == '$PLACEHOLDER': + pre_run = getattr(self, 'pre_run', None) + ext.sources[0] = make_mod(self.build_temp, pre_run) + base_class.run(self) + dist.cmdclass['build_ext'] = build_ext_make_mod + # NB. multiple runs here will create multiple 'build_ext_make_mod' + # classes. Even in this case the 'build_ext' command should be + # run once; but just in case, the logic above does nothing if + # called again. + + +def _add_py_module(dist, ffi, module_name): + from setuptools.command.build_py import build_py + from setuptools.command.build_ext import build_ext + from cffi._shimmed_dist_utils import log, mkpath + from cffi import recompiler + + def generate_mod(py_file): + log.info("generating cffi module %r" % py_file) + mkpath(os.path.dirname(py_file)) + updated = recompiler.make_py_source(ffi, module_name, py_file) + if not updated: + log.info("already up-to-date") + + base_class = dist.cmdclass.get('build_py', build_py) + class build_py_make_mod(base_class): + def run(self): + base_class.run(self) + module_path = module_name.split('.') + module_path[-1] += '.py' + generate_mod(os.path.join(self.build_lib, *module_path)) + def get_source_files(self): + # This is called from 'setup.py sdist' only. Exclude + # the generate .py module in this case. + saved_py_modules = self.py_modules + try: + if saved_py_modules: + self.py_modules = [m for m in saved_py_modules + if m != module_name] + return base_class.get_source_files(self) + finally: + self.py_modules = saved_py_modules + dist.cmdclass['build_py'] = build_py_make_mod + + # distutils and setuptools have no notion I could find of a + # generated python module. If we don't add module_name to + # dist.py_modules, then things mostly work but there are some + # combination of options (--root and --record) that will miss + # the module. So we add it here, which gives a few apparently + # harmless warnings about not finding the file outside the + # build directory. + # Then we need to hack more in get_source_files(); see above. + if dist.py_modules is None: + dist.py_modules = [] + dist.py_modules.append(module_name) + + # the following is only for "build_ext -i" + base_class_2 = dist.cmdclass.get('build_ext', build_ext) + class build_ext_make_mod(base_class_2): + def run(self): + base_class_2.run(self) + if self.inplace: + # from get_ext_fullpath() in distutils/command/build_ext.py + module_path = module_name.split('.') + package = '.'.join(module_path[:-1]) + build_py = self.get_finalized_command('build_py') + package_dir = build_py.get_package_dir(package) + file_name = module_path[-1] + '.py' + generate_mod(os.path.join(package_dir, file_name)) + dist.cmdclass['build_ext'] = build_ext_make_mod + +def cffi_modules(dist, attr, value): + assert attr == 'cffi_modules' + if isinstance(value, basestring): + value = [value] + + for cffi_module in value: + add_cffi_module(dist, cffi_module) diff --git a/.venv/Lib/site-packages/cffi/vengine_cpy.py b/.venv/Lib/site-packages/cffi/vengine_cpy.py new file mode 100644 index 00000000..49727d36 --- /dev/null +++ b/.venv/Lib/site-packages/cffi/vengine_cpy.py @@ -0,0 +1,1077 @@ +# +# DEPRECATED: implementation for ffi.verify() +# +import sys +from . import model +from .error import VerificationError +from . import _imp_emulation as imp + + +class VCPythonEngine(object): + _class_key = 'x' + _gen_python_module = True + + def __init__(self, verifier): + self.verifier = verifier + self.ffi = verifier.ffi + self._struct_pending_verification = {} + self._types_of_builtin_functions = {} + + def patch_extension_kwds(self, kwds): + pass + + def find_module(self, module_name, path, so_suffixes): + try: + f, filename, descr = imp.find_module(module_name, path) + except ImportError: + return None + if f is not None: + f.close() + # Note that after a setuptools installation, there are both .py + # and .so files with the same basename. The code here relies on + # imp.find_module() locating the .so in priority. + if descr[0] not in so_suffixes: + return None + return filename + + def collect_types(self): + self._typesdict = {} + self._generate("collecttype") + + def _prnt(self, what=''): + self._f.write(what + '\n') + + def _gettypenum(self, type): + # a KeyError here is a bug. please report it! :-) + return self._typesdict[type] + + def _do_collect_type(self, tp): + if ((not isinstance(tp, model.PrimitiveType) + or tp.name == 'long double') + and tp not in self._typesdict): + num = len(self._typesdict) + self._typesdict[tp] = num + + def write_source_to_f(self): + self.collect_types() + # + # The new module will have a _cffi_setup() function that receives + # objects from the ffi world, and that calls some setup code in + # the module. This setup code is split in several independent + # functions, e.g. one per constant. The functions are "chained" + # by ending in a tail call to each other. + # + # This is further split in two chained lists, depending on if we + # can do it at import-time or if we must wait for _cffi_setup() to + # provide us with the objects. This is needed because we + # need the values of the enum constants in order to build the + # that we may have to pass to _cffi_setup(). + # + # The following two 'chained_list_constants' items contains + # the head of these two chained lists, as a string that gives the + # call to do, if any. + self._chained_list_constants = ['((void)lib,0)', '((void)lib,0)'] + # + prnt = self._prnt + # first paste some standard set of lines that are mostly '#define' + prnt(cffimod_header) + prnt() + # then paste the C source given by the user, verbatim. + prnt(self.verifier.preamble) + prnt() + # + # call generate_cpy_xxx_decl(), for every xxx found from + # ffi._parser._declarations. This generates all the functions. + self._generate("decl") + # + # implement the function _cffi_setup_custom() as calling the + # head of the chained list. + self._generate_setup_custom() + prnt() + # + # produce the method table, including the entries for the + # generated Python->C function wrappers, which are done + # by generate_cpy_function_method(). + prnt('static PyMethodDef _cffi_methods[] = {') + self._generate("method") + prnt(' {"_cffi_setup", _cffi_setup, METH_VARARGS, NULL},') + prnt(' {NULL, NULL, 0, NULL} /* Sentinel */') + prnt('};') + prnt() + # + # standard init. + modname = self.verifier.get_module_name() + constants = self._chained_list_constants[False] + prnt('#if PY_MAJOR_VERSION >= 3') + prnt() + prnt('static struct PyModuleDef _cffi_module_def = {') + prnt(' PyModuleDef_HEAD_INIT,') + prnt(' "%s",' % modname) + prnt(' NULL,') + prnt(' -1,') + prnt(' _cffi_methods,') + prnt(' NULL, NULL, NULL, NULL') + prnt('};') + prnt() + prnt('PyMODINIT_FUNC') + prnt('PyInit_%s(void)' % modname) + prnt('{') + prnt(' PyObject *lib;') + prnt(' lib = PyModule_Create(&_cffi_module_def);') + prnt(' if (lib == NULL)') + prnt(' return NULL;') + prnt(' if (%s < 0 || _cffi_init() < 0) {' % (constants,)) + prnt(' Py_DECREF(lib);') + prnt(' return NULL;') + prnt(' }') + prnt(' return lib;') + prnt('}') + prnt() + prnt('#else') + prnt() + prnt('PyMODINIT_FUNC') + prnt('init%s(void)' % modname) + prnt('{') + prnt(' PyObject *lib;') + prnt(' lib = Py_InitModule("%s", _cffi_methods);' % modname) + prnt(' if (lib == NULL)') + prnt(' return;') + prnt(' if (%s < 0 || _cffi_init() < 0)' % (constants,)) + prnt(' return;') + prnt(' return;') + prnt('}') + prnt() + prnt('#endif') + + def load_library(self, flags=None): + # XXX review all usages of 'self' here! + # import it as a new extension module + imp.acquire_lock() + try: + if hasattr(sys, "getdlopenflags"): + previous_flags = sys.getdlopenflags() + try: + if hasattr(sys, "setdlopenflags") and flags is not None: + sys.setdlopenflags(flags) + module = imp.load_dynamic(self.verifier.get_module_name(), + self.verifier.modulefilename) + except ImportError as e: + error = "importing %r: %s" % (self.verifier.modulefilename, e) + raise VerificationError(error) + finally: + if hasattr(sys, "setdlopenflags"): + sys.setdlopenflags(previous_flags) + finally: + imp.release_lock() + # + # call loading_cpy_struct() to get the struct layout inferred by + # the C compiler + self._load(module, 'loading') + # + # the C code will need the objects. Collect them in + # order in a list. + revmapping = dict([(value, key) + for (key, value) in self._typesdict.items()]) + lst = [revmapping[i] for i in range(len(revmapping))] + lst = list(map(self.ffi._get_cached_btype, lst)) + # + # build the FFILibrary class and instance and call _cffi_setup(). + # this will set up some fields like '_cffi_types', and only then + # it will invoke the chained list of functions that will really + # build (notably) the constant objects, as if they are + # pointers, and store them as attributes on the 'library' object. + class FFILibrary(object): + _cffi_python_module = module + _cffi_ffi = self.ffi + _cffi_dir = [] + def __dir__(self): + return FFILibrary._cffi_dir + list(self.__dict__) + library = FFILibrary() + if module._cffi_setup(lst, VerificationError, library): + import warnings + warnings.warn("reimporting %r might overwrite older definitions" + % (self.verifier.get_module_name())) + # + # finally, call the loaded_cpy_xxx() functions. This will perform + # the final adjustments, like copying the Python->C wrapper + # functions from the module to the 'library' object, and setting + # up the FFILibrary class with properties for the global C variables. + self._load(module, 'loaded', library=library) + module._cffi_original_ffi = self.ffi + module._cffi_types_of_builtin_funcs = self._types_of_builtin_functions + return library + + def _get_declarations(self): + lst = [(key, tp) for (key, (tp, qual)) in + self.ffi._parser._declarations.items()] + lst.sort() + return lst + + def _generate(self, step_name): + for name, tp in self._get_declarations(): + kind, realname = name.split(' ', 1) + try: + method = getattr(self, '_generate_cpy_%s_%s' % (kind, + step_name)) + except AttributeError: + raise VerificationError( + "not implemented in verify(): %r" % name) + try: + method(tp, realname) + except Exception as e: + model.attach_exception_info(e, name) + raise + + def _load(self, module, step_name, **kwds): + for name, tp in self._get_declarations(): + kind, realname = name.split(' ', 1) + method = getattr(self, '_%s_cpy_%s' % (step_name, kind)) + try: + method(tp, realname, module, **kwds) + except Exception as e: + model.attach_exception_info(e, name) + raise + + def _generate_nothing(self, tp, name): + pass + + def _loaded_noop(self, tp, name, module, **kwds): + pass + + # ---------- + + def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode): + extraarg = '' + if isinstance(tp, model.PrimitiveType): + if tp.is_integer_type() and tp.name != '_Bool': + converter = '_cffi_to_c_int' + extraarg = ', %s' % tp.name + else: + converter = '(%s)_cffi_to_c_%s' % (tp.get_c_name(''), + tp.name.replace(' ', '_')) + errvalue = '-1' + # + elif isinstance(tp, model.PointerType): + self._convert_funcarg_to_c_ptr_or_array(tp, fromvar, + tovar, errcode) + return + # + elif isinstance(tp, (model.StructOrUnion, model.EnumType)): + # a struct (not a struct pointer) as a function argument + self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)' + % (tovar, self._gettypenum(tp), fromvar)) + self._prnt(' %s;' % errcode) + return + # + elif isinstance(tp, model.FunctionPtrType): + converter = '(%s)_cffi_to_c_pointer' % tp.get_c_name('') + extraarg = ', _cffi_type(%d)' % self._gettypenum(tp) + errvalue = 'NULL' + # + else: + raise NotImplementedError(tp) + # + self._prnt(' %s = %s(%s%s);' % (tovar, converter, fromvar, extraarg)) + self._prnt(' if (%s == (%s)%s && PyErr_Occurred())' % ( + tovar, tp.get_c_name(''), errvalue)) + self._prnt(' %s;' % errcode) + + def _extra_local_variables(self, tp, localvars, freelines): + if isinstance(tp, model.PointerType): + localvars.add('Py_ssize_t datasize') + localvars.add('struct _cffi_freeme_s *large_args_free = NULL') + freelines.add('if (large_args_free != NULL)' + ' _cffi_free_array_arguments(large_args_free);') + + def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode): + self._prnt(' datasize = _cffi_prepare_pointer_call_argument(') + self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % ( + self._gettypenum(tp), fromvar, tovar)) + self._prnt(' if (datasize != 0) {') + self._prnt(' %s = ((size_t)datasize) <= 640 ? ' + 'alloca((size_t)datasize) : NULL;' % (tovar,)) + self._prnt(' if (_cffi_convert_array_argument(_cffi_type(%d), %s, ' + '(char **)&%s,' % (self._gettypenum(tp), fromvar, tovar)) + self._prnt(' datasize, &large_args_free) < 0)') + self._prnt(' %s;' % errcode) + self._prnt(' }') + + def _convert_expr_from_c(self, tp, var, context): + if isinstance(tp, model.PrimitiveType): + if tp.is_integer_type() and tp.name != '_Bool': + return '_cffi_from_c_int(%s, %s)' % (var, tp.name) + elif tp.name != 'long double': + return '_cffi_from_c_%s(%s)' % (tp.name.replace(' ', '_'), var) + else: + return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( + var, self._gettypenum(tp)) + elif isinstance(tp, (model.PointerType, model.FunctionPtrType)): + return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( + var, self._gettypenum(tp)) + elif isinstance(tp, model.ArrayType): + return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( + var, self._gettypenum(model.PointerType(tp.item))) + elif isinstance(tp, model.StructOrUnion): + if tp.fldnames is None: + raise TypeError("'%s' is used as %s, but is opaque" % ( + tp._get_c_name(), context)) + return '_cffi_from_c_struct((char *)&%s, _cffi_type(%d))' % ( + var, self._gettypenum(tp)) + elif isinstance(tp, model.EnumType): + return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( + var, self._gettypenum(tp)) + else: + raise NotImplementedError(tp) + + # ---------- + # typedefs: generates no code so far + + _generate_cpy_typedef_collecttype = _generate_nothing + _generate_cpy_typedef_decl = _generate_nothing + _generate_cpy_typedef_method = _generate_nothing + _loading_cpy_typedef = _loaded_noop + _loaded_cpy_typedef = _loaded_noop + + # ---------- + # function declarations + + def _generate_cpy_function_collecttype(self, tp, name): + assert isinstance(tp, model.FunctionPtrType) + if tp.ellipsis: + self._do_collect_type(tp) + else: + # don't call _do_collect_type(tp) in this common case, + # otherwise test_autofilled_struct_as_argument fails + for type in tp.args: + self._do_collect_type(type) + self._do_collect_type(tp.result) + + def _generate_cpy_function_decl(self, tp, name): + assert isinstance(tp, model.FunctionPtrType) + if tp.ellipsis: + # cannot support vararg functions better than this: check for its + # exact type (including the fixed arguments), and build it as a + # constant function pointer (no CPython wrapper) + self._generate_cpy_const(False, name, tp) + return + prnt = self._prnt + numargs = len(tp.args) + if numargs == 0: + argname = 'noarg' + elif numargs == 1: + argname = 'arg0' + else: + argname = 'args' + prnt('static PyObject *') + prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname)) + prnt('{') + # + context = 'argument of %s' % name + for i, type in enumerate(tp.args): + prnt(' %s;' % type.get_c_name(' x%d' % i, context)) + # + localvars = set() + freelines = set() + for type in tp.args: + self._extra_local_variables(type, localvars, freelines) + for decl in sorted(localvars): + prnt(' %s;' % (decl,)) + # + if not isinstance(tp.result, model.VoidType): + result_code = 'result = ' + context = 'result of %s' % name + prnt(' %s;' % tp.result.get_c_name(' result', context)) + prnt(' PyObject *pyresult;') + else: + result_code = '' + # + if len(tp.args) > 1: + rng = range(len(tp.args)) + for i in rng: + prnt(' PyObject *arg%d;' % i) + prnt() + prnt(' if (!PyArg_ParseTuple(args, "%s:%s", %s))' % ( + 'O' * numargs, name, ', '.join(['&arg%d' % i for i in rng]))) + prnt(' return NULL;') + prnt() + # + for i, type in enumerate(tp.args): + self._convert_funcarg_to_c(type, 'arg%d' % i, 'x%d' % i, + 'return NULL') + prnt() + # + prnt(' Py_BEGIN_ALLOW_THREADS') + prnt(' _cffi_restore_errno();') + prnt(' { %s%s(%s); }' % ( + result_code, name, + ', '.join(['x%d' % i for i in range(len(tp.args))]))) + prnt(' _cffi_save_errno();') + prnt(' Py_END_ALLOW_THREADS') + prnt() + # + prnt(' (void)self; /* unused */') + if numargs == 0: + prnt(' (void)noarg; /* unused */') + if result_code: + prnt(' pyresult = %s;' % + self._convert_expr_from_c(tp.result, 'result', 'result type')) + for freeline in freelines: + prnt(' ' + freeline) + prnt(' return pyresult;') + else: + for freeline in freelines: + prnt(' ' + freeline) + prnt(' Py_INCREF(Py_None);') + prnt(' return Py_None;') + prnt('}') + prnt() + + def _generate_cpy_function_method(self, tp, name): + if tp.ellipsis: + return + numargs = len(tp.args) + if numargs == 0: + meth = 'METH_NOARGS' + elif numargs == 1: + meth = 'METH_O' + else: + meth = 'METH_VARARGS' + self._prnt(' {"%s", _cffi_f_%s, %s, NULL},' % (name, name, meth)) + + _loading_cpy_function = _loaded_noop + + def _loaded_cpy_function(self, tp, name, module, library): + if tp.ellipsis: + return + func = getattr(module, name) + setattr(library, name, func) + self._types_of_builtin_functions[func] = tp + + # ---------- + # named structs + + _generate_cpy_struct_collecttype = _generate_nothing + def _generate_cpy_struct_decl(self, tp, name): + assert name == tp.name + self._generate_struct_or_union_decl(tp, 'struct', name) + def _generate_cpy_struct_method(self, tp, name): + self._generate_struct_or_union_method(tp, 'struct', name) + def _loading_cpy_struct(self, tp, name, module): + self._loading_struct_or_union(tp, 'struct', name, module) + def _loaded_cpy_struct(self, tp, name, module, **kwds): + self._loaded_struct_or_union(tp) + + _generate_cpy_union_collecttype = _generate_nothing + def _generate_cpy_union_decl(self, tp, name): + assert name == tp.name + self._generate_struct_or_union_decl(tp, 'union', name) + def _generate_cpy_union_method(self, tp, name): + self._generate_struct_or_union_method(tp, 'union', name) + def _loading_cpy_union(self, tp, name, module): + self._loading_struct_or_union(tp, 'union', name, module) + def _loaded_cpy_union(self, tp, name, module, **kwds): + self._loaded_struct_or_union(tp) + + def _generate_struct_or_union_decl(self, tp, prefix, name): + if tp.fldnames is None: + return # nothing to do with opaque structs + checkfuncname = '_cffi_check_%s_%s' % (prefix, name) + layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) + cname = ('%s %s' % (prefix, name)).strip() + # + prnt = self._prnt + prnt('static void %s(%s *p)' % (checkfuncname, cname)) + prnt('{') + prnt(' /* only to generate compile-time warnings or errors */') + prnt(' (void)p;') + for fname, ftype, fbitsize, fqual in tp.enumfields(): + if (isinstance(ftype, model.PrimitiveType) + and ftype.is_integer_type()) or fbitsize >= 0: + # accept all integers, but complain on float or double + prnt(' (void)((p->%s) << 1);' % fname) + else: + # only accept exactly the type declared. + try: + prnt(' { %s = &p->%s; (void)tmp; }' % ( + ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual), + fname)) + except VerificationError as e: + prnt(' /* %s */' % str(e)) # cannot verify it, ignore + prnt('}') + prnt('static PyObject *') + prnt('%s(PyObject *self, PyObject *noarg)' % (layoutfuncname,)) + prnt('{') + prnt(' struct _cffi_aligncheck { char x; %s y; };' % cname) + prnt(' static Py_ssize_t nums[] = {') + prnt(' sizeof(%s),' % cname) + prnt(' offsetof(struct _cffi_aligncheck, y),') + for fname, ftype, fbitsize, fqual in tp.enumfields(): + if fbitsize >= 0: + continue # xxx ignore fbitsize for now + prnt(' offsetof(%s, %s),' % (cname, fname)) + if isinstance(ftype, model.ArrayType) and ftype.length is None: + prnt(' 0, /* %s */' % ftype._get_c_name()) + else: + prnt(' sizeof(((%s *)0)->%s),' % (cname, fname)) + prnt(' -1') + prnt(' };') + prnt(' (void)self; /* unused */') + prnt(' (void)noarg; /* unused */') + prnt(' return _cffi_get_struct_layout(nums);') + prnt(' /* the next line is not executed, but compiled */') + prnt(' %s(0);' % (checkfuncname,)) + prnt('}') + prnt() + + def _generate_struct_or_union_method(self, tp, prefix, name): + if tp.fldnames is None: + return # nothing to do with opaque structs + layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) + self._prnt(' {"%s", %s, METH_NOARGS, NULL},' % (layoutfuncname, + layoutfuncname)) + + def _loading_struct_or_union(self, tp, prefix, name, module): + if tp.fldnames is None: + return # nothing to do with opaque structs + layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) + # + function = getattr(module, layoutfuncname) + layout = function() + if isinstance(tp, model.StructOrUnion) and tp.partial: + # use the function()'s sizes and offsets to guide the + # layout of the struct + totalsize = layout[0] + totalalignment = layout[1] + fieldofs = layout[2::2] + fieldsize = layout[3::2] + tp.force_flatten() + assert len(fieldofs) == len(fieldsize) == len(tp.fldnames) + tp.fixedlayout = fieldofs, fieldsize, totalsize, totalalignment + else: + cname = ('%s %s' % (prefix, name)).strip() + self._struct_pending_verification[tp] = layout, cname + + def _loaded_struct_or_union(self, tp): + if tp.fldnames is None: + return # nothing to do with opaque structs + self.ffi._get_cached_btype(tp) # force 'fixedlayout' to be considered + + if tp in self._struct_pending_verification: + # check that the layout sizes and offsets match the real ones + def check(realvalue, expectedvalue, msg): + if realvalue != expectedvalue: + raise VerificationError( + "%s (we have %d, but C compiler says %d)" + % (msg, expectedvalue, realvalue)) + ffi = self.ffi + BStruct = ffi._get_cached_btype(tp) + layout, cname = self._struct_pending_verification.pop(tp) + check(layout[0], ffi.sizeof(BStruct), "wrong total size") + check(layout[1], ffi.alignof(BStruct), "wrong total alignment") + i = 2 + for fname, ftype, fbitsize, fqual in tp.enumfields(): + if fbitsize >= 0: + continue # xxx ignore fbitsize for now + check(layout[i], ffi.offsetof(BStruct, fname), + "wrong offset for field %r" % (fname,)) + if layout[i+1] != 0: + BField = ffi._get_cached_btype(ftype) + check(layout[i+1], ffi.sizeof(BField), + "wrong size for field %r" % (fname,)) + i += 2 + assert i == len(layout) + + # ---------- + # 'anonymous' declarations. These are produced for anonymous structs + # or unions; the 'name' is obtained by a typedef. + + _generate_cpy_anonymous_collecttype = _generate_nothing + + def _generate_cpy_anonymous_decl(self, tp, name): + if isinstance(tp, model.EnumType): + self._generate_cpy_enum_decl(tp, name, '') + else: + self._generate_struct_or_union_decl(tp, '', name) + + def _generate_cpy_anonymous_method(self, tp, name): + if not isinstance(tp, model.EnumType): + self._generate_struct_or_union_method(tp, '', name) + + def _loading_cpy_anonymous(self, tp, name, module): + if isinstance(tp, model.EnumType): + self._loading_cpy_enum(tp, name, module) + else: + self._loading_struct_or_union(tp, '', name, module) + + def _loaded_cpy_anonymous(self, tp, name, module, **kwds): + if isinstance(tp, model.EnumType): + self._loaded_cpy_enum(tp, name, module, **kwds) + else: + self._loaded_struct_or_union(tp) + + # ---------- + # constants, likely declared with '#define' + + def _generate_cpy_const(self, is_int, name, tp=None, category='const', + vartp=None, delayed=True, size_too=False, + check_value=None): + prnt = self._prnt + funcname = '_cffi_%s_%s' % (category, name) + prnt('static int %s(PyObject *lib)' % funcname) + prnt('{') + prnt(' PyObject *o;') + prnt(' int res;') + if not is_int: + prnt(' %s;' % (vartp or tp).get_c_name(' i', name)) + else: + assert category == 'const' + # + if check_value is not None: + self._check_int_constant_value(name, check_value) + # + if not is_int: + if category == 'var': + realexpr = '&' + name + else: + realexpr = name + prnt(' i = (%s);' % (realexpr,)) + prnt(' o = %s;' % (self._convert_expr_from_c(tp, 'i', + 'variable type'),)) + assert delayed + else: + prnt(' o = _cffi_from_c_int_const(%s);' % name) + prnt(' if (o == NULL)') + prnt(' return -1;') + if size_too: + prnt(' {') + prnt(' PyObject *o1 = o;') + prnt(' o = Py_BuildValue("On", o1, (Py_ssize_t)sizeof(%s));' + % (name,)) + prnt(' Py_DECREF(o1);') + prnt(' if (o == NULL)') + prnt(' return -1;') + prnt(' }') + prnt(' res = PyObject_SetAttrString(lib, "%s", o);' % name) + prnt(' Py_DECREF(o);') + prnt(' if (res < 0)') + prnt(' return -1;') + prnt(' return %s;' % self._chained_list_constants[delayed]) + self._chained_list_constants[delayed] = funcname + '(lib)' + prnt('}') + prnt() + + def _generate_cpy_constant_collecttype(self, tp, name): + is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() + if not is_int: + self._do_collect_type(tp) + + def _generate_cpy_constant_decl(self, tp, name): + is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() + self._generate_cpy_const(is_int, name, tp) + + _generate_cpy_constant_method = _generate_nothing + _loading_cpy_constant = _loaded_noop + _loaded_cpy_constant = _loaded_noop + + # ---------- + # enums + + def _check_int_constant_value(self, name, value, err_prefix=''): + prnt = self._prnt + if value <= 0: + prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % ( + name, name, value)) + else: + prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % ( + name, name, value)) + prnt(' char buf[64];') + prnt(' if ((%s) <= 0)' % name) + prnt(' snprintf(buf, 63, "%%ld", (long)(%s));' % name) + prnt(' else') + prnt(' snprintf(buf, 63, "%%lu", (unsigned long)(%s));' % + name) + prnt(' PyErr_Format(_cffi_VerificationError,') + prnt(' "%s%s has the real value %s, not %s",') + prnt(' "%s", "%s", buf, "%d");' % ( + err_prefix, name, value)) + prnt(' return -1;') + prnt(' }') + + def _enum_funcname(self, prefix, name): + # "$enum_$1" => "___D_enum____D_1" + name = name.replace('$', '___D_') + return '_cffi_e_%s_%s' % (prefix, name) + + def _generate_cpy_enum_decl(self, tp, name, prefix='enum'): + if tp.partial: + for enumerator in tp.enumerators: + self._generate_cpy_const(True, enumerator, delayed=False) + return + # + funcname = self._enum_funcname(prefix, name) + prnt = self._prnt + prnt('static int %s(PyObject *lib)' % funcname) + prnt('{') + for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): + self._check_int_constant_value(enumerator, enumvalue, + "enum %s: " % name) + prnt(' return %s;' % self._chained_list_constants[True]) + self._chained_list_constants[True] = funcname + '(lib)' + prnt('}') + prnt() + + _generate_cpy_enum_collecttype = _generate_nothing + _generate_cpy_enum_method = _generate_nothing + + def _loading_cpy_enum(self, tp, name, module): + if tp.partial: + enumvalues = [getattr(module, enumerator) + for enumerator in tp.enumerators] + tp.enumvalues = tuple(enumvalues) + tp.partial_resolved = True + + def _loaded_cpy_enum(self, tp, name, module, library): + for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): + setattr(library, enumerator, enumvalue) + + # ---------- + # macros: for now only for integers + + def _generate_cpy_macro_decl(self, tp, name): + if tp == '...': + check_value = None + else: + check_value = tp # an integer + self._generate_cpy_const(True, name, check_value=check_value) + + _generate_cpy_macro_collecttype = _generate_nothing + _generate_cpy_macro_method = _generate_nothing + _loading_cpy_macro = _loaded_noop + _loaded_cpy_macro = _loaded_noop + + # ---------- + # global variables + + def _generate_cpy_variable_collecttype(self, tp, name): + if isinstance(tp, model.ArrayType): + tp_ptr = model.PointerType(tp.item) + else: + tp_ptr = model.PointerType(tp) + self._do_collect_type(tp_ptr) + + def _generate_cpy_variable_decl(self, tp, name): + if isinstance(tp, model.ArrayType): + tp_ptr = model.PointerType(tp.item) + self._generate_cpy_const(False, name, tp, vartp=tp_ptr, + size_too = tp.length_is_unknown()) + else: + tp_ptr = model.PointerType(tp) + self._generate_cpy_const(False, name, tp_ptr, category='var') + + _generate_cpy_variable_method = _generate_nothing + _loading_cpy_variable = _loaded_noop + + def _loaded_cpy_variable(self, tp, name, module, library): + value = getattr(library, name) + if isinstance(tp, model.ArrayType): # int a[5] is "constant" in the + # sense that "a=..." is forbidden + if tp.length_is_unknown(): + assert isinstance(value, tuple) + (value, size) = value + BItemType = self.ffi._get_cached_btype(tp.item) + length, rest = divmod(size, self.ffi.sizeof(BItemType)) + if rest != 0: + raise VerificationError( + "bad size: %r does not seem to be an array of %s" % + (name, tp.item)) + tp = tp.resolve_length(length) + # 'value' is a which we have to replace with + # a if the N is actually known + if tp.length is not None: + BArray = self.ffi._get_cached_btype(tp) + value = self.ffi.cast(BArray, value) + setattr(library, name, value) + return + # remove ptr= from the library instance, and replace + # it by a property on the class, which reads/writes into ptr[0]. + ptr = value + delattr(library, name) + def getter(library): + return ptr[0] + def setter(library, value): + ptr[0] = value + setattr(type(library), name, property(getter, setter)) + type(library)._cffi_dir.append(name) + + # ---------- + + def _generate_setup_custom(self): + prnt = self._prnt + prnt('static int _cffi_setup_custom(PyObject *lib)') + prnt('{') + prnt(' return %s;' % self._chained_list_constants[True]) + prnt('}') + +cffimod_header = r''' +#include +#include + +/* this block of #ifs should be kept exactly identical between + c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py + and cffi/_cffi_include.h */ +#if defined(_MSC_VER) +# include /* for alloca() */ +# if _MSC_VER < 1600 /* MSVC < 2010 */ + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + typedef __int8 int_least8_t; + typedef __int16 int_least16_t; + typedef __int32 int_least32_t; + typedef __int64 int_least64_t; + typedef unsigned __int8 uint_least8_t; + typedef unsigned __int16 uint_least16_t; + typedef unsigned __int32 uint_least32_t; + typedef unsigned __int64 uint_least64_t; + typedef __int8 int_fast8_t; + typedef __int16 int_fast16_t; + typedef __int32 int_fast32_t; + typedef __int64 int_fast64_t; + typedef unsigned __int8 uint_fast8_t; + typedef unsigned __int16 uint_fast16_t; + typedef unsigned __int32 uint_fast32_t; + typedef unsigned __int64 uint_fast64_t; + typedef __int64 intmax_t; + typedef unsigned __int64 uintmax_t; +# else +# include +# endif +# if _MSC_VER < 1800 /* MSVC < 2013 */ +# ifndef __cplusplus + typedef unsigned char _Bool; +# endif +# endif +#else +# include +# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) +# include +# endif +#endif + +#if PY_MAJOR_VERSION < 3 +# undef PyCapsule_CheckExact +# undef PyCapsule_GetPointer +# define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule)) +# define PyCapsule_GetPointer(capsule, name) \ + (PyCObject_AsVoidPtr(capsule)) +#endif + +#if PY_MAJOR_VERSION >= 3 +# define PyInt_FromLong PyLong_FromLong +#endif + +#define _cffi_from_c_double PyFloat_FromDouble +#define _cffi_from_c_float PyFloat_FromDouble +#define _cffi_from_c_long PyInt_FromLong +#define _cffi_from_c_ulong PyLong_FromUnsignedLong +#define _cffi_from_c_longlong PyLong_FromLongLong +#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong +#define _cffi_from_c__Bool PyBool_FromLong + +#define _cffi_to_c_double PyFloat_AsDouble +#define _cffi_to_c_float PyFloat_AsDouble + +#define _cffi_from_c_int_const(x) \ + (((x) > 0) ? \ + ((unsigned long long)(x) <= (unsigned long long)LONG_MAX) ? \ + PyInt_FromLong((long)(x)) : \ + PyLong_FromUnsignedLongLong((unsigned long long)(x)) : \ + ((long long)(x) >= (long long)LONG_MIN) ? \ + PyInt_FromLong((long)(x)) : \ + PyLong_FromLongLong((long long)(x))) + +#define _cffi_from_c_int(x, type) \ + (((type)-1) > 0 ? /* unsigned */ \ + (sizeof(type) < sizeof(long) ? \ + PyInt_FromLong((long)x) : \ + sizeof(type) == sizeof(long) ? \ + PyLong_FromUnsignedLong((unsigned long)x) : \ + PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ + (sizeof(type) <= sizeof(long) ? \ + PyInt_FromLong((long)x) : \ + PyLong_FromLongLong((long long)x))) + +#define _cffi_to_c_int(o, type) \ + ((type)( \ + sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \ + : (type)_cffi_to_c_i8(o)) : \ + sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \ + : (type)_cffi_to_c_i16(o)) : \ + sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \ + : (type)_cffi_to_c_i32(o)) : \ + sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \ + : (type)_cffi_to_c_i64(o)) : \ + (Py_FatalError("unsupported size for type " #type), (type)0))) + +#define _cffi_to_c_i8 \ + ((int(*)(PyObject *))_cffi_exports[1]) +#define _cffi_to_c_u8 \ + ((int(*)(PyObject *))_cffi_exports[2]) +#define _cffi_to_c_i16 \ + ((int(*)(PyObject *))_cffi_exports[3]) +#define _cffi_to_c_u16 \ + ((int(*)(PyObject *))_cffi_exports[4]) +#define _cffi_to_c_i32 \ + ((int(*)(PyObject *))_cffi_exports[5]) +#define _cffi_to_c_u32 \ + ((unsigned int(*)(PyObject *))_cffi_exports[6]) +#define _cffi_to_c_i64 \ + ((long long(*)(PyObject *))_cffi_exports[7]) +#define _cffi_to_c_u64 \ + ((unsigned long long(*)(PyObject *))_cffi_exports[8]) +#define _cffi_to_c_char \ + ((int(*)(PyObject *))_cffi_exports[9]) +#define _cffi_from_c_pointer \ + ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[10]) +#define _cffi_to_c_pointer \ + ((char *(*)(PyObject *, CTypeDescrObject *))_cffi_exports[11]) +#define _cffi_get_struct_layout \ + ((PyObject *(*)(Py_ssize_t[]))_cffi_exports[12]) +#define _cffi_restore_errno \ + ((void(*)(void))_cffi_exports[13]) +#define _cffi_save_errno \ + ((void(*)(void))_cffi_exports[14]) +#define _cffi_from_c_char \ + ((PyObject *(*)(char))_cffi_exports[15]) +#define _cffi_from_c_deref \ + ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[16]) +#define _cffi_to_c \ + ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[17]) +#define _cffi_from_c_struct \ + ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[18]) +#define _cffi_to_c_wchar_t \ + ((wchar_t(*)(PyObject *))_cffi_exports[19]) +#define _cffi_from_c_wchar_t \ + ((PyObject *(*)(wchar_t))_cffi_exports[20]) +#define _cffi_to_c_long_double \ + ((long double(*)(PyObject *))_cffi_exports[21]) +#define _cffi_to_c__Bool \ + ((_Bool(*)(PyObject *))_cffi_exports[22]) +#define _cffi_prepare_pointer_call_argument \ + ((Py_ssize_t(*)(CTypeDescrObject *, PyObject *, char **))_cffi_exports[23]) +#define _cffi_convert_array_from_object \ + ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[24]) +#define _CFFI_NUM_EXPORTS 25 + +typedef struct _ctypedescr CTypeDescrObject; + +static void *_cffi_exports[_CFFI_NUM_EXPORTS]; +static PyObject *_cffi_types, *_cffi_VerificationError; + +static int _cffi_setup_custom(PyObject *lib); /* forward */ + +static PyObject *_cffi_setup(PyObject *self, PyObject *args) +{ + PyObject *library; + int was_alive = (_cffi_types != NULL); + (void)self; /* unused */ + if (!PyArg_ParseTuple(args, "OOO", &_cffi_types, &_cffi_VerificationError, + &library)) + return NULL; + Py_INCREF(_cffi_types); + Py_INCREF(_cffi_VerificationError); + if (_cffi_setup_custom(library) < 0) + return NULL; + return PyBool_FromLong(was_alive); +} + +union _cffi_union_alignment_u { + unsigned char m_char; + unsigned short m_short; + unsigned int m_int; + unsigned long m_long; + unsigned long long m_longlong; + float m_float; + double m_double; + long double m_longdouble; +}; + +struct _cffi_freeme_s { + struct _cffi_freeme_s *next; + union _cffi_union_alignment_u alignment; +}; + +#ifdef __GNUC__ + __attribute__((unused)) +#endif +static int _cffi_convert_array_argument(CTypeDescrObject *ctptr, PyObject *arg, + char **output_data, Py_ssize_t datasize, + struct _cffi_freeme_s **freeme) +{ + char *p; + if (datasize < 0) + return -1; + + p = *output_data; + if (p == NULL) { + struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc( + offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize); + if (fp == NULL) + return -1; + fp->next = *freeme; + *freeme = fp; + p = *output_data = (char *)&fp->alignment; + } + memset((void *)p, 0, (size_t)datasize); + return _cffi_convert_array_from_object(p, ctptr, arg); +} + +#ifdef __GNUC__ + __attribute__((unused)) +#endif +static void _cffi_free_array_arguments(struct _cffi_freeme_s *freeme) +{ + do { + void *p = (void *)freeme; + freeme = freeme->next; + PyObject_Free(p); + } while (freeme != NULL); +} + +static int _cffi_init(void) +{ + PyObject *module, *c_api_object = NULL; + + module = PyImport_ImportModule("_cffi_backend"); + if (module == NULL) + goto failure; + + c_api_object = PyObject_GetAttrString(module, "_C_API"); + if (c_api_object == NULL) + goto failure; + if (!PyCapsule_CheckExact(c_api_object)) { + PyErr_SetNone(PyExc_ImportError); + goto failure; + } + memcpy(_cffi_exports, PyCapsule_GetPointer(c_api_object, "cffi"), + _CFFI_NUM_EXPORTS * sizeof(void *)); + + Py_DECREF(module); + Py_DECREF(c_api_object); + return 0; + + failure: + Py_XDECREF(module); + Py_XDECREF(c_api_object); + return -1; +} + +#define _cffi_type(num) ((CTypeDescrObject *)PyList_GET_ITEM(_cffi_types, num)) + +/**********/ +''' diff --git a/.venv/Lib/site-packages/cffi/vengine_gen.py b/.venv/Lib/site-packages/cffi/vengine_gen.py new file mode 100644 index 00000000..26421526 --- /dev/null +++ b/.venv/Lib/site-packages/cffi/vengine_gen.py @@ -0,0 +1,675 @@ +# +# DEPRECATED: implementation for ffi.verify() +# +import sys, os +import types + +from . import model +from .error import VerificationError + + +class VGenericEngine(object): + _class_key = 'g' + _gen_python_module = False + + def __init__(self, verifier): + self.verifier = verifier + self.ffi = verifier.ffi + self.export_symbols = [] + self._struct_pending_verification = {} + + def patch_extension_kwds(self, kwds): + # add 'export_symbols' to the dictionary. Note that we add the + # list before filling it. When we fill it, it will thus also show + # up in kwds['export_symbols']. + kwds.setdefault('export_symbols', self.export_symbols) + + def find_module(self, module_name, path, so_suffixes): + for so_suffix in so_suffixes: + basename = module_name + so_suffix + if path is None: + path = sys.path + for dirname in path: + filename = os.path.join(dirname, basename) + if os.path.isfile(filename): + return filename + + def collect_types(self): + pass # not needed in the generic engine + + def _prnt(self, what=''): + self._f.write(what + '\n') + + def write_source_to_f(self): + prnt = self._prnt + # first paste some standard set of lines that are mostly '#include' + prnt(cffimod_header) + # then paste the C source given by the user, verbatim. + prnt(self.verifier.preamble) + # + # call generate_gen_xxx_decl(), for every xxx found from + # ffi._parser._declarations. This generates all the functions. + self._generate('decl') + # + # on Windows, distutils insists on putting init_cffi_xyz in + # 'export_symbols', so instead of fighting it, just give up and + # give it one + if sys.platform == 'win32': + if sys.version_info >= (3,): + prefix = 'PyInit_' + else: + prefix = 'init' + modname = self.verifier.get_module_name() + prnt("void %s%s(void) { }\n" % (prefix, modname)) + + def load_library(self, flags=0): + # import it with the CFFI backend + backend = self.ffi._backend + # needs to make a path that contains '/', on Posix + filename = os.path.join(os.curdir, self.verifier.modulefilename) + module = backend.load_library(filename, flags) + # + # call loading_gen_struct() to get the struct layout inferred by + # the C compiler + self._load(module, 'loading') + + # build the FFILibrary class and instance, this is a module subclass + # because modules are expected to have usually-constant-attributes and + # in PyPy this means the JIT is able to treat attributes as constant, + # which we want. + class FFILibrary(types.ModuleType): + _cffi_generic_module = module + _cffi_ffi = self.ffi + _cffi_dir = [] + def __dir__(self): + return FFILibrary._cffi_dir + library = FFILibrary("") + # + # finally, call the loaded_gen_xxx() functions. This will set + # up the 'library' object. + self._load(module, 'loaded', library=library) + return library + + def _get_declarations(self): + lst = [(key, tp) for (key, (tp, qual)) in + self.ffi._parser._declarations.items()] + lst.sort() + return lst + + def _generate(self, step_name): + for name, tp in self._get_declarations(): + kind, realname = name.split(' ', 1) + try: + method = getattr(self, '_generate_gen_%s_%s' % (kind, + step_name)) + except AttributeError: + raise VerificationError( + "not implemented in verify(): %r" % name) + try: + method(tp, realname) + except Exception as e: + model.attach_exception_info(e, name) + raise + + def _load(self, module, step_name, **kwds): + for name, tp in self._get_declarations(): + kind, realname = name.split(' ', 1) + method = getattr(self, '_%s_gen_%s' % (step_name, kind)) + try: + method(tp, realname, module, **kwds) + except Exception as e: + model.attach_exception_info(e, name) + raise + + def _generate_nothing(self, tp, name): + pass + + def _loaded_noop(self, tp, name, module, **kwds): + pass + + # ---------- + # typedefs: generates no code so far + + _generate_gen_typedef_decl = _generate_nothing + _loading_gen_typedef = _loaded_noop + _loaded_gen_typedef = _loaded_noop + + # ---------- + # function declarations + + def _generate_gen_function_decl(self, tp, name): + assert isinstance(tp, model.FunctionPtrType) + if tp.ellipsis: + # cannot support vararg functions better than this: check for its + # exact type (including the fixed arguments), and build it as a + # constant function pointer (no _cffi_f_%s wrapper) + self._generate_gen_const(False, name, tp) + return + prnt = self._prnt + numargs = len(tp.args) + argnames = [] + for i, type in enumerate(tp.args): + indirection = '' + if isinstance(type, model.StructOrUnion): + indirection = '*' + argnames.append('%sx%d' % (indirection, i)) + context = 'argument of %s' % name + arglist = [type.get_c_name(' %s' % arg, context) + for type, arg in zip(tp.args, argnames)] + tpresult = tp.result + if isinstance(tpresult, model.StructOrUnion): + arglist.insert(0, tpresult.get_c_name(' *r', context)) + tpresult = model.void_type + arglist = ', '.join(arglist) or 'void' + wrappername = '_cffi_f_%s' % name + self.export_symbols.append(wrappername) + if tp.abi: + abi = tp.abi + ' ' + else: + abi = '' + funcdecl = ' %s%s(%s)' % (abi, wrappername, arglist) + context = 'result of %s' % name + prnt(tpresult.get_c_name(funcdecl, context)) + prnt('{') + # + if isinstance(tp.result, model.StructOrUnion): + result_code = '*r = ' + elif not isinstance(tp.result, model.VoidType): + result_code = 'return ' + else: + result_code = '' + prnt(' %s%s(%s);' % (result_code, name, ', '.join(argnames))) + prnt('}') + prnt() + + _loading_gen_function = _loaded_noop + + def _loaded_gen_function(self, tp, name, module, library): + assert isinstance(tp, model.FunctionPtrType) + if tp.ellipsis: + newfunction = self._load_constant(False, tp, name, module) + else: + indirections = [] + base_tp = tp + if (any(isinstance(typ, model.StructOrUnion) for typ in tp.args) + or isinstance(tp.result, model.StructOrUnion)): + indirect_args = [] + for i, typ in enumerate(tp.args): + if isinstance(typ, model.StructOrUnion): + typ = model.PointerType(typ) + indirections.append((i, typ)) + indirect_args.append(typ) + indirect_result = tp.result + if isinstance(indirect_result, model.StructOrUnion): + if indirect_result.fldtypes is None: + raise TypeError("'%s' is used as result type, " + "but is opaque" % ( + indirect_result._get_c_name(),)) + indirect_result = model.PointerType(indirect_result) + indirect_args.insert(0, indirect_result) + indirections.insert(0, ("result", indirect_result)) + indirect_result = model.void_type + tp = model.FunctionPtrType(tuple(indirect_args), + indirect_result, tp.ellipsis) + BFunc = self.ffi._get_cached_btype(tp) + wrappername = '_cffi_f_%s' % name + newfunction = module.load_function(BFunc, wrappername) + for i, typ in indirections: + newfunction = self._make_struct_wrapper(newfunction, i, typ, + base_tp) + setattr(library, name, newfunction) + type(library)._cffi_dir.append(name) + + def _make_struct_wrapper(self, oldfunc, i, tp, base_tp): + backend = self.ffi._backend + BType = self.ffi._get_cached_btype(tp) + if i == "result": + ffi = self.ffi + def newfunc(*args): + res = ffi.new(BType) + oldfunc(res, *args) + return res[0] + else: + def newfunc(*args): + args = args[:i] + (backend.newp(BType, args[i]),) + args[i+1:] + return oldfunc(*args) + newfunc._cffi_base_type = base_tp + return newfunc + + # ---------- + # named structs + + def _generate_gen_struct_decl(self, tp, name): + assert name == tp.name + self._generate_struct_or_union_decl(tp, 'struct', name) + + def _loading_gen_struct(self, tp, name, module): + self._loading_struct_or_union(tp, 'struct', name, module) + + def _loaded_gen_struct(self, tp, name, module, **kwds): + self._loaded_struct_or_union(tp) + + def _generate_gen_union_decl(self, tp, name): + assert name == tp.name + self._generate_struct_or_union_decl(tp, 'union', name) + + def _loading_gen_union(self, tp, name, module): + self._loading_struct_or_union(tp, 'union', name, module) + + def _loaded_gen_union(self, tp, name, module, **kwds): + self._loaded_struct_or_union(tp) + + def _generate_struct_or_union_decl(self, tp, prefix, name): + if tp.fldnames is None: + return # nothing to do with opaque structs + checkfuncname = '_cffi_check_%s_%s' % (prefix, name) + layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) + cname = ('%s %s' % (prefix, name)).strip() + # + prnt = self._prnt + prnt('static void %s(%s *p)' % (checkfuncname, cname)) + prnt('{') + prnt(' /* only to generate compile-time warnings or errors */') + prnt(' (void)p;') + for fname, ftype, fbitsize, fqual in tp.enumfields(): + if (isinstance(ftype, model.PrimitiveType) + and ftype.is_integer_type()) or fbitsize >= 0: + # accept all integers, but complain on float or double + prnt(' (void)((p->%s) << 1);' % fname) + else: + # only accept exactly the type declared. + try: + prnt(' { %s = &p->%s; (void)tmp; }' % ( + ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual), + fname)) + except VerificationError as e: + prnt(' /* %s */' % str(e)) # cannot verify it, ignore + prnt('}') + self.export_symbols.append(layoutfuncname) + prnt('intptr_t %s(intptr_t i)' % (layoutfuncname,)) + prnt('{') + prnt(' struct _cffi_aligncheck { char x; %s y; };' % cname) + prnt(' static intptr_t nums[] = {') + prnt(' sizeof(%s),' % cname) + prnt(' offsetof(struct _cffi_aligncheck, y),') + for fname, ftype, fbitsize, fqual in tp.enumfields(): + if fbitsize >= 0: + continue # xxx ignore fbitsize for now + prnt(' offsetof(%s, %s),' % (cname, fname)) + if isinstance(ftype, model.ArrayType) and ftype.length is None: + prnt(' 0, /* %s */' % ftype._get_c_name()) + else: + prnt(' sizeof(((%s *)0)->%s),' % (cname, fname)) + prnt(' -1') + prnt(' };') + prnt(' return nums[i];') + prnt(' /* the next line is not executed, but compiled */') + prnt(' %s(0);' % (checkfuncname,)) + prnt('}') + prnt() + + def _loading_struct_or_union(self, tp, prefix, name, module): + if tp.fldnames is None: + return # nothing to do with opaque structs + layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) + # + BFunc = self.ffi._typeof_locked("intptr_t(*)(intptr_t)")[0] + function = module.load_function(BFunc, layoutfuncname) + layout = [] + num = 0 + while True: + x = function(num) + if x < 0: break + layout.append(x) + num += 1 + if isinstance(tp, model.StructOrUnion) and tp.partial: + # use the function()'s sizes and offsets to guide the + # layout of the struct + totalsize = layout[0] + totalalignment = layout[1] + fieldofs = layout[2::2] + fieldsize = layout[3::2] + tp.force_flatten() + assert len(fieldofs) == len(fieldsize) == len(tp.fldnames) + tp.fixedlayout = fieldofs, fieldsize, totalsize, totalalignment + else: + cname = ('%s %s' % (prefix, name)).strip() + self._struct_pending_verification[tp] = layout, cname + + def _loaded_struct_or_union(self, tp): + if tp.fldnames is None: + return # nothing to do with opaque structs + self.ffi._get_cached_btype(tp) # force 'fixedlayout' to be considered + + if tp in self._struct_pending_verification: + # check that the layout sizes and offsets match the real ones + def check(realvalue, expectedvalue, msg): + if realvalue != expectedvalue: + raise VerificationError( + "%s (we have %d, but C compiler says %d)" + % (msg, expectedvalue, realvalue)) + ffi = self.ffi + BStruct = ffi._get_cached_btype(tp) + layout, cname = self._struct_pending_verification.pop(tp) + check(layout[0], ffi.sizeof(BStruct), "wrong total size") + check(layout[1], ffi.alignof(BStruct), "wrong total alignment") + i = 2 + for fname, ftype, fbitsize, fqual in tp.enumfields(): + if fbitsize >= 0: + continue # xxx ignore fbitsize for now + check(layout[i], ffi.offsetof(BStruct, fname), + "wrong offset for field %r" % (fname,)) + if layout[i+1] != 0: + BField = ffi._get_cached_btype(ftype) + check(layout[i+1], ffi.sizeof(BField), + "wrong size for field %r" % (fname,)) + i += 2 + assert i == len(layout) + + # ---------- + # 'anonymous' declarations. These are produced for anonymous structs + # or unions; the 'name' is obtained by a typedef. + + def _generate_gen_anonymous_decl(self, tp, name): + if isinstance(tp, model.EnumType): + self._generate_gen_enum_decl(tp, name, '') + else: + self._generate_struct_or_union_decl(tp, '', name) + + def _loading_gen_anonymous(self, tp, name, module): + if isinstance(tp, model.EnumType): + self._loading_gen_enum(tp, name, module, '') + else: + self._loading_struct_or_union(tp, '', name, module) + + def _loaded_gen_anonymous(self, tp, name, module, **kwds): + if isinstance(tp, model.EnumType): + self._loaded_gen_enum(tp, name, module, **kwds) + else: + self._loaded_struct_or_union(tp) + + # ---------- + # constants, likely declared with '#define' + + def _generate_gen_const(self, is_int, name, tp=None, category='const', + check_value=None): + prnt = self._prnt + funcname = '_cffi_%s_%s' % (category, name) + self.export_symbols.append(funcname) + if check_value is not None: + assert is_int + assert category == 'const' + prnt('int %s(char *out_error)' % funcname) + prnt('{') + self._check_int_constant_value(name, check_value) + prnt(' return 0;') + prnt('}') + elif is_int: + assert category == 'const' + prnt('int %s(long long *out_value)' % funcname) + prnt('{') + prnt(' *out_value = (long long)(%s);' % (name,)) + prnt(' return (%s) <= 0;' % (name,)) + prnt('}') + else: + assert tp is not None + assert check_value is None + if category == 'var': + ampersand = '&' + else: + ampersand = '' + extra = '' + if category == 'const' and isinstance(tp, model.StructOrUnion): + extra = 'const *' + ampersand = '&' + prnt(tp.get_c_name(' %s%s(void)' % (extra, funcname), name)) + prnt('{') + prnt(' return (%s%s);' % (ampersand, name)) + prnt('}') + prnt() + + def _generate_gen_constant_decl(self, tp, name): + is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() + self._generate_gen_const(is_int, name, tp) + + _loading_gen_constant = _loaded_noop + + def _load_constant(self, is_int, tp, name, module, check_value=None): + funcname = '_cffi_const_%s' % name + if check_value is not None: + assert is_int + self._load_known_int_constant(module, funcname) + value = check_value + elif is_int: + BType = self.ffi._typeof_locked("long long*")[0] + BFunc = self.ffi._typeof_locked("int(*)(long long*)")[0] + function = module.load_function(BFunc, funcname) + p = self.ffi.new(BType) + negative = function(p) + value = int(p[0]) + if value < 0 and not negative: + BLongLong = self.ffi._typeof_locked("long long")[0] + value += (1 << (8*self.ffi.sizeof(BLongLong))) + else: + assert check_value is None + fntypeextra = '(*)(void)' + if isinstance(tp, model.StructOrUnion): + fntypeextra = '*' + fntypeextra + BFunc = self.ffi._typeof_locked(tp.get_c_name(fntypeextra, name))[0] + function = module.load_function(BFunc, funcname) + value = function() + if isinstance(tp, model.StructOrUnion): + value = value[0] + return value + + def _loaded_gen_constant(self, tp, name, module, library): + is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() + value = self._load_constant(is_int, tp, name, module) + setattr(library, name, value) + type(library)._cffi_dir.append(name) + + # ---------- + # enums + + def _check_int_constant_value(self, name, value): + prnt = self._prnt + if value <= 0: + prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % ( + name, name, value)) + else: + prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % ( + name, name, value)) + prnt(' char buf[64];') + prnt(' if ((%s) <= 0)' % name) + prnt(' sprintf(buf, "%%ld", (long)(%s));' % name) + prnt(' else') + prnt(' sprintf(buf, "%%lu", (unsigned long)(%s));' % + name) + prnt(' sprintf(out_error, "%s has the real value %s, not %s",') + prnt(' "%s", buf, "%d");' % (name[:100], value)) + prnt(' return -1;') + prnt(' }') + + def _load_known_int_constant(self, module, funcname): + BType = self.ffi._typeof_locked("char[]")[0] + BFunc = self.ffi._typeof_locked("int(*)(char*)")[0] + function = module.load_function(BFunc, funcname) + p = self.ffi.new(BType, 256) + if function(p) < 0: + error = self.ffi.string(p) + if sys.version_info >= (3,): + error = str(error, 'utf-8') + raise VerificationError(error) + + def _enum_funcname(self, prefix, name): + # "$enum_$1" => "___D_enum____D_1" + name = name.replace('$', '___D_') + return '_cffi_e_%s_%s' % (prefix, name) + + def _generate_gen_enum_decl(self, tp, name, prefix='enum'): + if tp.partial: + for enumerator in tp.enumerators: + self._generate_gen_const(True, enumerator) + return + # + funcname = self._enum_funcname(prefix, name) + self.export_symbols.append(funcname) + prnt = self._prnt + prnt('int %s(char *out_error)' % funcname) + prnt('{') + for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): + self._check_int_constant_value(enumerator, enumvalue) + prnt(' return 0;') + prnt('}') + prnt() + + def _loading_gen_enum(self, tp, name, module, prefix='enum'): + if tp.partial: + enumvalues = [self._load_constant(True, tp, enumerator, module) + for enumerator in tp.enumerators] + tp.enumvalues = tuple(enumvalues) + tp.partial_resolved = True + else: + funcname = self._enum_funcname(prefix, name) + self._load_known_int_constant(module, funcname) + + def _loaded_gen_enum(self, tp, name, module, library): + for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): + setattr(library, enumerator, enumvalue) + type(library)._cffi_dir.append(enumerator) + + # ---------- + # macros: for now only for integers + + def _generate_gen_macro_decl(self, tp, name): + if tp == '...': + check_value = None + else: + check_value = tp # an integer + self._generate_gen_const(True, name, check_value=check_value) + + _loading_gen_macro = _loaded_noop + + def _loaded_gen_macro(self, tp, name, module, library): + if tp == '...': + check_value = None + else: + check_value = tp # an integer + value = self._load_constant(True, tp, name, module, + check_value=check_value) + setattr(library, name, value) + type(library)._cffi_dir.append(name) + + # ---------- + # global variables + + def _generate_gen_variable_decl(self, tp, name): + if isinstance(tp, model.ArrayType): + if tp.length_is_unknown(): + prnt = self._prnt + funcname = '_cffi_sizeof_%s' % (name,) + self.export_symbols.append(funcname) + prnt("size_t %s(void)" % funcname) + prnt("{") + prnt(" return sizeof(%s);" % (name,)) + prnt("}") + tp_ptr = model.PointerType(tp.item) + self._generate_gen_const(False, name, tp_ptr) + else: + tp_ptr = model.PointerType(tp) + self._generate_gen_const(False, name, tp_ptr, category='var') + + _loading_gen_variable = _loaded_noop + + def _loaded_gen_variable(self, tp, name, module, library): + if isinstance(tp, model.ArrayType): # int a[5] is "constant" in the + # sense that "a=..." is forbidden + if tp.length_is_unknown(): + funcname = '_cffi_sizeof_%s' % (name,) + BFunc = self.ffi._typeof_locked('size_t(*)(void)')[0] + function = module.load_function(BFunc, funcname) + size = function() + BItemType = self.ffi._get_cached_btype(tp.item) + length, rest = divmod(size, self.ffi.sizeof(BItemType)) + if rest != 0: + raise VerificationError( + "bad size: %r does not seem to be an array of %s" % + (name, tp.item)) + tp = tp.resolve_length(length) + tp_ptr = model.PointerType(tp.item) + value = self._load_constant(False, tp_ptr, name, module) + # 'value' is a which we have to replace with + # a if the N is actually known + if tp.length is not None: + BArray = self.ffi._get_cached_btype(tp) + value = self.ffi.cast(BArray, value) + setattr(library, name, value) + type(library)._cffi_dir.append(name) + return + # remove ptr= from the library instance, and replace + # it by a property on the class, which reads/writes into ptr[0]. + funcname = '_cffi_var_%s' % name + BFunc = self.ffi._typeof_locked(tp.get_c_name('*(*)(void)', name))[0] + function = module.load_function(BFunc, funcname) + ptr = function() + def getter(library): + return ptr[0] + def setter(library, value): + ptr[0] = value + setattr(type(library), name, property(getter, setter)) + type(library)._cffi_dir.append(name) + +cffimod_header = r''' +#include +#include +#include +#include +#include /* XXX for ssize_t on some platforms */ + +/* this block of #ifs should be kept exactly identical between + c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py + and cffi/_cffi_include.h */ +#if defined(_MSC_VER) +# include /* for alloca() */ +# if _MSC_VER < 1600 /* MSVC < 2010 */ + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + typedef __int8 int_least8_t; + typedef __int16 int_least16_t; + typedef __int32 int_least32_t; + typedef __int64 int_least64_t; + typedef unsigned __int8 uint_least8_t; + typedef unsigned __int16 uint_least16_t; + typedef unsigned __int32 uint_least32_t; + typedef unsigned __int64 uint_least64_t; + typedef __int8 int_fast8_t; + typedef __int16 int_fast16_t; + typedef __int32 int_fast32_t; + typedef __int64 int_fast64_t; + typedef unsigned __int8 uint_fast8_t; + typedef unsigned __int16 uint_fast16_t; + typedef unsigned __int32 uint_fast32_t; + typedef unsigned __int64 uint_fast64_t; + typedef __int64 intmax_t; + typedef unsigned __int64 uintmax_t; +# else +# include +# endif +# if _MSC_VER < 1800 /* MSVC < 2013 */ +# ifndef __cplusplus + typedef unsigned char _Bool; +# endif +# endif +#else +# include +# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) +# include +# endif +#endif +''' diff --git a/.venv/Lib/site-packages/cffi/verifier.py b/.venv/Lib/site-packages/cffi/verifier.py new file mode 100644 index 00000000..e392a2b7 --- /dev/null +++ b/.venv/Lib/site-packages/cffi/verifier.py @@ -0,0 +1,306 @@ +# +# DEPRECATED: implementation for ffi.verify() +# +import sys, os, binascii, shutil, io +from . import __version_verifier_modules__ +from . import ffiplatform +from .error import VerificationError + +if sys.version_info >= (3, 3): + import importlib.machinery + def _extension_suffixes(): + return importlib.machinery.EXTENSION_SUFFIXES[:] +else: + import imp + def _extension_suffixes(): + return [suffix for suffix, _, type in imp.get_suffixes() + if type == imp.C_EXTENSION] + + +if sys.version_info >= (3,): + NativeIO = io.StringIO +else: + class NativeIO(io.BytesIO): + def write(self, s): + if isinstance(s, unicode): + s = s.encode('ascii') + super(NativeIO, self).write(s) + + +class Verifier(object): + + def __init__(self, ffi, preamble, tmpdir=None, modulename=None, + ext_package=None, tag='', force_generic_engine=False, + source_extension='.c', flags=None, relative_to=None, **kwds): + if ffi._parser._uses_new_feature: + raise VerificationError( + "feature not supported with ffi.verify(), but only " + "with ffi.set_source(): %s" % (ffi._parser._uses_new_feature,)) + self.ffi = ffi + self.preamble = preamble + if not modulename: + flattened_kwds = ffiplatform.flatten(kwds) + vengine_class = _locate_engine_class(ffi, force_generic_engine) + self._vengine = vengine_class(self) + self._vengine.patch_extension_kwds(kwds) + self.flags = flags + self.kwds = self.make_relative_to(kwds, relative_to) + # + if modulename: + if tag: + raise TypeError("can't specify both 'modulename' and 'tag'") + else: + key = '\x00'.join(['%d.%d' % sys.version_info[:2], + __version_verifier_modules__, + preamble, flattened_kwds] + + ffi._cdefsources) + if sys.version_info >= (3,): + key = key.encode('utf-8') + k1 = hex(binascii.crc32(key[0::2]) & 0xffffffff) + k1 = k1.lstrip('0x').rstrip('L') + k2 = hex(binascii.crc32(key[1::2]) & 0xffffffff) + k2 = k2.lstrip('0').rstrip('L') + modulename = '_cffi_%s_%s%s%s' % (tag, self._vengine._class_key, + k1, k2) + suffix = _get_so_suffixes()[0] + self.tmpdir = tmpdir or _caller_dir_pycache() + self.sourcefilename = os.path.join(self.tmpdir, modulename + source_extension) + self.modulefilename = os.path.join(self.tmpdir, modulename + suffix) + self.ext_package = ext_package + self._has_source = False + self._has_module = False + + def write_source(self, file=None): + """Write the C source code. It is produced in 'self.sourcefilename', + which can be tweaked beforehand.""" + with self.ffi._lock: + if self._has_source and file is None: + raise VerificationError( + "source code already written") + self._write_source(file) + + def compile_module(self): + """Write the C source code (if not done already) and compile it. + This produces a dynamic link library in 'self.modulefilename'.""" + with self.ffi._lock: + if self._has_module: + raise VerificationError("module already compiled") + if not self._has_source: + self._write_source() + self._compile_module() + + def load_library(self): + """Get a C module from this Verifier instance. + Returns an instance of a FFILibrary class that behaves like the + objects returned by ffi.dlopen(), but that delegates all + operations to the C module. If necessary, the C code is written + and compiled first. + """ + with self.ffi._lock: + if not self._has_module: + self._locate_module() + if not self._has_module: + if not self._has_source: + self._write_source() + self._compile_module() + return self._load_library() + + def get_module_name(self): + basename = os.path.basename(self.modulefilename) + # kill both the .so extension and the other .'s, as introduced + # by Python 3: 'basename.cpython-33m.so' + basename = basename.split('.', 1)[0] + # and the _d added in Python 2 debug builds --- but try to be + # conservative and not kill a legitimate _d + if basename.endswith('_d') and hasattr(sys, 'gettotalrefcount'): + basename = basename[:-2] + return basename + + def get_extension(self): + if not self._has_source: + with self.ffi._lock: + if not self._has_source: + self._write_source() + sourcename = ffiplatform.maybe_relative_path(self.sourcefilename) + modname = self.get_module_name() + return ffiplatform.get_extension(sourcename, modname, **self.kwds) + + def generates_python_module(self): + return self._vengine._gen_python_module + + def make_relative_to(self, kwds, relative_to): + if relative_to and os.path.dirname(relative_to): + dirname = os.path.dirname(relative_to) + kwds = kwds.copy() + for key in ffiplatform.LIST_OF_FILE_NAMES: + if key in kwds: + lst = kwds[key] + if not isinstance(lst, (list, tuple)): + raise TypeError("keyword '%s' should be a list or tuple" + % (key,)) + lst = [os.path.join(dirname, fn) for fn in lst] + kwds[key] = lst + return kwds + + # ---------- + + def _locate_module(self): + if not os.path.isfile(self.modulefilename): + if self.ext_package: + try: + pkg = __import__(self.ext_package, None, None, ['__doc__']) + except ImportError: + return # cannot import the package itself, give up + # (e.g. it might be called differently before installation) + path = pkg.__path__ + else: + path = None + filename = self._vengine.find_module(self.get_module_name(), path, + _get_so_suffixes()) + if filename is None: + return + self.modulefilename = filename + self._vengine.collect_types() + self._has_module = True + + def _write_source_to(self, file): + self._vengine._f = file + try: + self._vengine.write_source_to_f() + finally: + del self._vengine._f + + def _write_source(self, file=None): + if file is not None: + self._write_source_to(file) + else: + # Write our source file to an in memory file. + f = NativeIO() + self._write_source_to(f) + source_data = f.getvalue() + + # Determine if this matches the current file + if os.path.exists(self.sourcefilename): + with open(self.sourcefilename, "r") as fp: + needs_written = not (fp.read() == source_data) + else: + needs_written = True + + # Actually write the file out if it doesn't match + if needs_written: + _ensure_dir(self.sourcefilename) + with open(self.sourcefilename, "w") as fp: + fp.write(source_data) + + # Set this flag + self._has_source = True + + def _compile_module(self): + # compile this C source + tmpdir = os.path.dirname(self.sourcefilename) + outputfilename = ffiplatform.compile(tmpdir, self.get_extension()) + try: + same = ffiplatform.samefile(outputfilename, self.modulefilename) + except OSError: + same = False + if not same: + _ensure_dir(self.modulefilename) + shutil.move(outputfilename, self.modulefilename) + self._has_module = True + + def _load_library(self): + assert self._has_module + if self.flags is not None: + return self._vengine.load_library(self.flags) + else: + return self._vengine.load_library() + +# ____________________________________________________________ + +_FORCE_GENERIC_ENGINE = False # for tests + +def _locate_engine_class(ffi, force_generic_engine): + if _FORCE_GENERIC_ENGINE: + force_generic_engine = True + if not force_generic_engine: + if '__pypy__' in sys.builtin_module_names: + force_generic_engine = True + else: + try: + import _cffi_backend + except ImportError: + _cffi_backend = '?' + if ffi._backend is not _cffi_backend: + force_generic_engine = True + if force_generic_engine: + from . import vengine_gen + return vengine_gen.VGenericEngine + else: + from . import vengine_cpy + return vengine_cpy.VCPythonEngine + +# ____________________________________________________________ + +_TMPDIR = None + +def _caller_dir_pycache(): + if _TMPDIR: + return _TMPDIR + result = os.environ.get('CFFI_TMPDIR') + if result: + return result + filename = sys._getframe(2).f_code.co_filename + return os.path.abspath(os.path.join(os.path.dirname(filename), + '__pycache__')) + +def set_tmpdir(dirname): + """Set the temporary directory to use instead of __pycache__.""" + global _TMPDIR + _TMPDIR = dirname + +def cleanup_tmpdir(tmpdir=None, keep_so=False): + """Clean up the temporary directory by removing all files in it + called `_cffi_*.{c,so}` as well as the `build` subdirectory.""" + tmpdir = tmpdir or _caller_dir_pycache() + try: + filelist = os.listdir(tmpdir) + except OSError: + return + if keep_so: + suffix = '.c' # only remove .c files + else: + suffix = _get_so_suffixes()[0].lower() + for fn in filelist: + if fn.lower().startswith('_cffi_') and ( + fn.lower().endswith(suffix) or fn.lower().endswith('.c')): + try: + os.unlink(os.path.join(tmpdir, fn)) + except OSError: + pass + clean_dir = [os.path.join(tmpdir, 'build')] + for dir in clean_dir: + try: + for fn in os.listdir(dir): + fn = os.path.join(dir, fn) + if os.path.isdir(fn): + clean_dir.append(fn) + else: + os.unlink(fn) + except OSError: + pass + +def _get_so_suffixes(): + suffixes = _extension_suffixes() + if not suffixes: + # bah, no C_EXTENSION available. Occurs on pypy without cpyext + if sys.platform == 'win32': + suffixes = [".pyd"] + else: + suffixes = [".so"] + + return suffixes + +def _ensure_dir(filename): + dirname = os.path.dirname(filename) + if dirname and not os.path.isdir(dirname): + os.makedirs(dirname) diff --git a/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/INSTALLER b/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/LICENSE b/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/LICENSE new file mode 100644 index 00000000..b11f379e --- /dev/null +++ b/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/LICENSE @@ -0,0 +1,3 @@ +This software is made available under the terms of *either* of the licenses +found in LICENSE.APACHE or LICENSE.BSD. Contributions to cryptography are made +under the terms of *both* these licenses. diff --git a/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/LICENSE.APACHE b/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/LICENSE.APACHE new file mode 100644 index 00000000..62589edd --- /dev/null +++ b/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/LICENSE.APACHE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + https://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 + + https://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/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/LICENSE.BSD b/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/LICENSE.BSD new file mode 100644 index 00000000..ec1a29d3 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/LICENSE.BSD @@ -0,0 +1,27 @@ +Copyright (c) Individual contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of PyCA Cryptography nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/METADATA b/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/METADATA new file mode 100644 index 00000000..2c043b13 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/METADATA @@ -0,0 +1,135 @@ +Metadata-Version: 2.1 +Name: cryptography +Version: 42.0.1 +Summary: cryptography is a package which provides cryptographic recipes and primitives to Python developers. +Author-email: The Python Cryptographic Authority and individual contributors +License: Apache-2.0 OR BSD-3-Clause +Project-URL: homepage, https://github.com/pyca/cryptography +Project-URL: documentation, https://cryptography.io/ +Project-URL: source, https://github.com/pyca/cryptography/ +Project-URL: issues, https://github.com/pyca/cryptography/issues +Project-URL: changelog, https://cryptography.io/en/latest/changelog/ +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Apache Software License +Classifier: License :: OSI Approved :: BSD License +Classifier: Natural Language :: English +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: POSIX +Classifier: Operating System :: POSIX :: BSD +Classifier: Operating System :: POSIX :: Linux +Classifier: Operating System :: Microsoft :: Windows +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Security :: Cryptography +Requires-Python: >=3.7 +Description-Content-Type: text/x-rst +License-File: LICENSE +License-File: LICENSE.APACHE +License-File: LICENSE.BSD +Requires-Dist: cffi >=1.12 ; platform_python_implementation != "PyPy" +Provides-Extra: docs +Requires-Dist: sphinx >=5.3.0 ; extra == 'docs' +Requires-Dist: sphinx-rtd-theme >=1.1.1 ; extra == 'docs' +Provides-Extra: docstest +Requires-Dist: pyenchant >=1.6.11 ; extra == 'docstest' +Requires-Dist: readme-renderer ; extra == 'docstest' +Requires-Dist: sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' +Provides-Extra: nox +Requires-Dist: nox ; extra == 'nox' +Provides-Extra: pep8test +Requires-Dist: ruff ; extra == 'pep8test' +Requires-Dist: mypy ; extra == 'pep8test' +Requires-Dist: check-sdist ; extra == 'pep8test' +Requires-Dist: click ; extra == 'pep8test' +Provides-Extra: sdist +Requires-Dist: build ; extra == 'sdist' +Provides-Extra: ssh +Requires-Dist: bcrypt >=3.1.5 ; extra == 'ssh' +Provides-Extra: test +Requires-Dist: pytest >=6.2.0 ; extra == 'test' +Requires-Dist: pytest-benchmark ; extra == 'test' +Requires-Dist: pytest-cov ; extra == 'test' +Requires-Dist: pytest-xdist ; extra == 'test' +Requires-Dist: pretend ; extra == 'test' +Requires-Dist: certifi ; extra == 'test' +Provides-Extra: test-randomorder +Requires-Dist: pytest-randomly ; extra == 'test-randomorder' + +pyca/cryptography +================= + +.. image:: https://img.shields.io/pypi/v/cryptography.svg + :target: https://pypi.org/project/cryptography/ + :alt: Latest Version + +.. image:: https://readthedocs.org/projects/cryptography/badge/?version=latest + :target: https://cryptography.io + :alt: Latest Docs + +.. image:: https://github.com/pyca/cryptography/workflows/CI/badge.svg?branch=main + :target: https://github.com/pyca/cryptography/actions?query=workflow%3ACI+branch%3Amain + + +``cryptography`` is a package which provides cryptographic recipes and +primitives to Python developers. Our goal is for it to be your "cryptographic +standard library". It supports Python 3.7+ and PyPy3 7.3.11+. + +``cryptography`` includes both high level recipes and low level interfaces to +common cryptographic algorithms such as symmetric ciphers, message digests, and +key derivation functions. For example, to encrypt something with +``cryptography``'s high level symmetric encryption recipe: + +.. code-block:: pycon + + >>> from cryptography.fernet import Fernet + >>> # Put this somewhere safe! + >>> key = Fernet.generate_key() + >>> f = Fernet(key) + >>> token = f.encrypt(b"A really secret message. Not for prying eyes.") + >>> token + b'...' + >>> f.decrypt(token) + b'A really secret message. Not for prying eyes.' + +You can find more information in the `documentation`_. + +You can install ``cryptography`` with: + +.. code-block:: console + + $ pip install cryptography + +For full details see `the installation documentation`_. + +Discussion +~~~~~~~~~~ + +If you run into bugs, you can file them in our `issue tracker`_. + +We maintain a `cryptography-dev`_ mailing list for development discussion. + +You can also join ``#pyca`` on ``irc.libera.chat`` to ask questions or get +involved. + +Security +~~~~~~~~ + +Need to report a security issue? Please consult our `security reporting`_ +documentation. + + +.. _`documentation`: https://cryptography.io/ +.. _`the installation documentation`: https://cryptography.io/en/latest/installation/ +.. _`issue tracker`: https://github.com/pyca/cryptography/issues +.. _`cryptography-dev`: https://mail.python.org/mailman/listinfo/cryptography-dev +.. _`security reporting`: https://cryptography.io/en/latest/security/ diff --git a/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/RECORD b/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/RECORD new file mode 100644 index 00000000..d09eaade --- /dev/null +++ b/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/RECORD @@ -0,0 +1,171 @@ +cryptography-42.0.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +cryptography-42.0.1.dist-info/LICENSE,sha256=Pgx8CRqUi4JTO6mP18u0BDLW8amsv4X1ki0vmak65rs,197 +cryptography-42.0.1.dist-info/LICENSE.APACHE,sha256=qsc7MUj20dcRHbyjIJn2jSbGRMaBOuHk8F9leaomY_4,11360 +cryptography-42.0.1.dist-info/LICENSE.BSD,sha256=YCxMdILeZHndLpeTzaJ15eY9dz2s0eymiSMqtwCPtPs,1532 +cryptography-42.0.1.dist-info/METADATA,sha256=N9jI_s4pSMGbz0DaqjAr87UJCMGFRTqtPYcUoNitxJ8,5430 +cryptography-42.0.1.dist-info/RECORD,, +cryptography-42.0.1.dist-info/WHEEL,sha256=ZzJfItdlTwUbeh2SvWRPbrqgDfW_djikghnwfRmqFIQ,100 +cryptography-42.0.1.dist-info/top_level.txt,sha256=KNaT-Sn2K4uxNaEbe6mYdDn3qWDMlp4y-MtWfB73nJc,13 +cryptography/__about__.py,sha256=BWH-wXuR_WW0RqjRc0cp-C7I3e1ux0Aq-H2l7weXJb0,445 +cryptography/__init__.py,sha256=iVPlBlXWTJyiFeRedxcbMPhyHB34viOM10d72vGnWuE,364 +cryptography/__pycache__/__about__.cpython-311.pyc,, +cryptography/__pycache__/__init__.cpython-311.pyc,, +cryptography/__pycache__/exceptions.cpython-311.pyc,, +cryptography/__pycache__/fernet.cpython-311.pyc,, +cryptography/__pycache__/utils.cpython-311.pyc,, +cryptography/exceptions.py,sha256=835EWILc2fwxw-gyFMriciC2SqhViETB10LBSytnDIc,1087 +cryptography/fernet.py,sha256=aPj82w-Z_1GBXUtWRUsZdVbMwRo5Mbjj0wkA9wG4rkw,6696 +cryptography/hazmat/__init__.py,sha256=5IwrLWrVp0AjEr_4FdWG_V057NSJGY_W4egNNsuct0g,455 +cryptography/hazmat/__pycache__/__init__.cpython-311.pyc,, +cryptography/hazmat/__pycache__/_oid.cpython-311.pyc,, +cryptography/hazmat/_oid.py,sha256=0DhT6N-ziZzlQp05iPKOsy5wdPMayiKdrSg_yZfWLzc,14460 +cryptography/hazmat/backends/__init__.py,sha256=O5jvKFQdZnXhKeqJ-HtulaEL9Ni7mr1mDzZY5kHlYhI,361 +cryptography/hazmat/backends/__pycache__/__init__.cpython-311.pyc,, +cryptography/hazmat/backends/openssl/__init__.py,sha256=p3jmJfnCag9iE5sdMrN6VvVEu55u46xaS_IjoI0SrmA,305 +cryptography/hazmat/backends/openssl/__pycache__/__init__.cpython-311.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/aead.cpython-311.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/backend.cpython-311.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/ciphers.cpython-311.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/decode_asn1.cpython-311.pyc,, +cryptography/hazmat/backends/openssl/aead.py,sha256=UBNLqkicUo2ve7q-q8R49IgVOYlDMmSPtbPUK2qdMbM,8176 +cryptography/hazmat/backends/openssl/backend.py,sha256=dqdL5le6MnRjSuWjxRnyzvi8gIa_5rsWdB_9lrpeltg,32606 +cryptography/hazmat/backends/openssl/ciphers.py,sha256=MwBbBauaUjNiaja25oZKt7vI9bRGXfF5lK1p-8AQ67U,10353 +cryptography/hazmat/backends/openssl/decode_asn1.py,sha256=kz6gys8wuJhrx4QyU6enYx7UatNHr0LB3TI1jH3oQ54,1148 +cryptography/hazmat/bindings/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180 +cryptography/hazmat/bindings/__pycache__/__init__.cpython-311.pyc,, +cryptography/hazmat/bindings/_rust.pyd,sha256=urLvC6p9z6aHShxTSNn-6VEEn5POzV0dFwFUqrhKYvI,7211520 +cryptography/hazmat/bindings/_rust/__init__.pyi,sha256=djseHBlzUqDJ7JUc2J51OT_7CLm_Lz0EyVQ55o3udUI,495 +cryptography/hazmat/bindings/_rust/_openssl.pyi,sha256=mpNJLuYLbCVrd5i33FBTmWwL_55Dw7JPkSLlSX9Q7oI,230 +cryptography/hazmat/bindings/_rust/asn1.pyi,sha256=8w-f89ls0pb7BAbt1E0Pvkd59NGtTFItLtFK8ZJGbkk,556 +cryptography/hazmat/bindings/_rust/exceptions.pyi,sha256=exXr2xw_0pB1kk93cYbM3MohbzoUkjOms1ZMUi0uQZE,640 +cryptography/hazmat/bindings/_rust/ocsp.pyi,sha256=qUA2x7lwbG_Z7wJ_wUxsBFJ71arjoX-nnkZAw4nVDeQ,860 +cryptography/hazmat/bindings/_rust/openssl/__init__.pyi,sha256=SwBmmK_wzQbHK_Y5Q3lQIIk3NPFciNv6IjXVSBLx89Q,1067 +cryptography/hazmat/bindings/_rust/openssl/aead.pyi,sha256=ZNsO1H8Q9ixQO9Db7qtkboWKM5fycWY_ZeyGXb3scHg,1737 +cryptography/hazmat/bindings/_rust/openssl/cmac.pyi,sha256=nPH0X57RYpsAkRowVpjQiHE566ThUTx7YXrsadmrmHk,564 +cryptography/hazmat/bindings/_rust/openssl/dh.pyi,sha256=Z3TC-G04-THtSdAOPLM1h2G7ml5bda1ElZUcn5wpuhk,1564 +cryptography/hazmat/bindings/_rust/openssl/dsa.pyi,sha256=qBtkgj2albt2qFcnZ9UDrhzoNhCVO7HTby5VSf1EXMI,1299 +cryptography/hazmat/bindings/_rust/openssl/ec.pyi,sha256=zJy0pRa5n-_p2dm45PxECB_-B6SVZyNKfjxFDpPqT38,1691 +cryptography/hazmat/bindings/_rust/openssl/ed25519.pyi,sha256=OJsrblS2nHptZctva-pAKFL5q8yPEAkhmjPZpJ6TA94,493 +cryptography/hazmat/bindings/_rust/openssl/ed448.pyi,sha256=SkPHK2HdbYN02TVQEUOgW3iTdiEY7HBE4DijpdkAzmk,475 +cryptography/hazmat/bindings/_rust/openssl/hashes.pyi,sha256=J8HoN0GdtPcjRAfNHr5Elva_nkmQfq63L75_z9dd8Uc,573 +cryptography/hazmat/bindings/_rust/openssl/hmac.pyi,sha256=ZmLJ73pmxcZFC1XosWEiXMRYtvJJor3ZLdCQOJu85Cw,662 +cryptography/hazmat/bindings/_rust/openssl/kdf.pyi,sha256=wPS5c7NLspM2632II0I4iH1RSxZvSRtBOVqmpyQATfk,544 +cryptography/hazmat/bindings/_rust/openssl/keys.pyi,sha256=9nFfZ0USUxHtPvqJmvWewz27so3qlQxxTEt2d904msI,980 +cryptography/hazmat/bindings/_rust/openssl/poly1305.pyi,sha256=9iogF7Q4i81IkOS-IMXp6HvxFF_3cNy_ucrAjVQnn14,540 +cryptography/hazmat/bindings/_rust/openssl/rsa.pyi,sha256=2OQCNSXkxgc-3uw1xiCCloIQTV6p9_kK79Yu0rhZgPc,1364 +cryptography/hazmat/bindings/_rust/openssl/x25519.pyi,sha256=2BKdbrddM_9SMUpdvHKGhb9MNjURCarPxccbUDzHeoA,484 +cryptography/hazmat/bindings/_rust/openssl/x448.pyi,sha256=AoRMWNvCJTiH5L-lkIkCdPlrPLUdJvvfXpIvf1GmxpM,466 +cryptography/hazmat/bindings/_rust/pkcs7.pyi,sha256=WfJXBDgmsOg1ui1U3wclgL-xpmbcFNq6lt6fY6yxy8w,619 +cryptography/hazmat/bindings/_rust/x509.pyi,sha256=KqsM2W3tg4MpzxjI4eL9Jbsm7pQwvJ4_-xDE7wA1x3w,3001 +cryptography/hazmat/bindings/openssl/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180 +cryptography/hazmat/bindings/openssl/__pycache__/__init__.cpython-311.pyc,, +cryptography/hazmat/bindings/openssl/__pycache__/_conditional.cpython-311.pyc,, +cryptography/hazmat/bindings/openssl/__pycache__/binding.cpython-311.pyc,, +cryptography/hazmat/bindings/openssl/_conditional.py,sha256=rqgTeJjw9y83ICW5hd3bowvFWVO49-gRC9QF-636Vhg,6481 +cryptography/hazmat/bindings/openssl/binding.py,sha256=G4Nh4jXcIYiFyPJhwnJT4TGTyx8m8gY2REG7xgU1eaA,6531 +cryptography/hazmat/primitives/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180 +cryptography/hazmat/primitives/__pycache__/__init__.cpython-311.pyc,, +cryptography/hazmat/primitives/__pycache__/_asymmetric.cpython-311.pyc,, +cryptography/hazmat/primitives/__pycache__/_cipheralgorithm.cpython-311.pyc,, +cryptography/hazmat/primitives/__pycache__/_serialization.cpython-311.pyc,, +cryptography/hazmat/primitives/__pycache__/cmac.cpython-311.pyc,, +cryptography/hazmat/primitives/__pycache__/constant_time.cpython-311.pyc,, +cryptography/hazmat/primitives/__pycache__/hashes.cpython-311.pyc,, +cryptography/hazmat/primitives/__pycache__/hmac.cpython-311.pyc,, +cryptography/hazmat/primitives/__pycache__/keywrap.cpython-311.pyc,, +cryptography/hazmat/primitives/__pycache__/padding.cpython-311.pyc,, +cryptography/hazmat/primitives/__pycache__/poly1305.cpython-311.pyc,, +cryptography/hazmat/primitives/_asymmetric.py,sha256=RhgcouUB6HTiFDBrR1LxqkMjpUxIiNvQ1r_zJjRG6qQ,532 +cryptography/hazmat/primitives/_cipheralgorithm.py,sha256=u7ryLG_HivCXn-ulKM-h_eVWMzlobeg0K45Udflk7Gg,1072 +cryptography/hazmat/primitives/_serialization.py,sha256=qrozc8fw2WZSbjk3DAlSl3ResxpauwJ74ZgGoUL-mj0,5142 +cryptography/hazmat/primitives/asymmetric/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180 +cryptography/hazmat/primitives/asymmetric/__pycache__/__init__.cpython-311.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/dh.cpython-311.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/dsa.cpython-311.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/ec.cpython-311.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/ed25519.cpython-311.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/ed448.cpython-311.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/padding.cpython-311.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/rsa.cpython-311.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/types.cpython-311.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/utils.cpython-311.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/x25519.cpython-311.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/x448.cpython-311.pyc,, +cryptography/hazmat/primitives/asymmetric/dh.py,sha256=OOCjMClH1Bf14Sy7jAdwzEeCxFPb8XUe2qePbExvXwc,3420 +cryptography/hazmat/primitives/asymmetric/dsa.py,sha256=xBwdf0pZOgvqjUKcO7Q0L3NxwalYj0SJDUqThemhSmI,3945 +cryptography/hazmat/primitives/asymmetric/ec.py,sha256=W6nLb4Oho3BI3OsTR_nUI4WRHCbikTrqVOjQQYjV5vs,9704 +cryptography/hazmat/primitives/asymmetric/ed25519.py,sha256=kl63fg7myuMjNTmMoVFeH6iVr0x5FkjNmggxIRTloJk,3423 +cryptography/hazmat/primitives/asymmetric/ed448.py,sha256=2UzEDzzfkPn83UFVFlMZfIMbAixxY09WmQyrwinWTn8,3456 +cryptography/hazmat/primitives/asymmetric/padding.py,sha256=eZcvUqVLbe3u48SunLdeniaPlV4-k6pwBl67OW4jSy8,2885 +cryptography/hazmat/primitives/asymmetric/rsa.py,sha256=HToE4M5VJbGZS_2SbJ11kIGhtQ8D3GozW59sWEzrfZ4,6799 +cryptography/hazmat/primitives/asymmetric/types.py,sha256=LnsOJym-wmPUJ7Knu_7bCNU3kIiELCd6krOaW_JU08I,2996 +cryptography/hazmat/primitives/asymmetric/utils.py,sha256=DPTs6T4F-UhwzFQTh-1fSEpQzazH2jf2xpIro3ItF4o,790 +cryptography/hazmat/primitives/asymmetric/x25519.py,sha256=VGYuRdIYuVBtizpFdNWd2bTrT10JRa1admQdBr08xz8,3341 +cryptography/hazmat/primitives/asymmetric/x448.py,sha256=GKKJBqYLr03VewMF18bXIM941aaWcZIQ4rC02GLLEmw,3374 +cryptography/hazmat/primitives/ciphers/__init__.py,sha256=kAyb9NSczqTrCWj0HEoVp3Cxo7AHW8ibPFQz-ZHsOtA,680 +cryptography/hazmat/primitives/ciphers/__pycache__/__init__.cpython-311.pyc,, +cryptography/hazmat/primitives/ciphers/__pycache__/aead.cpython-311.pyc,, +cryptography/hazmat/primitives/ciphers/__pycache__/algorithms.cpython-311.pyc,, +cryptography/hazmat/primitives/ciphers/__pycache__/base.cpython-311.pyc,, +cryptography/hazmat/primitives/ciphers/__pycache__/modes.cpython-311.pyc,, +cryptography/hazmat/primitives/ciphers/aead.py,sha256=V6UKsIPNZQh0cfd8hpXx3ZzztQ-JQ9ChBMMN1ZTZXJ0,5540 +cryptography/hazmat/primitives/ciphers/algorithms.py,sha256=rNsvAJZIft8o0yan5Z62hJ-xoEM_Y6BYBkFs4jnnR2s,5120 +cryptography/hazmat/primitives/ciphers/base.py,sha256=4VktSqxhRjigjNQ3m2BiQQDo-1bYqCxXpddphJukoMI,8445 +cryptography/hazmat/primitives/ciphers/modes.py,sha256=Kw1419ZCUBNbbxd7BctwPp6i8rwnOvvifdXokrx_bYM,8317 +cryptography/hazmat/primitives/cmac.py,sha256=sz_s6H_cYnOvx-VNWdIKhRhe3Ymp8z8J0D3CBqOX3gg,338 +cryptography/hazmat/primitives/constant_time.py,sha256=xdunWT0nf8OvKdcqUhhlFKayGp4_PgVJRU2W1wLSr_A,422 +cryptography/hazmat/primitives/hashes.py,sha256=HCFCsR8p7OEWt1YA7oRbqgKHXOuZnrspkVrniU_B2uU,5091 +cryptography/hazmat/primitives/hmac.py,sha256=RpB3z9z5skirCQrm7zQbtnp9pLMnAjrlTUvKqF5aDDc,423 +cryptography/hazmat/primitives/kdf/__init__.py,sha256=4XibZnrYq4hh5xBjWiIXzaYW6FKx8hPbVaa_cB9zS64,750 +cryptography/hazmat/primitives/kdf/__pycache__/__init__.cpython-311.pyc,, +cryptography/hazmat/primitives/kdf/__pycache__/concatkdf.cpython-311.pyc,, +cryptography/hazmat/primitives/kdf/__pycache__/hkdf.cpython-311.pyc,, +cryptography/hazmat/primitives/kdf/__pycache__/kbkdf.cpython-311.pyc,, +cryptography/hazmat/primitives/kdf/__pycache__/pbkdf2.cpython-311.pyc,, +cryptography/hazmat/primitives/kdf/__pycache__/scrypt.cpython-311.pyc,, +cryptography/hazmat/primitives/kdf/__pycache__/x963kdf.cpython-311.pyc,, +cryptography/hazmat/primitives/kdf/concatkdf.py,sha256=bcn4NGXse-EsFl7nlU83e5ilop7TSHcX-CJJS107W80,3686 +cryptography/hazmat/primitives/kdf/hkdf.py,sha256=uhN5L87w4JvtAqQcPh_Ji2TPSc18IDThpaYJiHOWy3A,3015 +cryptography/hazmat/primitives/kdf/kbkdf.py,sha256=C3koAdtF_fwyvbhQA88AYbi3YOrUZ_7eaIM4DkWrfyM,9072 +cryptography/hazmat/primitives/kdf/pbkdf2.py,sha256=1CCH9Q5gXUpnZd3c8d8bCXgpJ3s2hZZGBnuG7FH1waM,2012 +cryptography/hazmat/primitives/kdf/scrypt.py,sha256=4QONhjxA_ZtuQtQ7QV3FnbB8ftrFnM52B4HPfV7hFys,2354 +cryptography/hazmat/primitives/kdf/x963kdf.py,sha256=wCpWmwQjZ2vAu2rlk3R_PX0nINl8WGXYBmlyMOC5iPw,1992 +cryptography/hazmat/primitives/keywrap.py,sha256=kHqtc56YvpTNEi6q1ifoHKXmY4SWqllBv-eBfqMpvuE,5650 +cryptography/hazmat/primitives/padding.py,sha256=g4qonAgYADkMArKt2MXD1XlnGd4ET_Rf5YDADwb_v8Q,6148 +cryptography/hazmat/primitives/poly1305.py,sha256=P5EPQV-RB_FJPahpg01u0Ts4S_PnAmsroxIGXbGeRRo,355 +cryptography/hazmat/primitives/serialization/__init__.py,sha256=6ZlL3EicEzoGdMOat86w8y_XICCnlHdCjFI97rMxRDg,1653 +cryptography/hazmat/primitives/serialization/__pycache__/__init__.cpython-311.pyc,, +cryptography/hazmat/primitives/serialization/__pycache__/base.cpython-311.pyc,, +cryptography/hazmat/primitives/serialization/__pycache__/pkcs12.cpython-311.pyc,, +cryptography/hazmat/primitives/serialization/__pycache__/pkcs7.cpython-311.pyc,, +cryptography/hazmat/primitives/serialization/__pycache__/ssh.cpython-311.pyc,, +cryptography/hazmat/primitives/serialization/base.py,sha256=ikq5MJIwp_oUnjiaBco_PmQwOTYuGi-XkYUYHKy8Vo0,615 +cryptography/hazmat/primitives/serialization/pkcs12.py,sha256=jtMcM-At_GZFRD5oSlOGHOE1OcosroWIvmkzrEsv75Q,6599 +cryptography/hazmat/primitives/serialization/pkcs7.py,sha256=uaWAdWggcM087zL1ltQc5fFhpXFFbBNn_2cyQK8toZ4,7488 +cryptography/hazmat/primitives/serialization/ssh.py,sha256=7JjL4ZWcOliyAOJdnlnWi_0nNlLtOrAoj6AqWHdrLNg,50051 +cryptography/hazmat/primitives/twofactor/__init__.py,sha256=tmMZGB-g4IU1r7lIFqASU019zr0uPp_wEBYcwdDCKCA,258 +cryptography/hazmat/primitives/twofactor/__pycache__/__init__.cpython-311.pyc,, +cryptography/hazmat/primitives/twofactor/__pycache__/hotp.cpython-311.pyc,, +cryptography/hazmat/primitives/twofactor/__pycache__/totp.cpython-311.pyc,, +cryptography/hazmat/primitives/twofactor/hotp.py,sha256=l1YdRMIhfPIuHKkA66keBDHhNbnBAlh6-O44P-OHIK8,2976 +cryptography/hazmat/primitives/twofactor/totp.py,sha256=v0y0xKwtYrP83ypOo5Ofd441RJLOkaFfjmp554jo5F0,1450 +cryptography/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +cryptography/utils.py,sha256=8fNXSfKvDgaji9M_m4lVXHFTVdIDP32GhlXzUBYDBHE,4033 +cryptography/x509/__init__.py,sha256=zaKuAaluw0p-lQm4RGK3_NBAG9V_UW6nhv_1m_ppugI,7924 +cryptography/x509/__pycache__/__init__.cpython-311.pyc,, +cryptography/x509/__pycache__/base.cpython-311.pyc,, +cryptography/x509/__pycache__/certificate_transparency.cpython-311.pyc,, +cryptography/x509/__pycache__/extensions.cpython-311.pyc,, +cryptography/x509/__pycache__/general_name.cpython-311.pyc,, +cryptography/x509/__pycache__/name.cpython-311.pyc,, +cryptography/x509/__pycache__/ocsp.cpython-311.pyc,, +cryptography/x509/__pycache__/oid.cpython-311.pyc,, +cryptography/x509/__pycache__/verification.cpython-311.pyc,, +cryptography/x509/base.py,sha256=U2ZTy4BMQKiQ7YwncAnfKffRv7KSzWaMvbbgMlO8blk,36933 +cryptography/x509/certificate_transparency.py,sha256=6HvzAD0dlSQVxy6tnDhGj0-pisp1MaJ9bxQNRr92inI,2261 +cryptography/x509/extensions.py,sha256=YU9R9IGt2tFl3zM7T2LI3dzQvKyvMhZxT2JgqCrZ3SE,66345 +cryptography/x509/general_name.py,sha256=sP_rV11Qlpsk4x3XXGJY_Mv0Q_s9dtjeLckHsjpLQoQ,7836 +cryptography/x509/name.py,sha256=85k7lJRtXnWTsVfsJXHNiWnDrsbW0OJ54np2opaBV28,14609 +cryptography/x509/ocsp.py,sha256=7Na0PAyA6nSyApTGd-QZ9Nfw2uyUS_PDVQx5XUw1xmU,18126 +cryptography/x509/oid.py,sha256=fFosjGsnIB_w_0YrzZv1ggkSVwZl7xmY0zofKZNZkDA,829 +cryptography/x509/verification.py,sha256=mPg6AUQDxK5wgGerP_hkFWD1Wj6l7lAt2IxpizZzekA,668 diff --git a/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/WHEEL b/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/WHEEL new file mode 100644 index 00000000..96dd4533 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.42.0) +Root-Is-Purelib: false +Tag: cp39-abi3-win_amd64 + diff --git a/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/top_level.txt b/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/top_level.txt new file mode 100644 index 00000000..0d38bc5e --- /dev/null +++ b/.venv/Lib/site-packages/cryptography-42.0.1.dist-info/top_level.txt @@ -0,0 +1 @@ +cryptography diff --git a/.venv/Lib/site-packages/cryptography/__about__.py b/.venv/Lib/site-packages/cryptography/__about__.py new file mode 100644 index 00000000..35d8510f --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/__about__.py @@ -0,0 +1,17 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +__all__ = [ + "__version__", + "__author__", + "__copyright__", +] + +__version__ = "42.0.1" + + +__author__ = "The Python Cryptographic Authority and individual contributors" +__copyright__ = f"Copyright 2013-2024 {__author__}" diff --git a/.venv/Lib/site-packages/cryptography/__init__.py b/.venv/Lib/site-packages/cryptography/__init__.py new file mode 100644 index 00000000..86b9a257 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/__init__.py @@ -0,0 +1,13 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +from cryptography.__about__ import __author__, __copyright__, __version__ + +__all__ = [ + "__version__", + "__author__", + "__copyright__", +] diff --git a/.venv/Lib/site-packages/cryptography/__pycache__/__about__.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/__pycache__/__about__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f2d832b6af6bb9baeb6f47680d47a0331f6a1ce3 GIT binary patch literal 485 zcmYjO&r9P#6n>MWskC;t2f=G_PX+DP){}@JE+~r>+0{!33~6RehfQa~WKu{^{VzN$ zg6w7S5AeAELyyv{CvO37?qy$AioSV#d>_0Y-^~1OwHko&_vD`cApnn+ScUaU$n!Rm zYhb`g0u$mB0x>Y_7x67-`!;iYht;_A6K*WO#@z4FsXtY%9kOhOQYsS~p=8#vmrY8i zTxX~#T{b8Ub2C;Nd5h9WrG*yp*ibri_xjylcXxJpG3MTRfko0g)GKv!I>BZ znJ|1O#iB6gSrENBFFxa*k;?Is-L!aFJD4bzC;U*a;}(2>$i5J0Qt0lt@l|v mPSYx31@n5j4j(t?&C-PrLo#nXv_w~u6%GqMn-Cas$zCp)?1tUVK|241y^Z(-{2y1R z60Gb3*PV?M0kC@83RYkrq zGbR{32uVXpq)3SQ5;d(bk`lEs;!O8RZ=h7kep|-A*Vmpk4ZP8 zm$F2Bg*B;QGrc&CQ<)VakMHGtdX=OPI=n`)`j86H7zAM z*YR%T31T4%N(}3Evwv2}tSR}q@+pM=67+L^-!xkP# J!%-d?egkvtd>a4& literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/__pycache__/exceptions.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/__pycache__/exceptions.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..82b5aa8cfdddf6ccb33767d50ba20a850056d969 GIT binary patch literal 2962 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 q$a$`U zK}mg^n%4zlIbuo#AaP9S9Q#B7(n(b>0C63NlU}54iX0<<)k7k5$inN?knmdfP;0Cu zB_aHZhn(!Us^Mf@Fre=#`m-Bt`z0@5N| zCD)I%fa3;4bZkf8Hx2Ga1LB_uJKo4482Y)wn}=4_5BuwH9avR=V^#edB9|{x*CN3x zvU7I$^ipD=5 z*E{#G0ZTzy!oLxI5K$y}ct3~-B&3bk0Wn27O31AszIIV!q4T-bE7KGS0p?opjM| literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/exceptions.py b/.venv/Lib/site-packages/cryptography/exceptions.py new file mode 100644 index 00000000..fe125ea9 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/exceptions.py @@ -0,0 +1,52 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import typing + +from cryptography.hazmat.bindings._rust import exceptions as rust_exceptions + +if typing.TYPE_CHECKING: + from cryptography.hazmat.bindings._rust import openssl as rust_openssl + +_Reasons = rust_exceptions._Reasons + + +class UnsupportedAlgorithm(Exception): + def __init__(self, message: str, reason: _Reasons | None = None) -> None: + super().__init__(message) + self._reason = reason + + +class AlreadyFinalized(Exception): + pass + + +class AlreadyUpdated(Exception): + pass + + +class NotYetFinalized(Exception): + pass + + +class InvalidTag(Exception): + pass + + +class InvalidSignature(Exception): + pass + + +class InternalError(Exception): + def __init__( + self, msg: str, err_code: list[rust_openssl.OpenSSLError] + ) -> None: + super().__init__(msg) + self.err_code = err_code + + +class InvalidKey(Exception): + pass diff --git a/.venv/Lib/site-packages/cryptography/fernet.py b/.venv/Lib/site-packages/cryptography/fernet.py new file mode 100644 index 00000000..35ce1131 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/fernet.py @@ -0,0 +1,215 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import base64 +import binascii +import os +import time +import typing + +from cryptography import utils +from cryptography.exceptions import InvalidSignature +from cryptography.hazmat.primitives import hashes, padding +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from cryptography.hazmat.primitives.hmac import HMAC + + +class InvalidToken(Exception): + pass + + +_MAX_CLOCK_SKEW = 60 + + +class Fernet: + def __init__( + self, + key: bytes | str, + backend: typing.Any = None, + ) -> None: + try: + key = base64.urlsafe_b64decode(key) + except binascii.Error as exc: + raise ValueError( + "Fernet key must be 32 url-safe base64-encoded bytes." + ) from exc + if len(key) != 32: + raise ValueError( + "Fernet key must be 32 url-safe base64-encoded bytes." + ) + + self._signing_key = key[:16] + self._encryption_key = key[16:] + + @classmethod + def generate_key(cls) -> bytes: + return base64.urlsafe_b64encode(os.urandom(32)) + + def encrypt(self, data: bytes) -> bytes: + return self.encrypt_at_time(data, int(time.time())) + + def encrypt_at_time(self, data: bytes, current_time: int) -> bytes: + iv = os.urandom(16) + return self._encrypt_from_parts(data, current_time, iv) + + def _encrypt_from_parts( + self, data: bytes, current_time: int, iv: bytes + ) -> bytes: + utils._check_bytes("data", data) + + padder = padding.PKCS7(algorithms.AES.block_size).padder() + padded_data = padder.update(data) + padder.finalize() + encryptor = Cipher( + algorithms.AES(self._encryption_key), + modes.CBC(iv), + ).encryptor() + ciphertext = encryptor.update(padded_data) + encryptor.finalize() + + basic_parts = ( + b"\x80" + + current_time.to_bytes(length=8, byteorder="big") + + iv + + ciphertext + ) + + h = HMAC(self._signing_key, hashes.SHA256()) + h.update(basic_parts) + hmac = h.finalize() + return base64.urlsafe_b64encode(basic_parts + hmac) + + def decrypt(self, token: bytes | str, ttl: int | None = None) -> bytes: + timestamp, data = Fernet._get_unverified_token_data(token) + if ttl is None: + time_info = None + else: + time_info = (ttl, int(time.time())) + return self._decrypt_data(data, timestamp, time_info) + + def decrypt_at_time( + self, token: bytes | str, ttl: int, current_time: int + ) -> bytes: + if ttl is None: + raise ValueError( + "decrypt_at_time() can only be used with a non-None ttl" + ) + timestamp, data = Fernet._get_unverified_token_data(token) + return self._decrypt_data(data, timestamp, (ttl, current_time)) + + def extract_timestamp(self, token: bytes | str) -> int: + timestamp, data = Fernet._get_unverified_token_data(token) + # Verify the token was not tampered with. + self._verify_signature(data) + return timestamp + + @staticmethod + def _get_unverified_token_data(token: bytes | str) -> tuple[int, bytes]: + if not isinstance(token, (str, bytes)): + raise TypeError("token must be bytes or str") + + try: + data = base64.urlsafe_b64decode(token) + except (TypeError, binascii.Error): + raise InvalidToken + + if not data or data[0] != 0x80: + raise InvalidToken + + if len(data) < 9: + raise InvalidToken + + timestamp = int.from_bytes(data[1:9], byteorder="big") + return timestamp, data + + def _verify_signature(self, data: bytes) -> None: + h = HMAC(self._signing_key, hashes.SHA256()) + h.update(data[:-32]) + try: + h.verify(data[-32:]) + except InvalidSignature: + raise InvalidToken + + def _decrypt_data( + self, + data: bytes, + timestamp: int, + time_info: tuple[int, int] | None, + ) -> bytes: + if time_info is not None: + ttl, current_time = time_info + if timestamp + ttl < current_time: + raise InvalidToken + + if current_time + _MAX_CLOCK_SKEW < timestamp: + raise InvalidToken + + self._verify_signature(data) + + iv = data[9:25] + ciphertext = data[25:-32] + decryptor = Cipher( + algorithms.AES(self._encryption_key), modes.CBC(iv) + ).decryptor() + plaintext_padded = decryptor.update(ciphertext) + try: + plaintext_padded += decryptor.finalize() + except ValueError: + raise InvalidToken + unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder() + + unpadded = unpadder.update(plaintext_padded) + try: + unpadded += unpadder.finalize() + except ValueError: + raise InvalidToken + return unpadded + + +class MultiFernet: + def __init__(self, fernets: typing.Iterable[Fernet]): + fernets = list(fernets) + if not fernets: + raise ValueError( + "MultiFernet requires at least one Fernet instance" + ) + self._fernets = fernets + + def encrypt(self, msg: bytes) -> bytes: + return self.encrypt_at_time(msg, int(time.time())) + + def encrypt_at_time(self, msg: bytes, current_time: int) -> bytes: + return self._fernets[0].encrypt_at_time(msg, current_time) + + def rotate(self, msg: bytes | str) -> bytes: + timestamp, data = Fernet._get_unverified_token_data(msg) + for f in self._fernets: + try: + p = f._decrypt_data(data, timestamp, None) + break + except InvalidToken: + pass + else: + raise InvalidToken + + iv = os.urandom(16) + return self._fernets[0]._encrypt_from_parts(p, timestamp, iv) + + def decrypt(self, msg: bytes | str, ttl: int | None = None) -> bytes: + for f in self._fernets: + try: + return f.decrypt(msg, ttl) + except InvalidToken: + pass + raise InvalidToken + + def decrypt_at_time( + self, msg: bytes | str, ttl: int, current_time: int + ) -> bytes: + for f in self._fernets: + try: + return f.decrypt_at_time(msg, ttl, current_time) + except InvalidToken: + pass + raise InvalidToken diff --git a/.venv/Lib/site-packages/cryptography/hazmat/__init__.py b/.venv/Lib/site-packages/cryptography/hazmat/__init__.py new file mode 100644 index 00000000..b9f11870 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/__init__.py @@ -0,0 +1,13 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +""" +Hazardous Materials + +This is a "Hazardous Materials" module. You should ONLY use it if you're +100% absolutely sure that you know what you're doing because this module +is full of land mines, dragons, and dinosaurs with laser guns. +""" diff --git a/.venv/Lib/site-packages/cryptography/hazmat/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b0f7424e8c9035afecdd1544fa4c8e1d539efb37 GIT binary patch literal 266 zcmZ3^%ge<81i#(4rXFWxV0aATzyK43!T4DS$e7NM!jQt4!;s4u#mLBz!W7J)$@~(e zK$GzncVb>%eo10UW`16=pC;2SuK4)0(vs4m)cE)!W}uRl44*+Ne?_}k#U$saWag#E zgyyG(cqArg7smvp=BDN*r52?YC#U8mr^e`&rRJ5z_+%!<6la#C>J|VMC8nnq$0Qe3 z7L??t7bO;CRO)9WR^=v^=*P!r=4F<|$LkeT{^GF7%}*)KNwq8D0NMrg3q!FokodsN e$jJDCi-A%30)rAV`oO}*$nt>!NEERF)d2v!Zc2v$ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/__pycache__/_oid.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/__pycache__/_oid.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e3962eb2c5f4f045511e3b75be45a4d540e7005c GIT binary patch literal 17971 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/_oid.py b/.venv/Lib/site-packages/cryptography/hazmat/_oid.py new file mode 100644 index 00000000..c5d062c1 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/_oid.py @@ -0,0 +1,296 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +from cryptography.hazmat.bindings._rust import ( + ObjectIdentifier as ObjectIdentifier, +) +from cryptography.hazmat.primitives import hashes + + +class ExtensionOID: + SUBJECT_DIRECTORY_ATTRIBUTES = ObjectIdentifier("2.5.29.9") + SUBJECT_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.14") + KEY_USAGE = ObjectIdentifier("2.5.29.15") + SUBJECT_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.17") + ISSUER_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.18") + BASIC_CONSTRAINTS = ObjectIdentifier("2.5.29.19") + NAME_CONSTRAINTS = ObjectIdentifier("2.5.29.30") + CRL_DISTRIBUTION_POINTS = ObjectIdentifier("2.5.29.31") + CERTIFICATE_POLICIES = ObjectIdentifier("2.5.29.32") + POLICY_MAPPINGS = ObjectIdentifier("2.5.29.33") + AUTHORITY_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.35") + POLICY_CONSTRAINTS = ObjectIdentifier("2.5.29.36") + EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37") + FRESHEST_CRL = ObjectIdentifier("2.5.29.46") + INHIBIT_ANY_POLICY = ObjectIdentifier("2.5.29.54") + ISSUING_DISTRIBUTION_POINT = ObjectIdentifier("2.5.29.28") + AUTHORITY_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.1") + SUBJECT_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.11") + OCSP_NO_CHECK = ObjectIdentifier("1.3.6.1.5.5.7.48.1.5") + TLS_FEATURE = ObjectIdentifier("1.3.6.1.5.5.7.1.24") + CRL_NUMBER = ObjectIdentifier("2.5.29.20") + DELTA_CRL_INDICATOR = ObjectIdentifier("2.5.29.27") + PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS = ObjectIdentifier( + "1.3.6.1.4.1.11129.2.4.2" + ) + PRECERT_POISON = ObjectIdentifier("1.3.6.1.4.1.11129.2.4.3") + SIGNED_CERTIFICATE_TIMESTAMPS = ObjectIdentifier("1.3.6.1.4.1.11129.2.4.5") + MS_CERTIFICATE_TEMPLATE = ObjectIdentifier("1.3.6.1.4.1.311.21.7") + + +class OCSPExtensionOID: + NONCE = ObjectIdentifier("1.3.6.1.5.5.7.48.1.2") + ACCEPTABLE_RESPONSES = ObjectIdentifier("1.3.6.1.5.5.7.48.1.4") + + +class CRLEntryExtensionOID: + CERTIFICATE_ISSUER = ObjectIdentifier("2.5.29.29") + CRL_REASON = ObjectIdentifier("2.5.29.21") + INVALIDITY_DATE = ObjectIdentifier("2.5.29.24") + + +class NameOID: + COMMON_NAME = ObjectIdentifier("2.5.4.3") + COUNTRY_NAME = ObjectIdentifier("2.5.4.6") + LOCALITY_NAME = ObjectIdentifier("2.5.4.7") + STATE_OR_PROVINCE_NAME = ObjectIdentifier("2.5.4.8") + STREET_ADDRESS = ObjectIdentifier("2.5.4.9") + ORGANIZATION_IDENTIFIER = ObjectIdentifier("2.5.4.97") + ORGANIZATION_NAME = ObjectIdentifier("2.5.4.10") + ORGANIZATIONAL_UNIT_NAME = ObjectIdentifier("2.5.4.11") + SERIAL_NUMBER = ObjectIdentifier("2.5.4.5") + SURNAME = ObjectIdentifier("2.5.4.4") + GIVEN_NAME = ObjectIdentifier("2.5.4.42") + TITLE = ObjectIdentifier("2.5.4.12") + INITIALS = ObjectIdentifier("2.5.4.43") + GENERATION_QUALIFIER = ObjectIdentifier("2.5.4.44") + X500_UNIQUE_IDENTIFIER = ObjectIdentifier("2.5.4.45") + DN_QUALIFIER = ObjectIdentifier("2.5.4.46") + PSEUDONYM = ObjectIdentifier("2.5.4.65") + USER_ID = ObjectIdentifier("0.9.2342.19200300.100.1.1") + DOMAIN_COMPONENT = ObjectIdentifier("0.9.2342.19200300.100.1.25") + EMAIL_ADDRESS = ObjectIdentifier("1.2.840.113549.1.9.1") + JURISDICTION_COUNTRY_NAME = ObjectIdentifier("1.3.6.1.4.1.311.60.2.1.3") + JURISDICTION_LOCALITY_NAME = ObjectIdentifier("1.3.6.1.4.1.311.60.2.1.1") + JURISDICTION_STATE_OR_PROVINCE_NAME = ObjectIdentifier( + "1.3.6.1.4.1.311.60.2.1.2" + ) + BUSINESS_CATEGORY = ObjectIdentifier("2.5.4.15") + POSTAL_ADDRESS = ObjectIdentifier("2.5.4.16") + POSTAL_CODE = ObjectIdentifier("2.5.4.17") + INN = ObjectIdentifier("1.2.643.3.131.1.1") + OGRN = ObjectIdentifier("1.2.643.100.1") + SNILS = ObjectIdentifier("1.2.643.100.3") + UNSTRUCTURED_NAME = ObjectIdentifier("1.2.840.113549.1.9.2") + + +class SignatureAlgorithmOID: + RSA_WITH_MD5 = ObjectIdentifier("1.2.840.113549.1.1.4") + RSA_WITH_SHA1 = ObjectIdentifier("1.2.840.113549.1.1.5") + # This is an alternate OID for RSA with SHA1 that is occasionally seen + _RSA_WITH_SHA1 = ObjectIdentifier("1.3.14.3.2.29") + RSA_WITH_SHA224 = ObjectIdentifier("1.2.840.113549.1.1.14") + RSA_WITH_SHA256 = ObjectIdentifier("1.2.840.113549.1.1.11") + RSA_WITH_SHA384 = ObjectIdentifier("1.2.840.113549.1.1.12") + RSA_WITH_SHA512 = ObjectIdentifier("1.2.840.113549.1.1.13") + RSA_WITH_SHA3_224 = ObjectIdentifier("2.16.840.1.101.3.4.3.13") + RSA_WITH_SHA3_256 = ObjectIdentifier("2.16.840.1.101.3.4.3.14") + RSA_WITH_SHA3_384 = ObjectIdentifier("2.16.840.1.101.3.4.3.15") + RSA_WITH_SHA3_512 = ObjectIdentifier("2.16.840.1.101.3.4.3.16") + RSASSA_PSS = ObjectIdentifier("1.2.840.113549.1.1.10") + ECDSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10045.4.1") + ECDSA_WITH_SHA224 = ObjectIdentifier("1.2.840.10045.4.3.1") + ECDSA_WITH_SHA256 = ObjectIdentifier("1.2.840.10045.4.3.2") + ECDSA_WITH_SHA384 = ObjectIdentifier("1.2.840.10045.4.3.3") + ECDSA_WITH_SHA512 = ObjectIdentifier("1.2.840.10045.4.3.4") + ECDSA_WITH_SHA3_224 = ObjectIdentifier("2.16.840.1.101.3.4.3.9") + ECDSA_WITH_SHA3_256 = ObjectIdentifier("2.16.840.1.101.3.4.3.10") + ECDSA_WITH_SHA3_384 = ObjectIdentifier("2.16.840.1.101.3.4.3.11") + ECDSA_WITH_SHA3_512 = ObjectIdentifier("2.16.840.1.101.3.4.3.12") + DSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10040.4.3") + DSA_WITH_SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.3.1") + DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2") + DSA_WITH_SHA384 = ObjectIdentifier("2.16.840.1.101.3.4.3.3") + DSA_WITH_SHA512 = ObjectIdentifier("2.16.840.1.101.3.4.3.4") + ED25519 = ObjectIdentifier("1.3.101.112") + ED448 = ObjectIdentifier("1.3.101.113") + GOSTR3411_94_WITH_3410_2001 = ObjectIdentifier("1.2.643.2.2.3") + GOSTR3410_2012_WITH_3411_2012_256 = ObjectIdentifier("1.2.643.7.1.1.3.2") + GOSTR3410_2012_WITH_3411_2012_512 = ObjectIdentifier("1.2.643.7.1.1.3.3") + + +_SIG_OIDS_TO_HASH: dict[ObjectIdentifier, hashes.HashAlgorithm | None] = { + SignatureAlgorithmOID.RSA_WITH_MD5: hashes.MD5(), + SignatureAlgorithmOID.RSA_WITH_SHA1: hashes.SHA1(), + SignatureAlgorithmOID._RSA_WITH_SHA1: hashes.SHA1(), + SignatureAlgorithmOID.RSA_WITH_SHA224: hashes.SHA224(), + SignatureAlgorithmOID.RSA_WITH_SHA256: hashes.SHA256(), + SignatureAlgorithmOID.RSA_WITH_SHA384: hashes.SHA384(), + SignatureAlgorithmOID.RSA_WITH_SHA512: hashes.SHA512(), + SignatureAlgorithmOID.RSA_WITH_SHA3_224: hashes.SHA3_224(), + SignatureAlgorithmOID.RSA_WITH_SHA3_256: hashes.SHA3_256(), + SignatureAlgorithmOID.RSA_WITH_SHA3_384: hashes.SHA3_384(), + SignatureAlgorithmOID.RSA_WITH_SHA3_512: hashes.SHA3_512(), + SignatureAlgorithmOID.ECDSA_WITH_SHA1: hashes.SHA1(), + SignatureAlgorithmOID.ECDSA_WITH_SHA224: hashes.SHA224(), + SignatureAlgorithmOID.ECDSA_WITH_SHA256: hashes.SHA256(), + SignatureAlgorithmOID.ECDSA_WITH_SHA384: hashes.SHA384(), + SignatureAlgorithmOID.ECDSA_WITH_SHA512: hashes.SHA512(), + SignatureAlgorithmOID.ECDSA_WITH_SHA3_224: hashes.SHA3_224(), + SignatureAlgorithmOID.ECDSA_WITH_SHA3_256: hashes.SHA3_256(), + SignatureAlgorithmOID.ECDSA_WITH_SHA3_384: hashes.SHA3_384(), + SignatureAlgorithmOID.ECDSA_WITH_SHA3_512: hashes.SHA3_512(), + SignatureAlgorithmOID.DSA_WITH_SHA1: hashes.SHA1(), + SignatureAlgorithmOID.DSA_WITH_SHA224: hashes.SHA224(), + SignatureAlgorithmOID.DSA_WITH_SHA256: hashes.SHA256(), + SignatureAlgorithmOID.ED25519: None, + SignatureAlgorithmOID.ED448: None, + SignatureAlgorithmOID.GOSTR3411_94_WITH_3410_2001: None, + SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_256: None, + SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_512: None, +} + + +class ExtendedKeyUsageOID: + SERVER_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.1") + CLIENT_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.2") + CODE_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.3") + EMAIL_PROTECTION = ObjectIdentifier("1.3.6.1.5.5.7.3.4") + TIME_STAMPING = ObjectIdentifier("1.3.6.1.5.5.7.3.8") + OCSP_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.9") + ANY_EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37.0") + SMARTCARD_LOGON = ObjectIdentifier("1.3.6.1.4.1.311.20.2.2") + KERBEROS_PKINIT_KDC = ObjectIdentifier("1.3.6.1.5.2.3.5") + IPSEC_IKE = ObjectIdentifier("1.3.6.1.5.5.7.3.17") + CERTIFICATE_TRANSPARENCY = ObjectIdentifier("1.3.6.1.4.1.11129.2.4.4") + + +class AuthorityInformationAccessOID: + CA_ISSUERS = ObjectIdentifier("1.3.6.1.5.5.7.48.2") + OCSP = ObjectIdentifier("1.3.6.1.5.5.7.48.1") + + +class SubjectInformationAccessOID: + CA_REPOSITORY = ObjectIdentifier("1.3.6.1.5.5.7.48.5") + + +class CertificatePoliciesOID: + CPS_QUALIFIER = ObjectIdentifier("1.3.6.1.5.5.7.2.1") + CPS_USER_NOTICE = ObjectIdentifier("1.3.6.1.5.5.7.2.2") + ANY_POLICY = ObjectIdentifier("2.5.29.32.0") + + +class AttributeOID: + CHALLENGE_PASSWORD = ObjectIdentifier("1.2.840.113549.1.9.7") + UNSTRUCTURED_NAME = ObjectIdentifier("1.2.840.113549.1.9.2") + + +_OID_NAMES = { + NameOID.COMMON_NAME: "commonName", + NameOID.COUNTRY_NAME: "countryName", + NameOID.LOCALITY_NAME: "localityName", + NameOID.STATE_OR_PROVINCE_NAME: "stateOrProvinceName", + NameOID.STREET_ADDRESS: "streetAddress", + NameOID.ORGANIZATION_NAME: "organizationName", + NameOID.ORGANIZATIONAL_UNIT_NAME: "organizationalUnitName", + NameOID.SERIAL_NUMBER: "serialNumber", + NameOID.SURNAME: "surname", + NameOID.GIVEN_NAME: "givenName", + NameOID.TITLE: "title", + NameOID.GENERATION_QUALIFIER: "generationQualifier", + NameOID.X500_UNIQUE_IDENTIFIER: "x500UniqueIdentifier", + NameOID.DN_QUALIFIER: "dnQualifier", + NameOID.PSEUDONYM: "pseudonym", + NameOID.USER_ID: "userID", + NameOID.DOMAIN_COMPONENT: "domainComponent", + NameOID.EMAIL_ADDRESS: "emailAddress", + NameOID.JURISDICTION_COUNTRY_NAME: "jurisdictionCountryName", + NameOID.JURISDICTION_LOCALITY_NAME: "jurisdictionLocalityName", + NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME: ( + "jurisdictionStateOrProvinceName" + ), + NameOID.BUSINESS_CATEGORY: "businessCategory", + NameOID.POSTAL_ADDRESS: "postalAddress", + NameOID.POSTAL_CODE: "postalCode", + NameOID.INN: "INN", + NameOID.OGRN: "OGRN", + NameOID.SNILS: "SNILS", + NameOID.UNSTRUCTURED_NAME: "unstructuredName", + SignatureAlgorithmOID.RSA_WITH_MD5: "md5WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA1: "sha1WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA224: "sha224WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA256: "sha256WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA384: "sha384WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA512: "sha512WithRSAEncryption", + SignatureAlgorithmOID.RSASSA_PSS: "RSASSA-PSS", + SignatureAlgorithmOID.ECDSA_WITH_SHA1: "ecdsa-with-SHA1", + SignatureAlgorithmOID.ECDSA_WITH_SHA224: "ecdsa-with-SHA224", + SignatureAlgorithmOID.ECDSA_WITH_SHA256: "ecdsa-with-SHA256", + SignatureAlgorithmOID.ECDSA_WITH_SHA384: "ecdsa-with-SHA384", + SignatureAlgorithmOID.ECDSA_WITH_SHA512: "ecdsa-with-SHA512", + SignatureAlgorithmOID.DSA_WITH_SHA1: "dsa-with-sha1", + SignatureAlgorithmOID.DSA_WITH_SHA224: "dsa-with-sha224", + SignatureAlgorithmOID.DSA_WITH_SHA256: "dsa-with-sha256", + SignatureAlgorithmOID.ED25519: "ed25519", + SignatureAlgorithmOID.ED448: "ed448", + SignatureAlgorithmOID.GOSTR3411_94_WITH_3410_2001: ( + "GOST R 34.11-94 with GOST R 34.10-2001" + ), + SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_256: ( + "GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)" + ), + SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_512: ( + "GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)" + ), + ExtendedKeyUsageOID.SERVER_AUTH: "serverAuth", + ExtendedKeyUsageOID.CLIENT_AUTH: "clientAuth", + ExtendedKeyUsageOID.CODE_SIGNING: "codeSigning", + ExtendedKeyUsageOID.EMAIL_PROTECTION: "emailProtection", + ExtendedKeyUsageOID.TIME_STAMPING: "timeStamping", + ExtendedKeyUsageOID.OCSP_SIGNING: "OCSPSigning", + ExtendedKeyUsageOID.SMARTCARD_LOGON: "msSmartcardLogin", + ExtendedKeyUsageOID.KERBEROS_PKINIT_KDC: "pkInitKDC", + ExtensionOID.SUBJECT_DIRECTORY_ATTRIBUTES: "subjectDirectoryAttributes", + ExtensionOID.SUBJECT_KEY_IDENTIFIER: "subjectKeyIdentifier", + ExtensionOID.KEY_USAGE: "keyUsage", + ExtensionOID.SUBJECT_ALTERNATIVE_NAME: "subjectAltName", + ExtensionOID.ISSUER_ALTERNATIVE_NAME: "issuerAltName", + ExtensionOID.BASIC_CONSTRAINTS: "basicConstraints", + ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: ( + "signedCertificateTimestampList" + ), + ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS: ( + "signedCertificateTimestampList" + ), + ExtensionOID.PRECERT_POISON: "ctPoison", + ExtensionOID.MS_CERTIFICATE_TEMPLATE: "msCertificateTemplate", + CRLEntryExtensionOID.CRL_REASON: "cRLReason", + CRLEntryExtensionOID.INVALIDITY_DATE: "invalidityDate", + CRLEntryExtensionOID.CERTIFICATE_ISSUER: "certificateIssuer", + ExtensionOID.NAME_CONSTRAINTS: "nameConstraints", + ExtensionOID.CRL_DISTRIBUTION_POINTS: "cRLDistributionPoints", + ExtensionOID.CERTIFICATE_POLICIES: "certificatePolicies", + ExtensionOID.POLICY_MAPPINGS: "policyMappings", + ExtensionOID.AUTHORITY_KEY_IDENTIFIER: "authorityKeyIdentifier", + ExtensionOID.POLICY_CONSTRAINTS: "policyConstraints", + ExtensionOID.EXTENDED_KEY_USAGE: "extendedKeyUsage", + ExtensionOID.FRESHEST_CRL: "freshestCRL", + ExtensionOID.INHIBIT_ANY_POLICY: "inhibitAnyPolicy", + ExtensionOID.ISSUING_DISTRIBUTION_POINT: "issuingDistributionPoint", + ExtensionOID.AUTHORITY_INFORMATION_ACCESS: "authorityInfoAccess", + ExtensionOID.SUBJECT_INFORMATION_ACCESS: "subjectInfoAccess", + ExtensionOID.OCSP_NO_CHECK: "OCSPNoCheck", + ExtensionOID.CRL_NUMBER: "cRLNumber", + ExtensionOID.DELTA_CRL_INDICATOR: "deltaCRLIndicator", + ExtensionOID.TLS_FEATURE: "TLSFeature", + AuthorityInformationAccessOID.OCSP: "OCSP", + AuthorityInformationAccessOID.CA_ISSUERS: "caIssuers", + SubjectInformationAccessOID.CA_REPOSITORY: "caRepository", + CertificatePoliciesOID.CPS_QUALIFIER: "id-qt-cps", + CertificatePoliciesOID.CPS_USER_NOTICE: "id-qt-unotice", + OCSPExtensionOID.NONCE: "OCSPNonce", + AttributeOID.CHALLENGE_PASSWORD: "challengePassword", +} diff --git a/.venv/Lib/site-packages/cryptography/hazmat/backends/__init__.py b/.venv/Lib/site-packages/cryptography/hazmat/backends/__init__.py new file mode 100644 index 00000000..b4400aa0 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/backends/__init__.py @@ -0,0 +1,13 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +from typing import Any + + +def default_backend() -> Any: + from cryptography.hazmat.backends.openssl.backend import backend + + return backend diff --git a/.venv/Lib/site-packages/cryptography/hazmat/backends/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/backends/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1233a821ff87a34aa5495e4a5e0946559a9fff21 GIT binary patch literal 576 zcmZ`#%}T>S5S~r?M{7|O1aG1s1T?*i2!f!3^x)5>1eP?rZG*`s>~0GY1rNT1k03sP z@6n^=RPf}j&|AGYTP?H)hhg@c{buIdo!5H33TWSF?>r;`pC*}`^$W;k55WsCU?hT= zvBOYTU2iRDmUiJ4N5~1YD(QS%U2oi`29%JKUUUI+-zKJVR(X%!s&3?N452* z<^)M-I+iTrIa`-g%&U}k`nW$%sl;VLUeZ~L@1OCr!EYc}OoI`aR*vF?^&@^P*Dy7o hRu>q?HX&qO1+qJYokbtP=5X1^C7W!F;h!**`T-O)mr4Kt literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__init__.py b/.venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__init__.py new file mode 100644 index 00000000..51b04476 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__init__.py @@ -0,0 +1,9 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +from cryptography.hazmat.backends.openssl.backend import backend + +__all__ = ["backend"] diff --git a/.venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..21309476e1490558d5019441209ce5290df2fc01 GIT binary patch literal 396 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 IvHA7?1#w=dJpcdz literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__pycache__/ciphers.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__pycache__/ciphers.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..887c2e3a4bd6636633c1693706f25493d4e6da27 GIT binary patch literal 14002 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

^K_t)2F{(n}FA(+0+cI*Lv3 z8yc{gjg1TZ6jwET0X;<^_l4&n@f$ zlNdvAfgA$-U5F{bEFPe;epjIYloC|(vWBl!6ghJnuEw$B#c%~4@IsC6fI{lOAplgs z7g(P9WY5Z;OjXh8gWIi1G0;(PcI2EL1P3^^?j0<62hlG-Bl;tod;ZmwC$KDt!S;f? zJ?CyGjZd$8hYQ|eXe|2idTSHVpjtaK4i`L!QArPjp2PbwF?jM{>b@HPr_k?0zdr;N zw0p;w-1?L;e^4JEFMYK1;ZN@UBxi4yU1~Vz)CVOUPmx;i2QY+B8&Wfj3GWJZykcH>Fy#lGpFJ(@2|*d~-qmgo1o(!DF9%Ed~fqgLb-% zalAs3b1??3v|M7WYUS9z&8(|yk$nTL2BGi*UD8{*-QOS$4}LR&UlK74d=Z6TM$N}D z?qZmC=c94Cg#R%PEQP@|25)14f6YMvQ=(w`4>0-H5J+}#jo`0DgatCBUs19}aS6-u z)FA;*J@s1%?yCQaHQu{Ja!|kJ?r6z!+hh%u;A8)akf&*DGgxqjpn8WD>{eqiWIADe zt3(-tQ|3DBwi0Cw_ByN`CCV7oQ#KEnjYw7rp3{)`!R3lvd3rdrHZQVpdLI5F23W}B z;VaqT6E6G$C#e6FCBogA;^xSo70J#R+8*+!T+N1h@+U8mIX*TE8}k-?YlC`9+V%2E zk@6QYU-?jt0GwaN@SmXcU zb#KBS;QzsagV~dbr@b}dh8Jhr?4~<;nS9^py|-`P+n@D%73uTu{V(`lLg=q?(z7%c z*3DfDp&!UWj^!cWI<_pM3tqu59v3YH#Zz55KBrTua`JpSv0tTWiA6Jo;!m9ros=T@R@?RPRXRZNL-hBZ1hA-yM%XiO;z;* zkO~~F?^94}92PDXnva}#fr1Qm3ra%3UEw+LyaZqL0lT^rrqYWS1IhZ#gAU+x7Iqy; z&UsuXx&AA7yS&MTV=hw+YmB;3Of zgq|t84L!6zt7D@V>pvPHe?OcpB&=(g9^puB+K4-+U4_PjnEtqndgmu9Vkw zKz|=FQT+L4Ft{zh_Jz~);Ei0>{mm~^m--qOEz25Kk+pV(8k6=1EnnqrxPqoC*QKTF z(u3&X?^1ar*P>6UY(!hBe0-55tVVZI`s5 bool: + cipher_name = _evp_cipher_cipher_name(cipher) + + return backend._lib.EVP_get_cipherbyname(cipher_name) != backend._ffi.NULL + + +def _encrypt( + backend: Backend, + cipher: _AEADTypes, + nonce: bytes, + data: bytes, + associated_data: list[bytes], + tag_length: int, +) -> bytes: + return _evp_cipher_encrypt( + backend, cipher, nonce, data, associated_data, tag_length + ) + + +def _decrypt( + backend: Backend, + cipher: _AEADTypes, + nonce: bytes, + data: bytes, + associated_data: list[bytes], + tag_length: int, +) -> bytes: + return _evp_cipher_decrypt( + backend, cipher, nonce, data, associated_data, tag_length + ) + + +_ENCRYPT = 1 +_DECRYPT = 0 + + +def _evp_cipher_cipher_name(cipher: _AEADTypes) -> bytes: + from cryptography.hazmat.primitives.ciphers.aead import ( + AESCCM, + AESGCM, + ) + + if isinstance(cipher, AESCCM): + return f"aes-{len(cipher._key) * 8}-ccm".encode("ascii") + else: + assert isinstance(cipher, AESGCM) + return f"aes-{len(cipher._key) * 8}-gcm".encode("ascii") + + +def _evp_cipher(cipher_name: bytes, backend: Backend): + evp_cipher = backend._lib.EVP_get_cipherbyname(cipher_name) + backend.openssl_assert(evp_cipher != backend._ffi.NULL) + return evp_cipher + + +def _evp_cipher_aead_setup( + backend: Backend, + cipher_name: bytes, + key: bytes, + nonce: bytes, + tag: bytes | None, + tag_len: int, + operation: int, +): + evp_cipher = _evp_cipher(cipher_name, backend) + ctx = backend._lib.EVP_CIPHER_CTX_new() + ctx = backend._ffi.gc(ctx, backend._lib.EVP_CIPHER_CTX_free) + res = backend._lib.EVP_CipherInit_ex( + ctx, + evp_cipher, + backend._ffi.NULL, + backend._ffi.NULL, + backend._ffi.NULL, + int(operation == _ENCRYPT), + ) + backend.openssl_assert(res != 0) + # CCM requires the IVLEN to be set before calling SET_TAG on decrypt + res = backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, + backend._lib.EVP_CTRL_AEAD_SET_IVLEN, + len(nonce), + backend._ffi.NULL, + ) + backend.openssl_assert(res != 0) + if operation == _DECRYPT: + assert tag is not None + _evp_cipher_set_tag(backend, ctx, tag) + elif cipher_name.endswith(b"-ccm"): + res = backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, + backend._lib.EVP_CTRL_AEAD_SET_TAG, + tag_len, + backend._ffi.NULL, + ) + backend.openssl_assert(res != 0) + + nonce_ptr = backend._ffi.from_buffer(nonce) + key_ptr = backend._ffi.from_buffer(key) + res = backend._lib.EVP_CipherInit_ex( + ctx, + backend._ffi.NULL, + backend._ffi.NULL, + key_ptr, + nonce_ptr, + int(operation == _ENCRYPT), + ) + backend.openssl_assert(res != 0) + return ctx + + +def _evp_cipher_set_tag(backend, ctx, tag: bytes) -> None: + tag_ptr = backend._ffi.from_buffer(tag) + res = backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, len(tag), tag_ptr + ) + backend.openssl_assert(res != 0) + + +def _evp_cipher_set_length(backend: Backend, ctx, data_len: int) -> None: + intptr = backend._ffi.new("int *") + res = backend._lib.EVP_CipherUpdate( + ctx, backend._ffi.NULL, intptr, backend._ffi.NULL, data_len + ) + backend.openssl_assert(res != 0) + + +def _evp_cipher_process_aad( + backend: Backend, ctx, associated_data: bytes +) -> None: + outlen = backend._ffi.new("int *") + a_data_ptr = backend._ffi.from_buffer(associated_data) + res = backend._lib.EVP_CipherUpdate( + ctx, backend._ffi.NULL, outlen, a_data_ptr, len(associated_data) + ) + backend.openssl_assert(res != 0) + + +def _evp_cipher_process_data(backend: Backend, ctx, data: bytes) -> bytes: + outlen = backend._ffi.new("int *") + buf = backend._ffi.new("unsigned char[]", len(data)) + data_ptr = backend._ffi.from_buffer(data) + res = backend._lib.EVP_CipherUpdate(ctx, buf, outlen, data_ptr, len(data)) + backend.openssl_assert(res != 0) + return backend._ffi.buffer(buf, outlen[0])[:] + + +def _evp_cipher_encrypt( + backend: Backend, + cipher: _AEADTypes, + nonce: bytes, + data: bytes, + associated_data: list[bytes], + tag_length: int, +) -> bytes: + from cryptography.hazmat.primitives.ciphers.aead import AESCCM + + cipher_name = _evp_cipher_cipher_name(cipher) + ctx = _evp_cipher_aead_setup( + backend, + cipher_name, + cipher._key, + nonce, + None, + tag_length, + _ENCRYPT, + ) + + # CCM requires us to pass the length of the data before processing + # anything. + # However calling this with any other AEAD results in an error + if isinstance(cipher, AESCCM): + _evp_cipher_set_length(backend, ctx, len(data)) + + for ad in associated_data: + _evp_cipher_process_aad(backend, ctx, ad) + processed_data = _evp_cipher_process_data(backend, ctx, data) + outlen = backend._ffi.new("int *") + # All AEADs we support besides OCB are streaming so they return nothing + # in finalization. OCB can return up to (16 byte block - 1) bytes so + # we need a buffer here too. + buf = backend._ffi.new("unsigned char[]", 16) + res = backend._lib.EVP_CipherFinal_ex(ctx, buf, outlen) + backend.openssl_assert(res != 0) + processed_data += backend._ffi.buffer(buf, outlen[0])[:] + tag_buf = backend._ffi.new("unsigned char[]", tag_length) + res = backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, backend._lib.EVP_CTRL_AEAD_GET_TAG, tag_length, tag_buf + ) + backend.openssl_assert(res != 0) + tag = backend._ffi.buffer(tag_buf)[:] + + return processed_data + tag + + +def _evp_cipher_decrypt( + backend: Backend, + cipher: _AEADTypes, + nonce: bytes, + data: bytes, + associated_data: list[bytes], + tag_length: int, +) -> bytes: + from cryptography.hazmat.primitives.ciphers.aead import AESCCM + + if len(data) < tag_length: + raise InvalidTag + + tag = data[-tag_length:] + data = data[:-tag_length] + cipher_name = _evp_cipher_cipher_name(cipher) + ctx = _evp_cipher_aead_setup( + backend, + cipher_name, + cipher._key, + nonce, + tag, + tag_length, + _DECRYPT, + ) + + # CCM requires us to pass the length of the data before processing + # anything. + # However calling this with any other AEAD results in an error + if isinstance(cipher, AESCCM): + _evp_cipher_set_length(backend, ctx, len(data)) + + for ad in associated_data: + _evp_cipher_process_aad(backend, ctx, ad) + # CCM has a different error path if the tag doesn't match. Errors are + # raised in Update and Final is irrelevant. + if isinstance(cipher, AESCCM): + outlen = backend._ffi.new("int *") + buf = backend._ffi.new("unsigned char[]", len(data)) + d_ptr = backend._ffi.from_buffer(data) + res = backend._lib.EVP_CipherUpdate(ctx, buf, outlen, d_ptr, len(data)) + if res != 1: + backend._consume_errors() + raise InvalidTag + + processed_data = backend._ffi.buffer(buf, outlen[0])[:] + else: + processed_data = _evp_cipher_process_data(backend, ctx, data) + outlen = backend._ffi.new("int *") + # OCB can return up to 15 bytes (16 byte block - 1) in finalization + buf = backend._ffi.new("unsigned char[]", 16) + res = backend._lib.EVP_CipherFinal_ex(ctx, buf, outlen) + processed_data += backend._ffi.buffer(buf, outlen[0])[:] + if res == 0: + backend._consume_errors() + raise InvalidTag + + return processed_data diff --git a/.venv/Lib/site-packages/cryptography/hazmat/backends/openssl/backend.py b/.venv/Lib/site-packages/cryptography/hazmat/backends/openssl/backend.py new file mode 100644 index 00000000..5d9eb276 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/backends/openssl/backend.py @@ -0,0 +1,897 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import collections +import contextlib +import itertools +import typing + +from cryptography import utils, x509 +from cryptography.exceptions import UnsupportedAlgorithm +from cryptography.hazmat.backends.openssl import aead +from cryptography.hazmat.backends.openssl.ciphers import _CipherContext +from cryptography.hazmat.bindings._rust import openssl as rust_openssl +from cryptography.hazmat.bindings.openssl import binding +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives._asymmetric import AsymmetricPadding +from cryptography.hazmat.primitives.asymmetric import ec +from cryptography.hazmat.primitives.asymmetric import utils as asym_utils +from cryptography.hazmat.primitives.asymmetric.padding import ( + MGF1, + OAEP, + PSS, + PKCS1v15, +) +from cryptography.hazmat.primitives.asymmetric.types import ( + PrivateKeyTypes, +) +from cryptography.hazmat.primitives.ciphers import ( + CipherAlgorithm, +) +from cryptography.hazmat.primitives.ciphers.algorithms import ( + AES, + AES128, + AES256, + ARC4, + SM4, + Camellia, + ChaCha20, + TripleDES, + _BlowfishInternal, + _CAST5Internal, + _IDEAInternal, + _SEEDInternal, +) +from cryptography.hazmat.primitives.ciphers.modes import ( + CBC, + CFB, + CFB8, + CTR, + ECB, + GCM, + OFB, + XTS, + Mode, +) +from cryptography.hazmat.primitives.serialization.pkcs12 import ( + PBES, + PKCS12Certificate, + PKCS12KeyAndCertificates, + PKCS12PrivateKeyTypes, + _PKCS12CATypes, +) + +_MemoryBIO = collections.namedtuple("_MemoryBIO", ["bio", "char_ptr"]) + + +# Not actually supported, just used as a marker for some serialization tests. +class _RC2: + pass + + +class Backend: + """ + OpenSSL API binding interfaces. + """ + + name = "openssl" + + # FIPS has opinions about acceptable algorithms and key sizes, but the + # disallowed algorithms are still present in OpenSSL. They just error if + # you try to use them. To avoid that we allowlist the algorithms in + # FIPS 140-3. This isn't ideal, but FIPS 140-3 is trash so here we are. + _fips_aead: typing.ClassVar[set[bytes]] = { + b"aes-128-ccm", + b"aes-192-ccm", + b"aes-256-ccm", + b"aes-128-gcm", + b"aes-192-gcm", + b"aes-256-gcm", + } + # TripleDES encryption is disallowed/deprecated throughout 2023 in + # FIPS 140-3. To keep it simple we denylist any use of TripleDES (TDEA). + _fips_ciphers = (AES,) + # Sometimes SHA1 is still permissible. That logic is contained + # within the various *_supported methods. + _fips_hashes = ( + hashes.SHA224, + hashes.SHA256, + hashes.SHA384, + hashes.SHA512, + hashes.SHA512_224, + hashes.SHA512_256, + hashes.SHA3_224, + hashes.SHA3_256, + hashes.SHA3_384, + hashes.SHA3_512, + hashes.SHAKE128, + hashes.SHAKE256, + ) + _fips_ecdh_curves = ( + ec.SECP224R1, + ec.SECP256R1, + ec.SECP384R1, + ec.SECP521R1, + ) + _fips_rsa_min_key_size = 2048 + _fips_rsa_min_public_exponent = 65537 + _fips_dsa_min_modulus = 1 << 2048 + _fips_dh_min_key_size = 2048 + _fips_dh_min_modulus = 1 << _fips_dh_min_key_size + + def __init__(self) -> None: + self._binding = binding.Binding() + self._ffi = self._binding.ffi + self._lib = self._binding.lib + self._fips_enabled = rust_openssl.is_fips_enabled() + + self._cipher_registry: dict[ + tuple[type[CipherAlgorithm], type[Mode]], + typing.Callable, + ] = {} + self._register_default_ciphers() + + def __repr__(self) -> str: + return "".format( + self.openssl_version_text(), + self._fips_enabled, + self._binding._legacy_provider_loaded, + ) + + def openssl_assert( + self, + ok: bool, + errors: list[rust_openssl.OpenSSLError] | None = None, + ) -> None: + return binding._openssl_assert(ok, errors=errors) + + def _enable_fips(self) -> None: + # This function enables FIPS mode for OpenSSL 3.0.0 on installs that + # have the FIPS provider installed properly. + self._binding._enable_fips() + assert rust_openssl.is_fips_enabled() + self._fips_enabled = rust_openssl.is_fips_enabled() + + def openssl_version_text(self) -> str: + """ + Friendly string name of the loaded OpenSSL library. This is not + necessarily the same version as it was compiled against. + + Example: OpenSSL 1.1.1d 10 Sep 2019 + """ + return self._ffi.string( + self._lib.OpenSSL_version(self._lib.OPENSSL_VERSION) + ).decode("ascii") + + def openssl_version_number(self) -> int: + return self._lib.OpenSSL_version_num() + + def _evp_md_from_algorithm(self, algorithm: hashes.HashAlgorithm): + if algorithm.name in ("blake2b", "blake2s"): + alg = f"{algorithm.name}{algorithm.digest_size * 8}".encode( + "ascii" + ) + else: + alg = algorithm.name.encode("ascii") + + evp_md = self._lib.EVP_get_digestbyname(alg) + return evp_md + + def _evp_md_non_null_from_algorithm(self, algorithm: hashes.HashAlgorithm): + evp_md = self._evp_md_from_algorithm(algorithm) + self.openssl_assert(evp_md != self._ffi.NULL) + return evp_md + + def hash_supported(self, algorithm: hashes.HashAlgorithm) -> bool: + if self._fips_enabled and not isinstance(algorithm, self._fips_hashes): + return False + + evp_md = self._evp_md_from_algorithm(algorithm) + return evp_md != self._ffi.NULL + + def signature_hash_supported( + self, algorithm: hashes.HashAlgorithm + ) -> bool: + # Dedicated check for hashing algorithm use in message digest for + # signatures, e.g. RSA PKCS#1 v1.5 SHA1 (sha1WithRSAEncryption). + if self._fips_enabled and isinstance(algorithm, hashes.SHA1): + return False + return self.hash_supported(algorithm) + + def scrypt_supported(self) -> bool: + if self._fips_enabled: + return False + else: + return self._lib.Cryptography_HAS_SCRYPT == 1 + + def hmac_supported(self, algorithm: hashes.HashAlgorithm) -> bool: + # FIPS mode still allows SHA1 for HMAC + if self._fips_enabled and isinstance(algorithm, hashes.SHA1): + return True + + return self.hash_supported(algorithm) + + def cipher_supported(self, cipher: CipherAlgorithm, mode: Mode) -> bool: + if self._fips_enabled: + # FIPS mode requires AES. TripleDES is disallowed/deprecated in + # FIPS 140-3. + if not isinstance(cipher, self._fips_ciphers): + return False + + try: + adapter = self._cipher_registry[type(cipher), type(mode)] + except KeyError: + return False + evp_cipher = adapter(self, cipher, mode) + return self._ffi.NULL != evp_cipher + + def register_cipher_adapter(self, cipher_cls, mode_cls, adapter) -> None: + if (cipher_cls, mode_cls) in self._cipher_registry: + raise ValueError( + f"Duplicate registration for: {cipher_cls} {mode_cls}." + ) + self._cipher_registry[cipher_cls, mode_cls] = adapter + + def _register_default_ciphers(self) -> None: + for cipher_cls in [AES, AES128, AES256]: + for mode_cls in [CBC, CTR, ECB, OFB, CFB, CFB8, GCM]: + self.register_cipher_adapter( + cipher_cls, + mode_cls, + GetCipherByName( + "{cipher.name}-{cipher.key_size}-{mode.name}" + ), + ) + for mode_cls in [CBC, CTR, ECB, OFB, CFB]: + self.register_cipher_adapter( + Camellia, + mode_cls, + GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}"), + ) + for mode_cls in [CBC, CFB, CFB8, OFB]: + self.register_cipher_adapter( + TripleDES, mode_cls, GetCipherByName("des-ede3-{mode.name}") + ) + self.register_cipher_adapter( + TripleDES, ECB, GetCipherByName("des-ede3") + ) + # ChaCha20 uses the Long Name "chacha20" in OpenSSL, but in LibreSSL + # it uses "chacha" + self.register_cipher_adapter( + ChaCha20, + type(None), + GetCipherByName( + "chacha" if self._lib.CRYPTOGRAPHY_IS_LIBRESSL else "chacha20" + ), + ) + self.register_cipher_adapter(AES, XTS, _get_xts_cipher) + for mode_cls in [ECB, CBC, OFB, CFB, CTR, GCM]: + self.register_cipher_adapter( + SM4, mode_cls, GetCipherByName("sm4-{mode.name}") + ) + # Don't register legacy ciphers if they're unavailable. Hypothetically + # this wouldn't be necessary because we test availability by seeing if + # we get an EVP_CIPHER * in the _CipherContext __init__, but OpenSSL 3 + # will return a valid pointer even though the cipher is unavailable. + if ( + self._binding._legacy_provider_loaded + or not self._lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER + ): + for mode_cls in [CBC, CFB, OFB, ECB]: + self.register_cipher_adapter( + _BlowfishInternal, + mode_cls, + GetCipherByName("bf-{mode.name}"), + ) + for mode_cls in [CBC, CFB, OFB, ECB]: + self.register_cipher_adapter( + _SEEDInternal, + mode_cls, + GetCipherByName("seed-{mode.name}"), + ) + for cipher_cls, mode_cls in itertools.product( + [_CAST5Internal, _IDEAInternal], + [CBC, OFB, CFB, ECB], + ): + self.register_cipher_adapter( + cipher_cls, + mode_cls, + GetCipherByName("{cipher.name}-{mode.name}"), + ) + self.register_cipher_adapter( + ARC4, type(None), GetCipherByName("rc4") + ) + # We don't actually support RC2, this is just used by some tests. + self.register_cipher_adapter( + _RC2, type(None), GetCipherByName("rc2") + ) + + def create_symmetric_encryption_ctx( + self, cipher: CipherAlgorithm, mode: Mode + ) -> _CipherContext: + return _CipherContext(self, cipher, mode, _CipherContext._ENCRYPT) + + def create_symmetric_decryption_ctx( + self, cipher: CipherAlgorithm, mode: Mode + ) -> _CipherContext: + return _CipherContext(self, cipher, mode, _CipherContext._DECRYPT) + + def pbkdf2_hmac_supported(self, algorithm: hashes.HashAlgorithm) -> bool: + return self.hmac_supported(algorithm) + + def _consume_errors(self) -> list[rust_openssl.OpenSSLError]: + return rust_openssl.capture_error_stack() + + def generate_rsa_parameters_supported( + self, public_exponent: int, key_size: int + ) -> bool: + return ( + public_exponent >= 3 + and public_exponent & 1 != 0 + and key_size >= 512 + ) + + def _bytes_to_bio(self, data: bytes) -> _MemoryBIO: + """ + Return a _MemoryBIO namedtuple of (BIO, char*). + + The char* is the storage for the BIO and it must stay alive until the + BIO is finished with. + """ + data_ptr = self._ffi.from_buffer(data) + bio = self._lib.BIO_new_mem_buf(data_ptr, len(data)) + self.openssl_assert(bio != self._ffi.NULL) + + return _MemoryBIO(self._ffi.gc(bio, self._lib.BIO_free), data_ptr) + + def _create_mem_bio_gc(self): + """ + Creates an empty memory BIO. + """ + bio_method = self._lib.BIO_s_mem() + self.openssl_assert(bio_method != self._ffi.NULL) + bio = self._lib.BIO_new(bio_method) + self.openssl_assert(bio != self._ffi.NULL) + bio = self._ffi.gc(bio, self._lib.BIO_free) + return bio + + def _read_mem_bio(self, bio) -> bytes: + """ + Reads a memory BIO. This only works on memory BIOs. + """ + buf = self._ffi.new("char **") + buf_len = self._lib.BIO_get_mem_data(bio, buf) + self.openssl_assert(buf_len > 0) + self.openssl_assert(buf[0] != self._ffi.NULL) + bio_data = self._ffi.buffer(buf[0], buf_len)[:] + return bio_data + + def _oaep_hash_supported(self, algorithm: hashes.HashAlgorithm) -> bool: + if self._fips_enabled and isinstance(algorithm, hashes.SHA1): + return False + + return isinstance( + algorithm, + ( + hashes.SHA1, + hashes.SHA224, + hashes.SHA256, + hashes.SHA384, + hashes.SHA512, + ), + ) + + def rsa_padding_supported(self, padding: AsymmetricPadding) -> bool: + if isinstance(padding, PKCS1v15): + return True + elif isinstance(padding, PSS) and isinstance(padding._mgf, MGF1): + # SHA1 is permissible in MGF1 in FIPS even when SHA1 is blocked + # as signature algorithm. + if self._fips_enabled and isinstance( + padding._mgf._algorithm, hashes.SHA1 + ): + return True + else: + return self.hash_supported(padding._mgf._algorithm) + elif isinstance(padding, OAEP) and isinstance(padding._mgf, MGF1): + return self._oaep_hash_supported( + padding._mgf._algorithm + ) and self._oaep_hash_supported(padding._algorithm) + else: + return False + + def rsa_encryption_supported(self, padding: AsymmetricPadding) -> bool: + if self._fips_enabled and isinstance(padding, PKCS1v15): + return False + else: + return self.rsa_padding_supported(padding) + + def dsa_supported(self) -> bool: + return ( + not self._lib.CRYPTOGRAPHY_IS_BORINGSSL and not self._fips_enabled + ) + + def dsa_hash_supported(self, algorithm: hashes.HashAlgorithm) -> bool: + if not self.dsa_supported(): + return False + return self.signature_hash_supported(algorithm) + + def cmac_algorithm_supported(self, algorithm) -> bool: + return self.cipher_supported( + algorithm, CBC(b"\x00" * algorithm.block_size) + ) + + def _cert2ossl(self, cert: x509.Certificate) -> typing.Any: + data = cert.public_bytes(serialization.Encoding.DER) + mem_bio = self._bytes_to_bio(data) + x509 = self._lib.d2i_X509_bio(mem_bio.bio, self._ffi.NULL) + self.openssl_assert(x509 != self._ffi.NULL) + x509 = self._ffi.gc(x509, self._lib.X509_free) + return x509 + + def _ossl2cert(self, x509_ptr: typing.Any) -> x509.Certificate: + bio = self._create_mem_bio_gc() + res = self._lib.i2d_X509_bio(bio, x509_ptr) + self.openssl_assert(res == 1) + return x509.load_der_x509_certificate(self._read_mem_bio(bio)) + + def _key2ossl(self, key: PKCS12PrivateKeyTypes) -> typing.Any: + data = key.private_bytes( + serialization.Encoding.DER, + serialization.PrivateFormat.PKCS8, + serialization.NoEncryption(), + ) + mem_bio = self._bytes_to_bio(data) + + evp_pkey = self._lib.d2i_PrivateKey_bio( + mem_bio.bio, + self._ffi.NULL, + ) + self.openssl_assert(evp_pkey != self._ffi.NULL) + return self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) + + def _handle_key_loading_error( + self, errors: list[rust_openssl.OpenSSLError] + ) -> typing.NoReturn: + if not errors: + raise ValueError( + "Could not deserialize key data. The data may be in an " + "incorrect format or it may be encrypted with an unsupported " + "algorithm." + ) + + elif ( + errors[0]._lib_reason_match( + self._lib.ERR_LIB_EVP, self._lib.EVP_R_BAD_DECRYPT + ) + or errors[0]._lib_reason_match( + self._lib.ERR_LIB_PKCS12, + self._lib.PKCS12_R_PKCS12_CIPHERFINAL_ERROR, + ) + or ( + self._lib.Cryptography_HAS_PROVIDERS + and errors[0]._lib_reason_match( + self._lib.ERR_LIB_PROV, + self._lib.PROV_R_BAD_DECRYPT, + ) + ) + ): + raise ValueError("Bad decrypt. Incorrect password?") + + elif any( + error._lib_reason_match( + self._lib.ERR_LIB_EVP, + self._lib.EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM, + ) + for error in errors + ): + raise ValueError("Unsupported public key algorithm.") + + else: + raise ValueError( + "Could not deserialize key data. The data may be in an " + "incorrect format, it may be encrypted with an unsupported " + "algorithm, or it may be an unsupported key type (e.g. EC " + "curves with explicit parameters).", + errors, + ) + + def elliptic_curve_supported(self, curve: ec.EllipticCurve) -> bool: + if self._fips_enabled and not isinstance( + curve, self._fips_ecdh_curves + ): + return False + + return rust_openssl.ec.curve_supported(curve) + + def elliptic_curve_signature_algorithm_supported( + self, + signature_algorithm: ec.EllipticCurveSignatureAlgorithm, + curve: ec.EllipticCurve, + ) -> bool: + # We only support ECDSA right now. + if not isinstance(signature_algorithm, ec.ECDSA): + return False + + return self.elliptic_curve_supported(curve) and ( + isinstance(signature_algorithm.algorithm, asym_utils.Prehashed) + or self.hash_supported(signature_algorithm.algorithm) + ) + + def elliptic_curve_exchange_algorithm_supported( + self, algorithm: ec.ECDH, curve: ec.EllipticCurve + ) -> bool: + return self.elliptic_curve_supported(curve) and isinstance( + algorithm, ec.ECDH + ) + + def dh_supported(self) -> bool: + return not self._lib.CRYPTOGRAPHY_IS_BORINGSSL + + def dh_x942_serialization_supported(self) -> bool: + return self._lib.Cryptography_HAS_EVP_PKEY_DHX == 1 + + def x25519_supported(self) -> bool: + # Beginning with OpenSSL 3.2.0, X25519 is considered FIPS. + if ( + self._fips_enabled + and not self._lib.CRYPTOGRAPHY_OPENSSL_320_OR_GREATER + ): + return False + return True + + def x448_supported(self) -> bool: + # Beginning with OpenSSL 3.2.0, X448 is considered FIPS. + if ( + self._fips_enabled + and not self._lib.CRYPTOGRAPHY_OPENSSL_320_OR_GREATER + ): + return False + return ( + not self._lib.CRYPTOGRAPHY_IS_LIBRESSL + and not self._lib.CRYPTOGRAPHY_IS_BORINGSSL + ) + + def ed25519_supported(self) -> bool: + if self._fips_enabled: + return False + return True + + def ed448_supported(self) -> bool: + if self._fips_enabled: + return False + return ( + not self._lib.CRYPTOGRAPHY_IS_LIBRESSL + and not self._lib.CRYPTOGRAPHY_IS_BORINGSSL + ) + + def aead_cipher_supported(self, cipher) -> bool: + return aead._aead_cipher_supported(self, cipher) + + def _zero_data(self, data, length: int) -> None: + # We clear things this way because at the moment we're not + # sure of a better way that can guarantee it overwrites the + # memory of a bytearray and doesn't just replace the underlying char *. + for i in range(length): + data[i] = 0 + + @contextlib.contextmanager + def _zeroed_null_terminated_buf(self, data): + """ + This method takes bytes, which can be a bytestring or a mutable + buffer like a bytearray, and yields a null-terminated version of that + data. This is required because PKCS12_parse doesn't take a length with + its password char * and ffi.from_buffer doesn't provide null + termination. So, to support zeroing the data via bytearray we + need to build this ridiculous construct that copies the memory, but + zeroes it after use. + """ + if data is None: + yield self._ffi.NULL + else: + data_len = len(data) + buf = self._ffi.new("char[]", data_len + 1) + self._ffi.memmove(buf, data, data_len) + try: + yield buf + finally: + # Cast to a uint8_t * so we can assign by integer + self._zero_data(self._ffi.cast("uint8_t *", buf), data_len) + + def load_key_and_certificates_from_pkcs12( + self, data: bytes, password: bytes | None + ) -> tuple[ + PrivateKeyTypes | None, + x509.Certificate | None, + list[x509.Certificate], + ]: + pkcs12 = self.load_pkcs12(data, password) + return ( + pkcs12.key, + pkcs12.cert.certificate if pkcs12.cert else None, + [cert.certificate for cert in pkcs12.additional_certs], + ) + + def load_pkcs12( + self, data: bytes, password: bytes | None + ) -> PKCS12KeyAndCertificates: + if password is not None: + utils._check_byteslike("password", password) + + bio = self._bytes_to_bio(data) + p12 = self._lib.d2i_PKCS12_bio(bio.bio, self._ffi.NULL) + if p12 == self._ffi.NULL: + self._consume_errors() + raise ValueError("Could not deserialize PKCS12 data") + + p12 = self._ffi.gc(p12, self._lib.PKCS12_free) + evp_pkey_ptr = self._ffi.new("EVP_PKEY **") + x509_ptr = self._ffi.new("X509 **") + sk_x509_ptr = self._ffi.new("Cryptography_STACK_OF_X509 **") + with self._zeroed_null_terminated_buf(password) as password_buf: + res = self._lib.PKCS12_parse( + p12, password_buf, evp_pkey_ptr, x509_ptr, sk_x509_ptr + ) + if res == 0: + self._consume_errors() + raise ValueError("Invalid password or PKCS12 data") + + cert = None + key = None + additional_certificates = [] + + if evp_pkey_ptr[0] != self._ffi.NULL: + evp_pkey = self._ffi.gc(evp_pkey_ptr[0], self._lib.EVP_PKEY_free) + # We don't support turning off RSA key validation when loading + # PKCS12 keys + key = rust_openssl.keys.private_key_from_ptr( + int(self._ffi.cast("uintptr_t", evp_pkey)), + unsafe_skip_rsa_key_validation=False, + ) + + if x509_ptr[0] != self._ffi.NULL: + x509 = self._ffi.gc(x509_ptr[0], self._lib.X509_free) + cert_obj = self._ossl2cert(x509) + name = None + maybe_name = self._lib.X509_alias_get0(x509, self._ffi.NULL) + if maybe_name != self._ffi.NULL: + name = self._ffi.string(maybe_name) + cert = PKCS12Certificate(cert_obj, name) + + if sk_x509_ptr[0] != self._ffi.NULL: + sk_x509 = self._ffi.gc(sk_x509_ptr[0], self._lib.sk_X509_free) + num = self._lib.sk_X509_num(sk_x509_ptr[0]) + + # In OpenSSL < 3.0.0 PKCS12 parsing reverses the order of the + # certificates. + indices: typing.Iterable[int] + if ( + self._lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER + or self._lib.CRYPTOGRAPHY_IS_BORINGSSL + ): + indices = range(num) + else: + indices = reversed(range(num)) + + for i in indices: + x509 = self._lib.sk_X509_value(sk_x509, i) + self.openssl_assert(x509 != self._ffi.NULL) + x509 = self._ffi.gc(x509, self._lib.X509_free) + addl_cert = self._ossl2cert(x509) + addl_name = None + maybe_name = self._lib.X509_alias_get0(x509, self._ffi.NULL) + if maybe_name != self._ffi.NULL: + addl_name = self._ffi.string(maybe_name) + additional_certificates.append( + PKCS12Certificate(addl_cert, addl_name) + ) + + return PKCS12KeyAndCertificates(key, cert, additional_certificates) + + def serialize_key_and_certificates_to_pkcs12( + self, + name: bytes | None, + key: PKCS12PrivateKeyTypes | None, + cert: x509.Certificate | None, + cas: list[_PKCS12CATypes] | None, + encryption_algorithm: serialization.KeySerializationEncryption, + ) -> bytes: + password = None + if name is not None: + utils._check_bytes("name", name) + + if isinstance(encryption_algorithm, serialization.NoEncryption): + nid_cert = -1 + nid_key = -1 + pkcs12_iter = 0 + mac_iter = 0 + mac_alg = self._ffi.NULL + elif isinstance( + encryption_algorithm, serialization.BestAvailableEncryption + ): + # PKCS12 encryption is hopeless trash and can never be fixed. + # OpenSSL 3 supports PBESv2, but Libre and Boring do not, so + # we use PBESv1 with 3DES on the older paths. + if self._lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER: + nid_cert = self._lib.NID_aes_256_cbc + nid_key = self._lib.NID_aes_256_cbc + else: + nid_cert = self._lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC + nid_key = self._lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC + # At least we can set this higher than OpenSSL's default + pkcs12_iter = 20000 + # mac_iter chosen for compatibility reasons, see: + # https://www.openssl.org/docs/man1.1.1/man3/PKCS12_create.html + # Did we mention how lousy PKCS12 encryption is? + mac_iter = 1 + # MAC algorithm can only be set on OpenSSL 3.0.0+ + mac_alg = self._ffi.NULL + password = encryption_algorithm.password + elif ( + isinstance( + encryption_algorithm, serialization._KeySerializationEncryption + ) + and encryption_algorithm._format + is serialization.PrivateFormat.PKCS12 + ): + # Default to OpenSSL's defaults. Behavior will vary based on the + # version of OpenSSL cryptography is compiled against. + nid_cert = 0 + nid_key = 0 + # Use the default iters we use in best available + pkcs12_iter = 20000 + # See the Best Available comment for why this is 1 + mac_iter = 1 + password = encryption_algorithm.password + keycertalg = encryption_algorithm._key_cert_algorithm + if keycertalg is PBES.PBESv1SHA1And3KeyTripleDESCBC: + nid_cert = self._lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC + nid_key = self._lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC + elif keycertalg is PBES.PBESv2SHA256AndAES256CBC: + if not self._lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER: + raise UnsupportedAlgorithm( + "PBESv2 is not supported by this version of OpenSSL" + ) + nid_cert = self._lib.NID_aes_256_cbc + nid_key = self._lib.NID_aes_256_cbc + else: + assert keycertalg is None + # We use OpenSSL's defaults + + if encryption_algorithm._hmac_hash is not None: + if not self._lib.Cryptography_HAS_PKCS12_SET_MAC: + raise UnsupportedAlgorithm( + "Setting MAC algorithm is not supported by this " + "version of OpenSSL." + ) + mac_alg = self._evp_md_non_null_from_algorithm( + encryption_algorithm._hmac_hash + ) + self.openssl_assert(mac_alg != self._ffi.NULL) + else: + mac_alg = self._ffi.NULL + + if encryption_algorithm._kdf_rounds is not None: + pkcs12_iter = encryption_algorithm._kdf_rounds + + else: + raise ValueError("Unsupported key encryption type") + + if cas is None or len(cas) == 0: + sk_x509 = self._ffi.NULL + else: + sk_x509 = self._lib.sk_X509_new_null() + sk_x509 = self._ffi.gc(sk_x509, self._lib.sk_X509_free) + + # This list is to keep the x509 values alive until end of function + ossl_cas = [] + for ca in cas: + if isinstance(ca, PKCS12Certificate): + ca_alias = ca.friendly_name + ossl_ca = self._cert2ossl(ca.certificate) + if ca_alias is None: + res = self._lib.X509_alias_set1( + ossl_ca, self._ffi.NULL, -1 + ) + else: + res = self._lib.X509_alias_set1( + ossl_ca, ca_alias, len(ca_alias) + ) + self.openssl_assert(res == 1) + else: + ossl_ca = self._cert2ossl(ca) + ossl_cas.append(ossl_ca) + res = self._lib.sk_X509_push(sk_x509, ossl_ca) + backend.openssl_assert(res >= 1) + + with self._zeroed_null_terminated_buf(password) as password_buf: + with self._zeroed_null_terminated_buf(name) as name_buf: + ossl_cert = self._cert2ossl(cert) if cert else self._ffi.NULL + ossl_pkey = ( + self._key2ossl(key) if key is not None else self._ffi.NULL + ) + + p12 = self._lib.PKCS12_create( + password_buf, + name_buf, + ossl_pkey, + ossl_cert, + sk_x509, + nid_key, + nid_cert, + pkcs12_iter, + mac_iter, + 0, + ) + + if ( + self._lib.Cryptography_HAS_PKCS12_SET_MAC + and mac_alg != self._ffi.NULL + ): + self._lib.PKCS12_set_mac( + p12, + password_buf, + -1, + self._ffi.NULL, + 0, + mac_iter, + mac_alg, + ) + + self.openssl_assert(p12 != self._ffi.NULL) + p12 = self._ffi.gc(p12, self._lib.PKCS12_free) + + bio = self._create_mem_bio_gc() + res = self._lib.i2d_PKCS12_bio(bio, p12) + self.openssl_assert(res > 0) + return self._read_mem_bio(bio) + + def poly1305_supported(self) -> bool: + if self._fips_enabled: + return False + elif ( + self._lib.CRYPTOGRAPHY_IS_BORINGSSL + or self._lib.CRYPTOGRAPHY_IS_LIBRESSL + ): + return True + else: + return self._lib.Cryptography_HAS_POLY1305 == 1 + + def pkcs7_supported(self) -> bool: + return not self._lib.CRYPTOGRAPHY_IS_BORINGSSL + + +class GetCipherByName: + def __init__(self, fmt: str): + self._fmt = fmt + + def __call__(self, backend: Backend, cipher: CipherAlgorithm, mode: Mode): + cipher_name = self._fmt.format(cipher=cipher, mode=mode).lower() + evp_cipher = backend._lib.EVP_get_cipherbyname( + cipher_name.encode("ascii") + ) + + # try EVP_CIPHER_fetch if present + if ( + evp_cipher == backend._ffi.NULL + and backend._lib.Cryptography_HAS_300_EVP_CIPHER + ): + evp_cipher = backend._lib.EVP_CIPHER_fetch( + backend._ffi.NULL, + cipher_name.encode("ascii"), + backend._ffi.NULL, + ) + + backend._consume_errors() + return evp_cipher + + +def _get_xts_cipher(backend: Backend, cipher: AES, mode): + cipher_name = f"aes-{cipher.key_size // 2}-xts" + return backend._lib.EVP_get_cipherbyname(cipher_name.encode("ascii")) + + +backend = Backend() diff --git a/.venv/Lib/site-packages/cryptography/hazmat/backends/openssl/ciphers.py b/.venv/Lib/site-packages/cryptography/hazmat/backends/openssl/ciphers.py new file mode 100644 index 00000000..3916b1a5 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/backends/openssl/ciphers.py @@ -0,0 +1,282 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import typing + +from cryptography.exceptions import InvalidTag, UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.primitives import ciphers +from cryptography.hazmat.primitives.ciphers import algorithms, modes + +if typing.TYPE_CHECKING: + from cryptography.hazmat.backends.openssl.backend import Backend + + +class _CipherContext: + _ENCRYPT = 1 + _DECRYPT = 0 + _MAX_CHUNK_SIZE = 2**29 + + def __init__(self, backend: Backend, cipher, mode, operation: int) -> None: + self._backend = backend + self._cipher = cipher + self._mode = mode + self._operation = operation + self._tag: bytes | None = None + + if isinstance(self._cipher, ciphers.BlockCipherAlgorithm): + self._block_size_bytes = self._cipher.block_size // 8 + else: + self._block_size_bytes = 1 + + ctx = self._backend._lib.EVP_CIPHER_CTX_new() + ctx = self._backend._ffi.gc( + ctx, self._backend._lib.EVP_CIPHER_CTX_free + ) + + registry = self._backend._cipher_registry + try: + adapter = registry[type(cipher), type(mode)] + except KeyError: + raise UnsupportedAlgorithm( + "cipher {} in {} mode is not supported " + "by this backend.".format( + cipher.name, mode.name if mode else mode + ), + _Reasons.UNSUPPORTED_CIPHER, + ) + + evp_cipher = adapter(self._backend, cipher, mode) + if evp_cipher == self._backend._ffi.NULL: + msg = f"cipher {cipher.name} " + if mode is not None: + msg += f"in {mode.name} mode " + msg += ( + "is not supported by this backend (Your version of OpenSSL " + "may be too old. Current version: {}.)" + ).format(self._backend.openssl_version_text()) + raise UnsupportedAlgorithm(msg, _Reasons.UNSUPPORTED_CIPHER) + + if isinstance(mode, modes.ModeWithInitializationVector): + iv_nonce = self._backend._ffi.from_buffer( + mode.initialization_vector + ) + elif isinstance(mode, modes.ModeWithTweak): + iv_nonce = self._backend._ffi.from_buffer(mode.tweak) + elif isinstance(mode, modes.ModeWithNonce): + iv_nonce = self._backend._ffi.from_buffer(mode.nonce) + elif isinstance(cipher, algorithms.ChaCha20): + iv_nonce = self._backend._ffi.from_buffer(cipher.nonce) + else: + iv_nonce = self._backend._ffi.NULL + # begin init with cipher and operation type + res = self._backend._lib.EVP_CipherInit_ex( + ctx, + evp_cipher, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + operation, + ) + self._backend.openssl_assert(res != 0) + # set the key length to handle variable key ciphers + res = self._backend._lib.EVP_CIPHER_CTX_set_key_length( + ctx, len(cipher.key) + ) + self._backend.openssl_assert(res != 0) + if isinstance(mode, modes.GCM): + res = self._backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, + self._backend._lib.EVP_CTRL_AEAD_SET_IVLEN, + len(iv_nonce), + self._backend._ffi.NULL, + ) + self._backend.openssl_assert(res != 0) + if mode.tag is not None: + res = self._backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, + self._backend._lib.EVP_CTRL_AEAD_SET_TAG, + len(mode.tag), + mode.tag, + ) + self._backend.openssl_assert(res != 0) + self._tag = mode.tag + + # pass key/iv + res = self._backend._lib.EVP_CipherInit_ex( + ctx, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + self._backend._ffi.from_buffer(cipher.key), + iv_nonce, + operation, + ) + + # Check for XTS mode duplicate keys error + errors = self._backend._consume_errors() + lib = self._backend._lib + if res == 0 and ( + ( + not lib.CRYPTOGRAPHY_IS_LIBRESSL + and errors[0]._lib_reason_match( + lib.ERR_LIB_EVP, lib.EVP_R_XTS_DUPLICATED_KEYS + ) + ) + or ( + lib.Cryptography_HAS_PROVIDERS + and errors[0]._lib_reason_match( + lib.ERR_LIB_PROV, lib.PROV_R_XTS_DUPLICATED_KEYS + ) + ) + ): + raise ValueError("In XTS mode duplicated keys are not allowed") + + self._backend.openssl_assert(res != 0, errors=errors) + + # We purposely disable padding here as it's handled higher up in the + # API. + self._backend._lib.EVP_CIPHER_CTX_set_padding(ctx, 0) + self._ctx = ctx + + def update(self, data: bytes) -> bytes: + buf = bytearray(len(data) + self._block_size_bytes - 1) + n = self.update_into(data, buf) + return bytes(buf[:n]) + + def update_into(self, data: bytes, buf: bytes) -> int: + total_data_len = len(data) + if len(buf) < (total_data_len + self._block_size_bytes - 1): + raise ValueError( + "buffer must be at least {} bytes for this payload".format( + len(data) + self._block_size_bytes - 1 + ) + ) + + data_processed = 0 + total_out = 0 + outlen = self._backend._ffi.new("int *") + baseoutbuf = self._backend._ffi.from_buffer(buf, require_writable=True) + baseinbuf = self._backend._ffi.from_buffer(data) + + while data_processed != total_data_len: + outbuf = baseoutbuf + total_out + inbuf = baseinbuf + data_processed + inlen = min(self._MAX_CHUNK_SIZE, total_data_len - data_processed) + + res = self._backend._lib.EVP_CipherUpdate( + self._ctx, outbuf, outlen, inbuf, inlen + ) + if res == 0 and isinstance(self._mode, modes.XTS): + self._backend._consume_errors() + raise ValueError( + "In XTS mode you must supply at least a full block in the " + "first update call. For AES this is 16 bytes." + ) + else: + self._backend.openssl_assert(res != 0) + data_processed += inlen + total_out += outlen[0] + + return total_out + + def finalize(self) -> bytes: + if ( + self._operation == self._DECRYPT + and isinstance(self._mode, modes.ModeWithAuthenticationTag) + and self.tag is None + ): + raise ValueError( + "Authentication tag must be provided when decrypting." + ) + + buf = self._backend._ffi.new("unsigned char[]", self._block_size_bytes) + outlen = self._backend._ffi.new("int *") + res = self._backend._lib.EVP_CipherFinal_ex(self._ctx, buf, outlen) + if res == 0: + errors = self._backend._consume_errors() + + if not errors and isinstance(self._mode, modes.GCM): + raise InvalidTag + + lib = self._backend._lib + self._backend.openssl_assert( + errors[0]._lib_reason_match( + lib.ERR_LIB_EVP, + lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH, + ) + or ( + lib.Cryptography_HAS_PROVIDERS + and errors[0]._lib_reason_match( + lib.ERR_LIB_PROV, + lib.PROV_R_WRONG_FINAL_BLOCK_LENGTH, + ) + ) + or ( + lib.CRYPTOGRAPHY_IS_BORINGSSL + and errors[0].reason + == lib.CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH + ), + errors=errors, + ) + raise ValueError( + "The length of the provided data is not a multiple of " + "the block length." + ) + + if ( + isinstance(self._mode, modes.GCM) + and self._operation == self._ENCRYPT + ): + tag_buf = self._backend._ffi.new( + "unsigned char[]", self._block_size_bytes + ) + res = self._backend._lib.EVP_CIPHER_CTX_ctrl( + self._ctx, + self._backend._lib.EVP_CTRL_AEAD_GET_TAG, + self._block_size_bytes, + tag_buf, + ) + self._backend.openssl_assert(res != 0) + self._tag = self._backend._ffi.buffer(tag_buf)[:] + + res = self._backend._lib.EVP_CIPHER_CTX_reset(self._ctx) + self._backend.openssl_assert(res == 1) + return self._backend._ffi.buffer(buf)[: outlen[0]] + + def finalize_with_tag(self, tag: bytes) -> bytes: + tag_len = len(tag) + if tag_len < self._mode._min_tag_length: + raise ValueError( + "Authentication tag must be {} bytes or longer.".format( + self._mode._min_tag_length + ) + ) + elif tag_len > self._block_size_bytes: + raise ValueError( + "Authentication tag cannot be more than {} bytes.".format( + self._block_size_bytes + ) + ) + res = self._backend._lib.EVP_CIPHER_CTX_ctrl( + self._ctx, self._backend._lib.EVP_CTRL_AEAD_SET_TAG, len(tag), tag + ) + self._backend.openssl_assert(res != 0) + self._tag = tag + return self.finalize() + + def authenticate_additional_data(self, data: bytes) -> None: + outlen = self._backend._ffi.new("int *") + res = self._backend._lib.EVP_CipherUpdate( + self._ctx, + self._backend._ffi.NULL, + outlen, + self._backend._ffi.from_buffer(data), + len(data), + ) + self._backend.openssl_assert(res != 0) + + @property + def tag(self) -> bytes | None: + return self._tag diff --git a/.venv/Lib/site-packages/cryptography/hazmat/backends/openssl/decode_asn1.py b/.venv/Lib/site-packages/cryptography/hazmat/backends/openssl/decode_asn1.py new file mode 100644 index 00000000..bf123b62 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -0,0 +1,32 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +from cryptography import x509 + +# CRLReason ::= ENUMERATED { +# unspecified (0), +# keyCompromise (1), +# cACompromise (2), +# affiliationChanged (3), +# superseded (4), +# cessationOfOperation (5), +# certificateHold (6), +# -- value 7 is not used +# removeFromCRL (8), +# privilegeWithdrawn (9), +# aACompromise (10) } +_CRL_ENTRY_REASON_ENUM_TO_CODE = { + x509.ReasonFlags.unspecified: 0, + x509.ReasonFlags.key_compromise: 1, + x509.ReasonFlags.ca_compromise: 2, + x509.ReasonFlags.affiliation_changed: 3, + x509.ReasonFlags.superseded: 4, + x509.ReasonFlags.cessation_of_operation: 5, + x509.ReasonFlags.certificate_hold: 6, + x509.ReasonFlags.remove_from_crl: 8, + x509.ReasonFlags.privilege_withdrawn: 9, + x509.ReasonFlags.aa_compromise: 10, +} diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/__init__.py b/.venv/Lib/site-packages/cryptography/hazmat/bindings/__init__.py new file mode 100644 index 00000000..b5093362 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/__init__.py @@ -0,0 +1,3 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/bindings/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..be334345649738ce4944000a5ba25faa71cbb080 GIT binary patch literal 209 zcmZ3^%ge<81i#(4rfvb!k3k$5V1zP0vjG{?8B!R688jLFRx%VZ0r{UnlD|@1tYVV$ zQ!?|?V?y)OLOc?avx{SbQgc&tlTwRPi<49Hl2c>!%2M;nVtg`_Vu~|MQgsV}iW1XP zi(`_DDho>T(~A-dGAi{m6033(OZ1a6^FXE*>&M4u=4F<|$LkeT{^GF7%}*)KNwq6t Z1zHMnRxv-2_`uA_$oPQ)Miemv#Q?T(Iu!r_ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust.pyd b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust.pyd new file mode 100644 index 0000000000000000000000000000000000000000..97e43779a7f67e99f38a020bd330e2838b47c517 GIT binary patch literal 7211520 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

TP$%98mp|@DxeN$-PCkpskw;p{WQn9KVm7Yx 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

L)QkYW{hKjEvz~24WYJl6Jci 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

{*$^X8#g>F^aT#K@Dj9Dgz!zW~RWOyojfnhG-L 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	%wpzxBLHFdgeW@lLPFl{n%2L_aqon7j-x
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

KC7_YE+UUD~O{GJP_W*lBQh-p1^yRwHM<-E(56 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Ⓢ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�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%0A}zq#%*kxDYv$L7H3 zVhPIUqp-#SY4SG0$eX(`FBYRl`19kuEjssC@wl*3-#1&96Ka@enUHZS~LIn3Fl>^0yyyJg@*HYpqd-vg;H zyL>+$naU(_XGqO^$OF_h~DbY0M$3#=BxfyP-l0SBa z6-+Fo1Y?hg&LEyb-x?h-obE0grZfyV4=HK$K!n$S6Xx=_JP=^z4gzFvE8 zr}B$oJ)u|VEoI-e{ky=*h*|5kZvhR$M5I)a++d0^9V=110(-kA`MO@18<*BR=zu=8O&*p_^&;}M$s`Ekq1XjqdD+`h9<=ca; zf@bR!aEAh>HQbgdtIC#3WOlpx6ht~vk<_B<=9N%NI-K9OJ8As3#*3v!ag;))j})k< zOO3)4iK9Zbqj6J8j5j`;cf92No6Y;#4)TtWyferPI<5SNjD;rmHCHoucK51J(0R+x z4UK*IIpUO;azjFl@WgA!hLa!4Pp2&Cp={OHWGO;~Q&P;Gwq(@#fPn2~de6k-Z*yR#OxGTg=FX%W+R}1v_4%WDiPqc3&ZDMM^@3RwSiD!2t5eKD7Rp%y z<$o-csRCt84-{3d=KL6xkW(w#i_qtE5sEW)+BYLOP?VbcZTC3T^X?1=j z2+$6F6qPD=8TULB)P9JWSixt)V@u*>5=Tnnkv4IpB%Ub8iSE7=sAl?8w*Oz!@>guj zAL7}}q(`>@SGtoQF)z^(bAru#rR4qC=Dkt!PPBP@r*?Mf%s_o5DjFul#Lwc%tjfdPsVA9T zaFcM*H|IXsrK}log2yBE0WP)N~PUzuJtHhR61E_c!VO_n#>~6 zijAChu^ttw)CBzP5&TB-MYF6NU^1gwn19VrelDuz!U0}=g7AGcoW;Av{u=Z13%+7M z;WwAx(frcr*#7+H^UK|0YgYUcTke__SL@%I`u8gRJ460@U7-Es$KNH@{w#CP|T!0`jkCtcmi6{2m28ikETz0=QGmBi9GXl2?C88+gV zl1=o0W;5d(5yj2sF5J?*u2~ID3-)3YdEjPsemF#3UwBH+88$y6MB})BWoo*m0U}dlg+RIBi!pY$cQf0A+iv8XvFZqwL~m#|`$@Cw zI@d|ZSe_8Daftc%*Mbl1=I7*+B_dAU&Iog?V9A*}GUT#=d3HaUHqTLY;zC(xns$UW zpBdt_vN=qJ`7ct@FT^z|rvD%>ud|=|^x!?@qMQ`T(IULKc}LO4z={R5!koDtK#gbS z^GwoW{_=ew-$m~}ijO@gKZSO#6pE0J?9fiDmw{?tsC5!A$I}cg)~&oAzS_fY*0%`{ zze9iDgI~25w^ z>F((xBkrArReX!M-aZJL?{t~3X<4)Rid;Q>1GmBU=oa>!4mN+w)5%l(6tyQG*b-z$qb)~|SyLOqefv1Z;y2t)xZ=IlOz1%uX~)J79rMw3i)ohJyg7Qfo# zQ7Q-#$M<|DSqazja^YB>oUJqfo9u3W@(BPfdt(d~KBi(ql{J95q;fB~Xu&pgI!_K! zT1yum7+7(kbl%MyEiHC)#`9x7BIs=VyIlEtk^P!(zfO{`>-Z`me+J-BD+@*QuakOX zQvQYn1f?2>o6JGS*k$#6Qe|uGNuZTswH?X(jHS++;$oaH!^gO{nK53u ziBhhjx-get(q-i`9{)oNRIM2lD-lklsXB^cYicte{={a{LmN6g6c*s7=_vcu8wu$%=HhHu*2m0C@)j8C({VLw#f9kWcs=?lZ*%V zHuR;Vr8}_^%&22KpVH|_hI;m#y%OyPdx6Ed;N*`dev@2TO5^Mn_m^9?i3>-enAMfX z@b_KyD)hE^t{DZK@no%WXQ4D*yrS=WMX@A(6fE`P$etM)E}x4! z&>9(mko+kX3G{$qUYL<*!8ecaXSFqH@G_R?Dx02fKI~6sHZ=A@?*3&7nuhU@Rnt7lh=G3*A|}d{NqbE7On2&R_niLb+{dxZ zZ&oH}CfLuczI+er)_R!PMXEEt(gRk5EV%-1xSu)qVNq@H%zMxRfBO?u)7zzgZq64x zn@9hYQe)@4lYeD)Qd?&w@a-y<&@DiZI(Yg2tlU&mSxw!d<4nW?a|PI47TBW#?ED^J z*SM2^Z=MifB6B6;ZU_0yro+=A%5@?Km@YP$$8MFm9P$(sUgeoWQnSpfwK6wr%8BOJ z1?j{$dqgpFh}8ExTiE|)#3R~|JA5*WG7eU%fJezB6z3g_} zBG>G_Lbnse-0cPckz`0_8EP1*G>U#9+A_hI#1ccTc5sqJU=qJc+fcEucL;pc?v7go zCCz5*ktuenlP|E-87q~YgaTnFiT0Nywry!v^sLottK|}C|y|@p- z3*!ixa~%`}FQkwEoW}phtPLs7loLO@h5n}t{m&!9j=6p*h8KqWc$4|Cj_ZPdg5NdL zOE>4|Je$GbUB)%qe`Q>%zZiUX$^i(WnbT(Om5q*gcj-;cWsO=aZw$pKeV&v)8^eI< zJi=qLEoR8|!emNMDka7R5tHD6O_=c!a;j%FVXC9K>OQ-c^h zXR3kz=x=t~^I`<&aDCyeDp#-1_0CW-D3;>v66557f4Dhwa`xskw-n z33InVFiy?$rDlmGWoDzS;rAFX$pkt7{DYRhR7!tsOP?&IKL@I9H%5ac=2R)YSiVcB z1AHe#&b(}Aq-iLWW2M@eE;1ygO7l(R2+J&T>h8o*^SV(KWxWn+EK_r2Jq6$VwN2*8R#U9=bhFumW+n^$ zI}7Wi-7xpn%ayr1c=edO?|q9`^WqtL!R@h+ChC%WY$Js2OY=tQR%?U?<_S$jdLr_sAP#U)&#faVG+cXI?Lad>=B zvNE41{3lCB#|~J$heB0z26BEsxu&e7r1A^j%3Y)7#OpvdKEl2rrWbt2IHQ#J!0^Lp zORJg236PYzMkIz1%-Ulmjl3PEmd{ZMiB=|fu4ty@0h9D*GMN-gOc-6us*!HqfrWsS zR9|kIZych9>#cKr;~3SQzTDFMoxc5pRc7Wh((@MJJRQKp8B1QO#Qwo0T44X^13mel zG=}^Ux29dN_`%WMtNx}E~i25)RUg>PqY;2=>E}?o)RIm6dYm;Cr`k4Z=*Sm zlRE4H*%0l~av`lD&nsyO#aLxkym~L{d+2_}OzJbYKi6mem?k6wEmiAb2YG>SJoi&x zO6BEA!4)sCj(3WUm+|tF(&5I+izsoDE#C~2r})~L`)X^f=Qs%PRADI!?ut5EX}*0n zMc2Be4cv*1MddzTnP?lZ;?t zkJi-j_5tMH9h&e$Hu<>8tFcBN_}4GO)uX6+ZeHH|2(4+U32Cco;mjUWym;~dMpNP*ZK2sK|woaK)r5U1AYU^0QYJ>SMU62Ls5`GDmF-wN|NI}}-wRI$2vPLw2H?RFv zq5MXnxv^#d)1rhiaq}J`S%je^dn{CLX%UJ`krpO3{Hv(O_2P)+{fc5eW%e&Coaa&F zl2no417@c!p)$tJySQ(OaluDyCDCO)1?o(_Eg&OB%Z}|^VE&)01q8_y z=-0QvxZn=2hP0jnx#lto^fo&<(t|m+CrgPL^;bb>%}8MC1S(vISZ`6}1WP@jKGQ*1D+kX|hE1FS2}vA@+>YsWjxTE{~NXc*t}Y)-mgXRVd8iNXBb-`xIy zdJ;_B$F!;IL*0+@tZF-+@pxf(nOl0E8xq&4f4m30PhP+RW7m8?fzFasbD5Cy$#fI6 zMW)vz({0P;x@no0#>04AAg8C6d)~YiD?Css#!Fc~1TZ`WM)E(O|H!ti(@us3Yq_c@ zYYN>U(H?i|%ftU?`Ez>8=e_$M%BSq1nW?^VUFZ7P;U?BP2-BNv*3h3Xr8J81GxS^7 zMI;FZP};1&J&SK1tbJ|y(-w1dZh+<*yT*(GVybZOrn9&I)w{`jt5;Mw_$$lAX44qd z&#mT>7g9Ey$~opd6jNtw{hrZ_KVm*yw0KQ2xhSn*t0}q{HBj!&#=>e@ltlGyj?rwWC8$AeX}pCBZKl1~G+0q{`i&IgPd z2MTjT6QWyUIc5?&FX6^ut{?{WCU$xlka(r#9j3KkAho~utoU$5@DRkltjSX)xsl|6 z8i+{W`L@Y+Td$4K-G64f<(Q~Y#Aihf}_keoVcaG8z{GOm%_-I#j~078#`D-7_82- z)ryAGXp1SLAkba}TID$N6I=Q&DZSg4K3+ijhAzxh;&FT7Z`E44WE%My=Z4$m z8~&A_e3y(b_zOnm*u)u)!Mnd)74OcNf3)w#{xkf+yDJN-7WR9s@{oArcOmzJ4Ds_2 zWps^s61}>CxZm(zVR2n;@GopW*ZdxUL=~&KM|z~hayB8sprk1ei`6j17<=OQKxxqf zPe|0uUBY_f1y1Lgs4amNM@XC9yfNEEm|=fi2IVydWyhKE<@}=3r?5@sN*V8SSNAZ$ zms^Daju+B+ic*rhjO$1UJkt3Y-pIw&((@UyTqRi5K~50;0?SlKwn~l9}Hj+fizHEI@ny)&OGD2(t=Ucfc zmne^Ln0tqsYwgtnH`ZCss(Dfl;>TU(^MAYrr=}}q<}BgaICu35WptGx=Iy)1S!TXo zc_33#N#`ZpgrnySTFgTX7viL<xnduW3-82NL$D!=_j&zP{Cy?t+yh?80ig8wPOOp05VwGp*{>Q;6Te zgSYkK<~`?SKUTB*YHrGc7~&1tazS4X*@aDfHFsqT?3~|{85zNH6W0IWy8fU}jaivd zr!v1Mv&@XNNlGqF^~86_5u|>(aGOnky5XZNSwgq5!j@&Mg|uW8)1bP{h3LSqfu{{ONy1^-1mv%nHj5^&9qJbWHUF@s=jzLCD z#)efbM1)j}`U0Mh^;Q3aClQYgfs)~vpT6PMGe51aDoLySLUf{5DVZnxho_`I*C*?$ zCZtt<>07yTv~T5((ec&&0xPysWyWey^w7pJX-*T$;vb$Ag|b^IDxcQr%}lsEH<>Y* z(wH^?%;B51;yO#OKLUTp=wuV4R5J16*zk$R#yA*60HC~G)F9LRMW4vJWwRQyg>Ls`(-9aw7^~242jPI(h68C(-uUKDf?-bR; z_hRs$FNp)mjDq@?(n|UD*K>$am7EfDsf9gNV9N^LFEFzNOz60!ve&h>wg=#DBNDQa%6OWO*TH8!SmG!Nf%fDBg>~>k?>}j+3 zTg6ExWe*(ueAQcFjVRX1;b!PHsPpI*A-yykRB^Zih|E){M@*1r^|h)OR%g&|VXJ*K zviAry-XlK`BS*skI(KQh$j|>T{7u+ol?EKM4`#y~O?~CvKy(FS^P&c94=2}0{LQnK zf0)ze{Hv@wSTRz%jID<(G6SV` zz}KwBm~2t3Tpq$8NL<~(4oNiDcgLUrHrc0AIHN&`nN- zK6T8kVzTxtD)?UtuVgxq1$ciTQ1}@s{Hzqdio%I{n)h07FjM6uxVv{JFOLb5cIXmY*u+FQoj+ zD?yInn-(JZ-O2xB9#beiO&A9VF-v&vwmQq2|4vu-z>UG zOjNSR<6Hi^Xnm-Bo)HS$)PqO%@mG&H8-2?MR_$Ii_r$O>i3lPu4h{wCI|l`PD?do{ z-S!}(L0TqhCX=*|v^hDP3P?1k^nLh$V1VMjJ7$noK%C)aAE4QNx5=6!l{V0VxHRZ{ zbsJ!ar&8v7RmxvfqK5bsOPJ# z2HxKJvRVev&^bCX=?5Bmd*>he0PI$o0% z$SPTor1V=IueoRU#huqhRv_9%U4f*!m>`1Rf9zl4nHiI6CWd4MvRzgn3<@idN!g^1 z3dss&b;1>%%q4V_FzCp>wp80*j*i&SP5FX}&mL4v$lkzCaaD8bOVVQpSS@4_H_#^Q z0;&bEEiPRx4RI_)taZ!>3{%%=vwgW3v}D!58WGY}b*ZF(Y{Y-iXPm9FpU3seSvMVs zBjuh@hHNJ+SP!S?z9+Lr>_~zl#`k3UZvP_N7Iz@+H8 z+e@t1e6gloip*(Dd?@3R`X@-v_U!ZJ4|r1S8}UGP^RA@@Cc$35;QDsOK;Ff+Rpw1i zj?E$4&%C61n-n2wl9%+fO`2f-xj-fUPf1_-xs)Qk~(~3w1+i-}9!}puXi)XDaX4t_6!fN1rGpC9TZvcjIYI zZ#&KN&tgnKyTHz%D^ivwYs)o~9-b*eW6dQQv7s}T_SKimO2&ykzGJj(#Z>__StkxM zA-(!g!@HE44bNC3MRgEmJn)+8Ijb;jq`fLE`_ed`_KC-YydD&-_-E94(@O0INSx_i ztwt<7`>Q2kKDkau+^tbv?SRyGtV(uadPeZ%dJYAO$q8Mb!q}1WW5`G?WKCL ziZA{Ec(X|0P7aHOeXRguZ6$qn{Vf#HA#$AF&80jxA%}WJf;YyiXXt01?>Gz#|!`zPp*9eXou{pO`yD zu#GY?qfDgr2!XEYN*j`1bApQN#zd=c`Od0uPOdz^WNLclIV=+-Y7mAkwm%A;DI=rK zHWojD6?Q@?rAa51R_$Fh7cX|~PC%bknTG;BToaM{nwUAu8l&D&a2yzYBbHn0d$ob9 z0DLu{F;rNpq7K&;6Aq)r-2D6?D&4^zaV#4vZDC*ucLgmuN!QTVi9}zIF)mOtL>9nl zoJa81$E%a|RVTAP_O1MCbf~B;M1(e#02zZqk|~|-@%@xpFn1Dv>~9|5iLD!rWr$qz zmS4R-HeT6{$)cJM!dsk@cW+8(6r=7Hh3SDMk<6szuU=pIky4>rAF-fH=*1-hY{^NT z#Vp(UvJ9*kTr#*{=c%Nd-Sbq|eYhG~_mNdB_tqop(r-!0x*6`|C(XIH;%axiX|}na zm)zWGA?kg*<}91*1j*H9bCpZ3^Lld4bSMAWJWk^k6KY|Rz9Z(3B%`2Zsi0-W z2w}N~%uJGe=1mR(dAa@{(!K;fsv`M+azQxa3qmyF!7K)efEb8EARsf4zzYOHkwZm5 zgDi>%$_zy12uvc3k3m$tb#+&F#ns)#iw!{~AxHvIE)_v^1<#JNDqb;wI{)vt`n{P+ zz}?^P_vgc8-t_CPuCA`GuCA`GPCzbiX<=l<5!FU@I_x zpKn@IAP?M;z_Z2;s?D`n=i&RJi-~Q6Y7)l5@0(DPr^!KC1>zL*~P3$RknZ17Tz8RY#K9YC!9=yp?}t zkx)h@GOH25lJgiR&Db6+4GYg2;==)v0aFjWp7*L}X3FMSSCVE9B--)i0+vuSx&u*KGJOce$ajjFkA1JST)c*c{}bCVf=qxhpBIlK2M9a|;&5!C|2SCf=QWu6 z02cK0j_N_2?KguP*RlI8YahQP{hJ%$mKWS836=%>nw|dpOi(nqQ4%am96}`jI1NV< zEKB@8B>jt{R6aIJf@RS)NW<@@^GkwdWk%E6>U2r4tjcJ;(|^KgkKjg0u&lMw^yMcD zK9XQr)zNgL4NNk@jgnwl_0jaUr%HZFu&iCt^pBBWM>h+SN z-_8v=vIIw(Cp3V{IH5+}_D9sDhD(B+q%_L^&bq<?34{faVXR|ISV?)A==j zAYD&)4QjSd*ZhHW9sQ+2&1fP!1cV*fi2XzWjmqmJcnUi(y~a+Tf%O#fS37t{S0-7hPeOTEv zsJYlIMVjvSY9CyI8q~^Z?Bam#a~%0$TB%8IU|$-ARdfx&7w2R8g)|TmKW{c03sF9J z8y`BT{`k(_KiE%N#>a^t+kUk7E~zgt)JF)u*#LVs ztNFty%uk`TQ~7);tc`f?z~={G_cN`uwtT({3i^(N{Xin{L5bTv3&Id_QdQ-0Mq=L zKd$VLdlS1D%b#QKhB7MdtB+VKtNPqD5b?0LM-G`*U@hAl&o6oaw@8tp(juk$xKhBW z6&x7=ElSByZ;^8FxKir46d5!vN(tMyND*PtB1ObRixfRy#Ep!Ao+;u}WZ<7p!O$0Ox(iGSQwLZNL0~gn5Fg;LMhpD4<_!*b>pkcnpW(NyUhd(m z+qR(TU~`C>t=#6q6%AYcr-J8a|C8!4DHv0Su*>7~0QS>*^o9r^PhcB`LoGs%$N(zk zi*7b#0No0u6(FwyNYP{aoB%fEh?Z9m+^I(r8ZrWv4b+vn39|t(?eTgBtJCAP9bc`h z)eWJZ{Bn@vwK`po*$@nqqK@KxYNZ>DsxGi=5Nbh$hcfoSYl5b^9FS~12&t}SO^}L0 zv~@_aiS{^O7R1$MvabAna5t@^2qy?ppDQUW^h`U#(CvdPK@$g~_RCm%C~YWV zE5Np!IEdBiCZ5ArZ*7h>arX-Lb}Adzct46r9UA_mkidU-fAZZhyH960rS`)csx!}zgRmW5!D8VQi`(oMuvjSL$jfAF#6v-1tKPBo ztN8Uw2M6eP0Gfi68(4n;K*$`gR)?Z%m0Yh79xopi=!lO)-nRo;WCZg$tXd5vZzZi| zC^FkdXf8veGZWV*QMb}4>&Sx{yu=i~a`sn(mv~zJ9^dMBUW?y#-fWUj(g4gIzj#0m zW}P=P{(X9@_s;nFVVQ71v2_XD!>Zx%2lrau`jcN>V2rFr5WZ}9w52(#N*NC3L(ork zz4BYy7A2{HT}9qkW68Ksy9Zu|%oms&p@c(?MclN2o!)kB~};iY|f^o#){q4OR>vk7yhp z5avJO_vBKcX$$a*rr@e&^Kd!Lb zYxCo!x|Uo(4ox@{?Y)F`Ol2MaBYrIW5B#`yvePbgWr_0`-^6!Iq>1bQjwb$2H*pW1 z)rUZ;MHBmg{_#!3{AHALWZ84rV~cb)JxM}jblYRYhrWCAJ2aw*%nNTZKfsB8I zq6=lbAgR|fwJ%eHcchxZ{H77^RBp+RK{S?(Rg&d;X6c}_WCri(f-DK5uF$PV`*CE< zL{3VzPXmAy6VoEA`A6#)O$!A}Z{-Al1pK}zg(0v63{2KeLCNgeIuDg{XQH+tcw`rA zawR)Y{X>H>t(0qT$26ad+vdPmxe?gz^LUvo!hdko6k12H%azS}iPx*+goFu6!jmJ7 z1CwFT1gicloQU8=l$Yo0;>A7mG_qsk8Z%Ly2Ztd4Et{>_h=;qenc!Sl8>rspY;}1f zJGs||V4(=Z1}w4y&56cxMpVazEK7Q-AFh@TzUpu2;9?>YN*jb{_4768;Jc8}xDa`< z4b%^i;15XTJ#ww_0HotO^S-|Jywu#ND27oQmyF>I2QNLYK~Y-p9s7MN2vVe+a)Ka? z@*tmJa{h5|vey($C70D4OagMg9st7%4o}vQKE>PICOD!E2o2d3TB5w6A&bLLCp9z8 zW2~=>Y|UCy^G(~~E0TL-BLe%xUpB4-j(kmU9}w1MXctauRo<6Xbnj1%p&^}WB8gTV zu6jvo&WAJE;!!62tIXnjMc%Gp3qu(zo}>T4TPhXT$%RI_y_L(EUQ&-&H{um#zUos( zCoUe8Hp&^f1X(#xmAhk)3Kc2xA7C5&W(*G7{U!R*mobLKU+Fyc#I9n0`yg%{)Jz>+VqVN(dqc1G$}BzFoY z;u04Q1M&-uKDrl3{KltYwo#W)7uMYTSFq+pz7D1R0nh5{8DPx-62jN33w0i*S6!p? z+|E2hnP(aEj8vU;9;R3Mb)HGga~kuI1>yPi)ikM#=~a*GJpGyHN0hCag9JVArl|sq zmuMHvg}19@&PYLKc0t7wxKv&q&4507MrZi+S)E}fGO(XJc4nAF+yFXH*ZcwASB=s& zSK?XS!J6s&<TKrpF(@ z)%wEZN)KM*Jd-^KCGsd@4x&jGfM?u1&W&%m2W1N5XTaQrLmKMaH;+cjt8Z(&aTW@P zJ7SPbY2zEZ(MM2!zDnqL5nJ;m63}N~u0?D9hE}2>5(hI)MbI{`1*Srm3~cdCuVn}e zK!v4vb3sAnG%N*wc*WbOg2sXUi(fSmp2qHufpazNoOBYlgsC`g$PnsZo9b zVFqr`bQ$I6;!$*<$LuTGHuKDFrC?jkASQ@A^2?dWaLO*wJkD5Ej~7E>>{_z;O0{*W zG;bK1R8=hn(mJqtJJ4)2uj&h=VY??yorxB5?SL_7gSK>SqCv5D!tFpiFC0CY+OpO={;#s%_-y zXy>M#jGfJAxzr?NZ5)JTd%oQ27uu7Wm>C=E&N$|56EfbA+|@iDm8n1Ie7Ijw+=;%0 z=4`AoDR|j8!$bmig@iE5bMaiZuy@2|tjxwEk3ft52hMX#v;g=8GDuJk|1faS1*#uv z1%-NmF6+B8{sOj~>~L=LakBu_%c6w7P-+?x9s*0(SF_5162gL)<(K(SW{l6%kzSB@ zN5lwq!V`{s;DX9u79J!N?AMg1F0Nl+))8W8C)qR)Qf|6WO8ZWZqS@AhJ;G+R-Vu5p|+sQUjH+C-HXdxyp>{%!@eX^ z*vB{EA`;%*DvK41=cZuSucAgEHBjO{W?H(j z#YvyR+>i+eqd8r;4 zHr3b3TJ|Z@YE)Y}9t3sKu?)n{{>JppJ5O9+r&jgd&H7SVA7Oi9^(FecXdKp3e7TJK ztBK!~Nwsx&A4WzJ}?vA3;x|LYpxRF~ueTz^O zF`K>CK16KhmD;Nf*`(=;HTNmrrlq8HqOT*K2*28&DBYvC=^b$&wQpW_0(hSP1kZh9 zc$ywQ6Ppz`B03sixXD0^Bw%P<0T=9{+%<#rVc@r64qX zsp>TTXUMnGQy4z4L47igYCyeu?oy`uIyi)HbuQh(C+j!x83KHq#!a`RXECQwT-(Nf ziC)V}<FO*BNm+4UnW<|Y`5+vX;o-=#Dd0rgn;4mk#>m8MJVk_JgX}wLO;A036Q{{(W}*S zlgJk+r-fS!=LrzqwhzVP4Rp{*+MX($hUtNYsIP2$FVlKJ@h4RLv((%!3{K|Ds60z@ zz>phf#x6{_^@KC~?&oGi$J>$%cIY64BP`48nT7u&t5npfUC%6&zA9>8X_)Pkp z;l79bqY*}9a^pv&R^5x2`TG`rf_9;KEvudaCvFZ+0tXhW1lV@sDQ;k1G@cB8J^}q2ZjgdrL|bPkt1(jAH;Q44 zI)_Fiwni31cLi28?B=sEeEZ;8Vtqq{1HD=_3^DQ3B}wxao6rh-#v|48wLqi6xaixU zFIn1qL0aGpHTib(cZubH82MxE)k7I_*a}cKX(Bib-bxq)qID0&c7e6otLFxh-O0Y; zO`8*Z?Qm)uS5V`UU~6*^j~nVU|M=Tff<&%b%EdO75I?Tkrp=httfimgIje1xgdk3V z6E98k4!$$zIQ;{@^tTHkPKez-qupxY$`D#eZ=xv+l7QHMHF zDHP6VgGhJCG5{*agXL#Y!m96YlW2TUFgA<@9!sHGt_Ge)Aq5E9UCC7a7(XxlM*9b| z{Tb96w$t@ z{U;e7$CCG{=^LWM?&+>FEo4-lNwiz?6?l4wdJ5_20XTB(R1fNBYzaSjShDX>?_f(3 zNcLpb)E+X`$SR`+gEmgXdMGNX;)i6E=k#3H!^LUFp5eQrT0>9rW&VuHo~W_b625^w z<)>YNgKoR;3B)sTf@%F*pURkVoiyEAIvz9yr&Fw00u*W%3nrj{@(^AM&R{08sOf9j zMx*?*Hkf2(L{KyLK?qy&KJtt+Qd$Fml??V@#tCNdMD@Vifc7oKANZ#@BpxqZ>ws;h zHgM75Z@*OB%v^B8W$HOyNPU0XfTVg}=Zt~lsF^4fd})`ExFIxYidt-vvRv31YTktBf)@1WTz^PduI&tXZq~cuq>CGK)mWf2nn|A%~1}< zzL{E7r2DZ0uvJ@TkYNro;9O`IrcIK{8`NY;D~$sSms7T_t$OTTgrhqQCJesx4sxr7 z<2t%*T7qT5zkv=g!SZ~9x(I*^;eUux4Q5za5PXR;t6)&h;%t%+9_I-KL6KwdCS8n` zEl+Tn2{ngOy&dX<7Bg$2Kum8}A z-w58v`2a1}J(Q|mc>TY^yHxcdyr@r~|36oMh5DsHvWwKifITidS$@L{l&bJvZ&ts) zWDD5$)QAij;@J4UPs_{(ji*~Zj1@ItLCQ3!x4N;vMG@)`4}v&J;f{_i%^MTdEgF|p z^4f`Tafad}_E7Zd{OP}ypY=bk=k~af=RoPsV#sl9gis*!x1c!r5e!%IH|YHC-^ve| z!pZ^Uvsw8Q^kZ@8!hV1MHL{w#4EabPB+FrSV6Z%@dF?TWHxIp>9A~2oVTvkusCx7% zSOorxJJj=b_5x%_2mvH7_HKZrfQ86MH9aHu0T@a`W8H-zZwIv_8B;#;ToH&|>dOs8 zCi=PuB9ncc0+B2HeI1dV2*a=QoZt$B-Ko;JTsR8sAcE;j*u6nLKip~7%6?$?Xb!ti zelZ-uD>k42XDa;1eG6~$iZB8$vu7XsoC4+;*$2fHY;*q@Tk&ujQ`3>4uD~2o97;KG zKjhFNRuf8l2G8o6A}IcU06E2gLq2zor8tIxvH&jxbL(;bBceER$LM{;JwRPE{legU5j-f zCTI@hwQhfh8r4Q$EfH^+@J!VE@#VTk;Woqs3XLDgQ(n`&WX=kbkV7I3HfB%6N6kD3 zvpkN%ndBn${CG~*h!_MOz*d@vxTvcUcb)q=`gSzR)bEi@1`H9P@-m_<<{nJCW~emX zj~UlceI!`BvFbBqm4L38rTPa3xfWwx>V<4d4^GMqC&4^gFsR>REbEyj6H15OOFv#x z#_n019!{y^BeEi(Ecx$hNH_mfz{etIdv96f^wsAdk%mRmdIV+VQimvDsq+l7aH$i9 zKtx?c-cmV#qx69(a+mVAX#>q>1N90oLY~rZR~i*TAtP*8zt*)XQ0Oq+4>Jl&_tsdbQ;~2)) zPh0z=cu+{Kn=V`g{{m-qiM`-TyuoA(Le%JB{HvZoO3~~1<8qC6CF`}{pAo_z{sp*6 z2<|sHM76#>jso?>`J%ETgBP?ZGM?ITYnrisG>;JD;Ln%gj%B#dj%S985#5g2%Z~K+ zCly6DBMNqUZZ&?1m%<*15E#cI_1MqgtrFQJAimxFRx<{PoPp0W*PGpeUj9B~!dd4Lah|A={5gkDv9^q~*EQW2u?!@pXgUD-T9G=R6`#<dDmjOa> zKI(8c+&c(&5dg|=Jcf009DOysSq?lLAO^S|xYFeGdl8$Zn;mZ?9v)<1M~UAL6kmS=XY008;aO_o8d}?cKADh!p!Q$ zP6d13!#Kne4G*Ib*RgYp8PUhF<)TKsrAHT-_ayJ8G)PnLtFHl-@EH{2DcF>?-GRq= zH+7e{oA8$Rid;As*x^V?JA8$vcUPBVvOo}BFE1r~OU=QoS76m4#4+ZP*E!n*+*Y~5 zC5)xQ4pqfxq<-(o%SXJHh|~PqNL^Vz=#9d~xUyW%f$9iuD`3y?R^n_0YR$NBH4W`M zu$rpDtxQ%eH`u0d_@LXRrD!$JZgKbs9pX9*kJM_fx7XzBrV0hIQh{q-vF)#y3;1dl zFMQ&4qM?kl@!MN@Bd}ECC6(6klOz#m8DPIhBD@#yi1enri5%un=9FbA*2g)_R-o%D z<`H#kKf=Sp>jDjeJOvwkgJMRvGURiOzdv13!t}9d-VL? z@$izJ`a|Ad;;MgCaOP3KxcW~;{n7j~DC0_WLWvXL+lKJj^pN*hT<&pq$@pmrpY1z7 zKbmy0)1(XW<0j`vw!ArsEgvUoi7t3&Fhe({-R#fASE9?`Nh1)4uqyY6)O~Fgq^_t| zp|sQRtX5*i!-S5*emKTgr9OnZVOk^7(I0=sYkf6B#&dWSrHA{nZly3JWX46;i9DXH zc_QZuoBv=Zz`5y5(sQ?|si%UGFec$~BTz4kL7mtV>b)8&rV9_r#`vv#bk286Qq&%X zpaB#FZtZX82DR0Tmune_(_tAGg~;Ru9AOj}YVX6`V$$p0dytBGwE%}Yt*OSPvQCiiqORnomkCvw5zi4 z##ldrhs4qPiWE#b@Q6t?DrEN@O?ru-WSwhNyvW*zx{>Vy7 z&$I>%Uv<$iq*J!Qwc%vs!RtHly6Q4yMV@Dvrz`W^fIPx>Fdke7*7R1cmMj_N$ijG! zFHfVyB8d<;3br9N;_RbjI^hY-haw%PfKeoH0qoUJ4VCITvbw8?<=yOolW{GdJsnj? zwlewxL|yeQFSXz5k%{!p(f&8PFGG z_lKi()v;f=hVRZfxclGr0HCJ~{5Z}gaP$|)06bZ+AszmN`T*)fk#^zIuggd{I;9l@joH5BRI%IO-~T7k9`i}1ZyK-D=0zkuHPU*l@|_s}%E z`CW0*dtWZHWCLu~QMMo6187}0Z{!+JG;9A)k)q;kdC4El=_|c!%Os#p5Dp_NXAgc8f0S|w#ZAs zrnIp)UaqVy%Ri5Lu7@%mt_RjJGnDohlqlxKLKzRStWk&s<_J;Dk$Ozq#skEC-OI;yt7w&}G!+jQ7OXGFQo|m|Z4TkbL7(af><(Icgf1(+qM6 zY?PNF6TCEJq6AgImE+YkxR7C2dA1;7qlI)_&5I-94ESOrws@@Ln8Mvc5Db}6+ZW|f zD>ht>ns|czTby%+dP0$VmgGQ}yulomCB)^s$%tYAp&ALpYnYXUGM zp92}h=!zL&y&O2EJ4-w1lUTeOdcdZ_yNQ?C>iYm^qlIeYcviN3h#`%a(PD`9-^x+1{B1b2Q#26JP!T`{(L(_8Z+p5WN=?U z<3oLAc$?lxbaJC`jf}=LTvjjFzJ(3GLmB~3B#j`RP0j$lc#4bb(N^(sJbC^6-`Me& zf{$fYqbSx7m~R=(DRjw1wex(;>F^BNN1(RiQ%jEH8uANuxGQ_pSTz+%j=!(HYJ2xg zm?TyTNf1iJ5>9#_P(+E_jfWz+Jg1$yq3LL3D0c;Q7-fc}kVD)iECGSR9gT`dr0z>` zEbR7Fmr+i=DKHoh%a|@q)o#0>v4U%wVpLi!-{sn~PkO!tO6J=VECiQfLC|8)xi_LZ zGSH@GtX0cmjPWruxcGgqas&;1kOaNOj-iXND(FPxTN<4Xo74z#h? z)fZZCk;^%vJZv$S$~he3*;Q%xeF)b9IA?%0 zA3zc}`TFDPhcVIvnxo%c8s+yypoE;V_oS{xc4VcVfp)eB=O9!qEyr~Hssv2nO&+D| z9c2JAxQ&W$@WcQhZ69xr2pmw2vI=&Y!>W64SVA#f8Y@`P>2F4c-l5j_(nj5{v+x}# zWk;<8q>ibzl7hZ=JpxYi-dKE`jCY-B>q4KrQacZo>3ykN>h*H@&OA z4LRN9!(v<0;|=D}UG&`qbkPC-XuGAD))`tG@!Nr`v?EAAM~wf#mf1XzBG;VJFU)~; zo4^uT@)y9e{snol$CugZeOb4A}$DTtH+?B%9+VEHR5#Q?8K9K za2%qw{Y`8FIU1)T?yvD4M>rz^u756$9zeMrU5rSyfYp0zy#F_~*hs_hvLP{C+C{I-=<`SMN5rCuR$H?hPM#FAf{;)d;|qheGUDyq8bNA->}|r zWU41lk%j$)dJ?3oZ8mE$-=#tVLyrUn_ZU^581wp&fZesd6zlaQ5O97|txdn8NNrJM z``G;5q~C5|2Z`5*b9%e|m+}ts;bVL6i*Fz8ABg+6J{>^%4c_cKEo5#gJ965B#AJ79 zv^*u1ZFUdd?C*l$c13|N6Z~)KWjk<61uNjMc1*A_CjB#GQ-ILDa^K z98q&iAudvVS)n-z;ci8NpObIJ4GDVU$#5^W*N>2)sPkeoG%CT&KkQE_8`jI0&%y)D zsw3SHopTt42-d(x$ouw?^A@x*ji)x>+9~9HV#sOp;f(Z^@8q&0ef@}*S%*^o_av}C z)h1CZXXxXnElEY*a>i#?k@N`_rp;Vd*xo&~Us41^w_moN+9h>rf0p{JudH5oEX2z5 z?`SskyxZ}tzQPQMYdEkq1Ov)Wb?jI^iQbhO7%SXCqvr7*Ju7Wd_VqY9KILox(BfC*EGJ{??Bx{TjIOwhd6u_beTk! z*`&)nz%uPx<2xls<2&QywWBa>Rj}n~8>2Sp{$(cD^rF-}j3g>>NWYbNjfGMS1 zE{8G(qkcX6&4rsrpc$HKfQ(k0Re*CWcv`T4)8*2m@;rw}1WIAWkzZHwnv}U-JKs37 z1l8h%QJ1{J@;$z@z1H@sQ~*%_{1Z>!HN-y1uMotsgL^H z$)gBid$9t3vgIxO=g2s4?S|0{S5>-MP4!4=KP7F+cSR*80_8Oaj-(sq)Oo>k*xcoEBq@5VM>TW%7 zFA0oFPu5vY9NWx2Fl$!4ef1>9M~m!G_pIQMD?PjBlVs!d>JIxbZVy?t-W5}aCDf=? z?~3GMp^*symFP%l3xH;9_^=nV8*ms3^Gq3lJ47sK8J}nX~{N!8(dX# zTDXRH+_wjBr03W9+J|4n)8Fy*SJ17b7~3LP^@1upFve9X8d8}~kfDybz3X6rDydeH zafokTLKZK%EUTa(f4lDjsMcPqrZ=Jrvux6CWGm{8a}hP^@XSz~Q9z(H7NVI(I@)Y> zYNJzfrQz^>+@byqMerwagiCJBLNZA&|75ql7mzd9eF(C$r3R+xkibp~*_;z>&s4 z>6`J2mts&kg%3?ZhkCPQZ^ePJ#<;EO`}+U_XU!0r&`fIVeHcefYQy~zfIJBW&yj*f ziN^ZLybHxZ*XCgPr178|Y*jWJ@(;j3)Bst>WVBxZxgdD1g*;&A&ZaeC;|NeZr0;ys zDYE9|6A8s&k+3IayN&TJjY0&ZQo_gd% zI#L>iAIeYIK`(!S6P18zR%d*GM&Za~ceSjiP~=gx!MW(^RJP|Xv@We{=k9eh#INOPG?y$QH0VC_)zv@l&zWx;y6?7;~)-u3az)hi-C59zRq|; z=vi6R7tRh6&rK-=V zaR;zjGEIUDq6%j|e_F$X`j2@Kx@T`^J@9(Ho})THCPJ>W9rU%l+W)EM1X`V3KHTO6 zM?{E4c)Ot!^Q^5}A0CRzo!wnoziV?>X~axAX67IBWf`v@iKPk|V8u;WWF9bq!it=|F%esOu2)|?Cm&9UY?B_++ z7H5LR+!z=3Kz2%Gm8nHXRK6d#p1aID$C2KrCc@Rf14+FGCHeYk z6xIt9qa00zSROHUDo`*$12Isi$a&3S*)&t&?y_`TQ@cszSfmvi;I-PNrv=bqtBT9!SvK9y#L)E3A zqB`yY0I$&+uLE<5c!TOt!2R+uI&rHczNMOgt5^GjBc1>fx$r-PL@mWV$1hEF=S;2D zz7U@e5vpToXE$B}T}8_d{?+fd>i5MZ-Y#CNy7%xd{!X~gJrl;+Oeym(YQ`vB8UPJPZlR?_9iMsvNFk2W4a4nyMUOX$&7DzGRZm-)CO5Y<5FdH zqW(<73zrs-46#PI1NCXaQEszjL>GN&Ar2;nQr-~??ecCo2NY8~?m!<0M`f~8FSSN= z36AQ5ZQ|f4^ajr7fx%AqR`$`PeG~=NNed-EU6g2*ftg^N?|htO)LBZIB`hGtDvP64 zJ5~5KHYN@;ggDoWAV_7n*^44DKVRrwNJ|rp6uWcvxzcVhZN^A1Pa>b}sotYYdFxO; z4Oh(th$><2XH*t=%y<#c44MUelhf_<6r2}P>GWD18y1|)8C{DXNk^%GE8>>g3JuwP`Tb2VLl z!{U>e^6StIiNM+@*k52hFJ~`toi&0LKx_6k4WF6_BktjwsS%}J$1cNsUJ7wtZ+#;% zSeSR!UX(}JW|}+V*8^R$BvSIaNco=9WSBqNW5(AjCZqf$fG;~b)SryYqPpPJe!5i? zsP8=Vdty@YE&c|MB^q}tJS;uJU3lN@z_!jykMKP_9Rf!@MyLVL-bl@e6yRjVt>4I&A-nH1VdZ;+5Ir4@#|Eopd5NL&R zUttw6bCGli5AYu8cDA>vCdofF2D+054gGXX{=Oxn2nve#Ah_oEaWv7N43kxgZG9!N ztn#cfg2W_>)hKS&1m9t*j+y$dtcAU32gVw<2y|!TuRZ?rq-!Bvr$GeHW)lS>_Y=*y3 z7=9W6G>w>=;7`RZz13Tj2er5A@z-TDe4ExPZ0xr^i1he~!y&i2&YMhjw?_r>iQnJE zW{9l;zc^56W|qKIl^gK}G4EzKwis5U=KvWLYjcxu z`l0 z>RXdsxT6n+tdYt2YT-!S2fCE}v1CC(fmIJy1TfB)5|6rMQZiZjyWU@#N&9eB;PJ2o z%A!|o81p-N>yop8HP*1ME};JsAdu z^n-r-Gk7E0@Mg*9MJ2n4@cI111M`Si}u_y8^ z`4EGy2l%XPQQJs;p#EoAC213tH7e&X@ygAirtuP*S|~!$SoJ47Q&15P?@O#8Wu&qG zjCB0=B)q_g?r$?qDrFj$j*U2&n!GL&W@0j8@i)K3Y#x|{CEpoH+Ex^(#WYgKR!mAX16z{{ z^S?D#;`&^8&ep+mfju7e*3M=RxY-w(UTh6ka_OwLUZCeItTHj#I8;A;olW%z@c`Ny zs}3Wxj2O_{MCXcsod=#iN0M%x$mQ_<#v_ea|H&O%T|^yOJgde9yy$H=jhOl3HtAvQ<;l zoQf-deS?M)xUc`xBV5V)dZ}Qh;PMEBTU8H@%VG+;dw?TxNkUrV&7fwmgSDJ{bHP9| z#+PZ0N)5nx(My>cz~uzcR|6PI0OM@{L6m9iE8W5KPWbOhSPDNiD9qo*!J9pJRmoQw zeVcKi_;Y+Nww70eKyZ=u!FB}qda={dB843gY6+|H7TewykihC*y+0T097N?tQK8dE zII&x7EijLx(^kB&=~O25RI7KOk;c)flrTb8Hpp*{8XpYo;%{s66!ke2TlPT!Adpas zOi$vS+F_^9k@N@4fEiw`<*S$MSL5-@8Z`qfI|xD^?acvnZ{K7YVn}HaN!HWzXXD*D42|`{MyFD@P~9%Bzx|I5{j6+&u1M3`&YWzUr+V5MH?(6 zj9_e(zbVxRoADOE{T&C%xHQUNMmm=rFK6ZP6_{{5|I7{+t}%m!PvY}@u<+$z;RnIO ze+LVHwvzC&z!Dh|ENrIJ2S_0xQ*oIAfZ@DKQKnV1BGeBr&`SpaHn$1lsi^Y&G1uL= z?Dc~uuc*l3yO91079yx#A=EnV;)F(^`obLCyAmwSMshZj5eF(TMX)PGsBVt`V4(*u zJ$wmf3~&UX*bFN`rVkdP06xLO6$oNy{&Wa`>k8BH2DaJlLBHGF-H5o~L4S1q;^&U*XuWWQ<}spmgDrK;lU>&yw*PEL=-$ zhCA3CcfV}R-WR-|Ln2u5B>tikK%C1fJbrgKZUnX;O)}z4@-F-uLM&{c`+@A z^zpJ_;o;yb;t>-{>3J=Oy;!Sz+iK9{8sb9-meo#aEJuuuK5AH}I2rP_6@IP{pf zy+SW=7g={?LnmkvY%Qk$#NuyQz2fD9gu$FEwS0kE)KJtxi*GLd-Y(QWc9-C__OS~y z%hBuE3)N;Y$z$BVm0e4_hV0~t5kr1!qed*z5m$OYFW!lb9HW}fwUJ7B9+z91xmy@= z>PfsQvRvFnNQA$k^`nX9xyLNoUo>cTDtz-n*di-cb$yESBdt|N`EH~Ij&(AYKY|Cw z@}}J5$#u2m_j<_Ir60s&eyvfwk6RhV zC1DsUrUj0*UxYyDIMEjF4o{V@fE>C;BwQ$C7CI2;``AD9@ATzZzo1Mn+&)9l*v%;X ziIaNrza+?4QT~SuzbJxT@f#pT>V>g$Yp6p+5&lqQ3aEfaITbTmiG?Nrvz>~}37y9N zl_@^$D>e_2HdtHei#ck5L}Ubi<(Fhh3O zr=#ZS97q6~J)k)G;1s4ef}hh_Ih2bm#r-jyq^$N|toDFxW^g20RgGv9zV<@)&t`z^ z2c%=t{)lI_5Z%E=p?$@&p&HN+XdsLb5EwqlUt7r6lX5xghHo&W_vP0uIbH7$@(eTf zU@rvGAT7oqqTxr2!%T$z407-_q?`F~_-3l_+X(_QiGb1wxQW0qAVvhDB4D&20HIN% zOY~=nk9CQ!r=!F+yF?V_OkKhe8tkxE=tsqaZEu}_w$K;$)>FZu4*@EgncaAPua?GB z6hi=a#;StnWFHc;jR>Y%a0(u=ppDd8b$LQyk>;8N&R3D^uP+@_PkJ28J79nEkgYEu2ALlNxu%2YG(4aUEm)wT_HIqI4j zsPrRM`zYle5i`o40<}f%@yM4W z_g3Lq-FUT@dve7UJR?JA{0k-#qx=?T4B+_dwd#t0lka$umhU7=je3;{#6i2!Xp6ex zOT5+QVRf*rutdLU=wJ$T7){dftW;_%o*alCFS1Tj|3DKPd5+dw$(>pb0}uLd-&HuS zn1clM_nv@mH{y>-C4rgFAWby$j{K#y3WR7$rp)@!$oygt%l^}Yl8mTdR z5P++ySyL!&9-h_3tucEXJnF5ikt`YGk%iNq0v145hL1Wn9UAgPLhnbySa2ZS8Y+!o zZ2S?mNgg)s9cJsR-fANxX_|_P?TPXzp4GcRsKqGBLd6tDvb#l-Eqa_{ucft?{sHmI z*F!*5-R8E%Uds7rMJK~Dynz87{4f?L@fZD>$`*gp!|6(2 zU)&;dU~zWt0ee1tPkm0(IqH=O^-9THcsFnfL-~PrS5CAJAmR%Zt5*S+6YE!tucqlb z8EQ~9e7FOpnJ!-;=NLWrtp;yGd(v~?+iI!wkIa3=R+nF)9?9MiyjX{0#6n^6T8Uaw zx-?UCB3wGS@Q<7Ub8K}enZ&~W%$1ricA-fkCc-)D(`4!BG`w;;x)Yw&zf)RubUu2X z@_1!d8L5K_@3d~{zolE)mvIxF?GWPlgRD7AI$8buLCPDNDjkn!HD}jTT=SMIsiabnfYb|{m6~+XcEmHZePb@za9GyQiuz~qqej~79wLI9O zvxRpvLGy2yT_0})j|Fw*&LK9;b*8FdOH^r z1m?~#DSdGYM8eog9vNC+p%(w{g$aW!DXmX-A zvMYQO5iu&3;jIP;RnHx$-XTC&AT_W-;cqfK*HLbOWPkt7C#ubNdR$HLj*yy!KBxKG!1aAfp8Mc zTS4Ki7DVy&ibE6TGn*i|$9Gq7BgcPSW%3x@AgQ9=L~D2UV<*`)gFm{(_ydP#G;?>r zq(Xh+BPgTs%t3u2uz_lt%Ll$EA7A^Xi4INA$rvS!0?x=I6a0|~r3u$vEGxEW~P zSm=Da^lrh8Nk2yd8-=rd?E)J)k`jF5V0aL&2*h!PudAs!LMC3AtH=>T>&ULUfD}aG zKqTTzhZ|xQ$PbdhzC9jRdbDM_EdZ>gFB97+MRKb($0rzTBwk{C|Kw=&0~-WCVPhaE zog_#e&$_LVj4{)HMDmMqyx%^`t5M|e;K;kDPmAXj5V3Blh#fShC7<+;K|u-)-zm;0O=G{CsR)>ia5fI_vLO54 z9j{X4pdNLO#omh!fJ}?;utNYn>az!1B&54xN|!`?lDPfKIiuZAa(~ zL#NEbt>Z>PBf`-wx~VOdtq0oRg;8*%IMlo5buh|_gq#UH83O>uP`tw^@J8MZ2KbDCQw!=b zV^8{BeS`t;maRTyUllhb z4n^zp7elG>jlvK=3=GWBP06P9QZpY*-ZgvQlByoc;cfyTUV&=O{I88=VwbT3lAl{r zNn5ew#3JY_SQyLjR2N_aHJ;MM(zq&h6Q9&geD*Zm#J>|b}UlWfc)@28*nK!FWi@kFLm$FNFR^F-b&Wo_yHc- zn=!(MuT^7NnEMwfeB=@-{645Dt?CBhbc;44BG!FzkF6k5fF?w7f&LatN+{PRn=vswO<-Z2H{9tzH;|K|n z_i;uC@f6Kr>-%>R2?b}6(A=H2)GvTrh_xSg9zf?tKdDtND6iWh8LyY04q87);Q%e1 zB7r-zYdIPt0Zuqp2S(kcw@YY*Cwwv;1THeI2_F9B7C^s(K~UNLAR_e^LB#a&Q39&D3me5ya)N*J09Xbam8<-qZuRFw_@ zs0-BpHu5gom|0+r@z@LoFBS?5-`F0m2qG1`eg(+O3n3p-8i@MFs@=`#Jzgx0uAMke zcyAiM)czyKu=d;Ltt98^6L#xy-$Y{$umZ41WGKf3t|ebh09?C=U&C5a!ejv(9C2x< zuDwPAOLSB>Fwe8h^Dr8An4~IDb?0#lf+lspp+++Y&E}0hz^-z6*ruJTb8itU$Z#$* zyu=I>kOB8?6ACH<1=*5<;KsT5QrEmD0W2?6M}87+U3M|JbsOGbnB0kHm2iB!{)NDQ zjT4c_N&+s@&$0|T9mE75;6{38QQo8Upy4=1}KH=ZxBTrF@WAcYAkO-a9B7Geiyh{6`95Y z5;FNa>kQ}-wqK@-&J6D_yK(wmGTv#%1Jn5*3eEi`d=qdNu1*0AUw^f;NssHXpw#z( z3`$MKvw9B{6b>MLQLS7Z^CHd$s>gMSb6DaBU7{CD{8>s=%gt@@rtYGCK&OE^5sRaZ z{rNU_BgyEe%8BcSszf)Or@)RWRf%9@vM(ahakocKC(x}tpq&|8S{NLCB`e+5SN7L= zXOIlgmB)w1hxGw}^~R61tSpK8A=izV0c@l3_oK^C(J!=bm$<*uFMS3wsx5{Me}f1S zZgEGnYGGQHZom@N;=&uRv{j4Ce(nJBo%i^3Q7z!$GjvahC=v%Ec%hYz)mquupBPm( zrk#d)Ka|$?WUXw#-e6f|3T`X)MyoJMVZlR1;u=&*MWXxzJg8HC#E|$WxCle{{V_6h zpTd_q3*Do~ZDTLIweI7hogEl?FBsr66^_%)hrHIx^2@#)=qgHjGjgadz$!_@;*jYq ztY{U*dM5NnE}6nA*j^KF1!W99+_KAQ+-ktG53ebxI9AT)87jBRf_OL~8XGZF|L59f z5Zu!Mry+HPFk;HROd*=F2^xV_H&&xV3!; zxpX${O91jB)^1S+3T=SGw(N3I*seUxNSDT{hf&>$8W8O>>WFri8OuMT!;Ey>4K2Hk z*frMiE!M`T|EBT>pl_krVc_7?+P1JE7L=RrIDeHBaNJ4d(Sw_dN! z>LAjk*kUxpXNk%hP<;beeyaS`uC5Kh)unF2Q+!!IBfhMM@3J%m9&*evgI7V_T?B16 z<*ig&Sh4?F2z@7IlYw8D*v_R+wCoP(L>O1+V!iSDC=dZI)ER%X6LAGm%00}D&n@ z1Au@X4?xu)el9R5y`FB{);i6-YhOPWqBP zF&;D@)7I{Rigdi)fCK6v-dVRh#Pi)EbWcG7@SSOfUYkuI_ak<1u@&M>W`-tW0|kD@ zxlNl$E$%u1t5jG~%)qt;hR$?d$D(|()eTT+GO@YMjJ$8+-QXoiNaFYNAWTnkoZ zsHN=OJ>UUg>W*YgT%dcsE8cO>nR_&JVL*tVWMi4)lXX9_C=QK?TpUUs1;<;swBzdf z<^}DF^EVp-F2#`BZ7f?Rx!=aA#K6bhihFN2HU7o80+Khxe{U@I93C6;c<^90n<0;T zmNBCm=aKonZI*G%!BqS?l={8bSmJq-xeqdfykMHSjs=yS+0IujZ*~>sZ@cvgc!4M1 ziUWl3@jdvnjdt|>$t>fh{5Da5yBNYy%z){W%*yWvgi#0)fBt^+4Bm_N$voekJ zV(fhK0IkTbP6^-fG`!pBRFwXm(a8(mMbJNe{wnB&NI_uRAZ~pL;*C`kHGt~+Mjlrm zC*^2;tR<8B{r{}a_!epSpC`9&56$RN`2UOcXm}4C2ajFxe}^~nICw4SE$zoj`~Tkl zq}J^}p1%J-@b5eh{_*(#|McHE$HAwY%Kx3-dlQ8o+}wfF`!;{)qPiM#@vPMdtvsS^ zNUF;Zr@biiYt;Yu%uoHrjwL-)*T~aTJo-#+0b6rM`2%>s1?Q>WfJ*R<^m3hgzUrxD zoqE`VRi_)3Luq<`7^d^{8===NMG459(CAfa$(P3>;U2|SqIC(>_@Z?6H3EHwjktsl z|HR|^jEM907XtG!!t9}8P9e+#s7qoGgrQy}X+vs&`<3dCy2SM?(M6Xyhb5k6iA2~+ zfCbjRhH3^{P>ZCL*7xQoXnx}+4r~W;TAhAB$$n2#&{!g*coGkw1eg0uVAIZoZkFsT z!QWJ$;nneo2=A|FB0s`p>n#E(3YDm!3>U=}p5N74}JkDRj96P^3Eo61i zqq^|j8jSts1$7PIaM>j{w!)%;r3WxI1GiM#wVwp84 z1Ih|t2vdB5cG!5gkjL48t0qNGgMxcdh63@E{-;gM?td8H?fyU4>3@nR?%_24^>jSw zZqQ8&GRCN;j>&TYt@`oCC@eT}G^hGswhPCs>QH9p*Q*yl6>6N$mTialLWc|-f|ga0 zXp0?c+@spZ8b(OqKj00mRbwIj{DR=B`}s-@b_+mNeX7A8%m>&Kf{p9vmq5T1^z&ul zk6Uxt&;9YlexBd`I};skOs>XvFWu1w;%c?%>CZlq#$3!=59wO3XRTiWn<|{>))Him z8XBury`alS*}q5dI6OIv&1^b#)B25;yhTOpP-9_zu8*W05Px*LKqtn5V-%j;lJTH|@h0 zY?_1&-d8!Bn4vR!vYKARz^Y{+%AIN`>O`lYDQJ+o8+Cz+U^(^B4bP=B>}}LuIYML74bNQi7VT1x0Z({q;K#$8fmdMjB9Z=|0ZsOky9IKfO7KcFQH=y( zz+3`2Re2g_!vM7IVnEZaTNE07uX+MdYycux*9y(FTuss-h7iOg4PpgBbO4BWxq4*` z2AfT>si)BTThFCfeH#>(>GO1o)oplh)x-pA8>9TMoGS1Cmms_YHB?Q|wRL4}j{^&h z@ExJiYt+}IMztp1HM+>7EOLb|^2LQHay^L}Cr+#4%JkJ`e$O%)y39)~GeB1pn_Vkn zg<`zSC(X}IKRNOg;b1X62|pgjgUyd4qa1Pk{Cc!Yj2}@VIuL=I&M?sAg z=6Z$sv4QqOmiyCGuOe1Ooiy3(%lz(a@?zfDYoZr(Zz><5&grIPM0%Po2f$ zJS!C5Bn)sQjsX(!4m|WIpjO?EEC9WnpxYDlG6!@>UC|PBJOkWD2KX4nmU(p!er3Fg zU%8l6&);rj*W7yQcgEDs__29jnz;cW`L7Ji*YAprKGlF!oK#)f_PZiX!{JOEiG#@r zC);?BWruq5P|bJ7l;{Lq++u<*_&~7#5Exf2(AaOw1@^^kaohy`7+T|SRJtznEXyp` zW$tI0OqPk`sM&F4J~$xt_*rI%E^{@@d#h9Pl zV18b#p|@op*zty_6MAcT4NcC0n%8WaDKHT zSRDRAu#U#n5Op)r84lznG$Yy9Q~mROA<{aaUey+p9$0AztKS5)q#2E0BQrF2-VS&Tvvd-~Vo+YI-e(gtAADf^S9hLQ$QBLlW!zF%%PyKOTmKve! z9Kt$#>N@LD3imAovJbh#a66m;+ZAHa*Q+s9m^pXnZ@u+GY?Nb!?NUz;223PmsiytX zfVKoysDa%xl{2D>jiIhVf>vy}-KXB( zM-p8)lMuCHLx^JuaUUv+LDXtZ7GM$=bvnQh#co8gYv7_}N2|d#V^E^(>vY1oT9esi zYcf|6?hIC`HJKf19xCBXfqSpsQd`jmO;k^uB13w%b}^T5$lEyPis+|NP;4bo!yV$- zTZ^pCV|#Cooo7H~WJZo~_1^7oivYv0ZG44d>0>Q#c2S@P$I`0(u*uaHIVLzlP6KDV zaV?)vE8ZCmLrnV9_NRUF+qfP?LH}U2=sjV)X{2g@Z6ioLA5E`7(<$1=7@C~#qV*0J zp_$Wh8;IA9ZXsy_W`G8BD!~lYU^eyzn2T&M<7_aiT7$s=PV{3o+o?)c%KguS)t7q( zr3Ro;m9JslOjzHcj(C|gyfrLBc|6n{2~@XzIPh`Xq|MfZ)SBibn56?p6U>m8Ar@=2 z1sEF-Mq#~XfH7{_BdSMZaJ^Gzaej?9=@$nPvg=EPqC;t4$Bkt5O_u|oFih>cSl71| z5@<2Vu*{n-;TvqC%9}4%^UZCgn9lQdFZ*)ih0tnJo7OfRPtN<9(sgkE*=Z1!c5rWl%aRZbBfxoN3}hMc=6s zUxxiCT5G5%o5}vKTPoms{+RWR<{awZE%j&aH0eCU?L6SC3snz|`AA?}wSy8H_h$e(6B^gNEvOG?P2cF6MzW@DzyRD4qj6@es+Kg?yPmw6%pn`->wd&*DQb`FbIagQmdsgx# z5suR^2gfQ=f7fNsXBjxTlDxSrvz}!r!6?&Vcy1Fb6DJ$^sK@gBupaNiXP0ZBz0h4% zJ5vPczp?@JY5;A)XY0^>r_*5nDaKY2bj+^0_(tMXsf$0s;@w-}bZe}%bTS4NB7MXS zTESG~xA)69{5I?oLUm^ai*yASv4R>@+ycM!xEjDhAP1(eJ&;xlG=zg7RaHPk__-$_ zENKm42XMAq=-q&fG87tTV`I=EqsDK5jUVOZQE;vE)}ikyaqkfUDH^@RdEeCd-{tKd zJCF3yD?5b-ZP4y2IXN3j8_X8GhL*LU!T+P|T;QWDuD_o^0ucxs6cDXSRMaSHqwx}q zmt9F<7ZQx3fb|ytc)@C0lwFC65KN+MA6IF;RI9Dn+Saz#qE#BuY9L5J?sx-f6|bF` zYVlHTR`>n>W}auWiQ4wf=ksKr%gmWGXU?2CbLPyM0bModCJTBczSC3Qo{^CQ#|Ltt zOWwv22~KMNPvSN=F}WxBZ2|bi!^Dufd70QDt}PNdB^oNDZ#dfDP(3=I=- z8q)ak0Jh|m)T^eTr~b?V{0JaR9&i8;5x`#wU{+847j*IgddoD$lxfy=OM0ZMsi}3q z9u}~N9I#go1K1P+%j#W^b^$~G%E<47O%~JUIap5%RQbtZofIpNHOqzd4HROumLJ8nc*M|5QIB>LU@A;_!Nn`+T*A~$VSeT z-QkYCS9j{T5}nv@1b_Y<*P(|h(TsGcvp|627Q=^$XnGYd&L|5l;-sSLk!^U$m{F+C zOf+o}^L1u8Pfk^JlXjg6Vbyq>#WE@ZSNg_AZjKL}Up_dO!>ZD)QM_k9aBqG`&dZ+bbt2nGfXPsudL}-7I!zGVw9U zx1w@HG3R##Db4#UE$$B$gS+kFsluzdHy=?ahx@G5xVy|5;BK1-M-~6i;k)SVui|^L ziWah?cYtF9a-zYNaLH=DmoNo`iYWvg24 zonKV8RVtS?m+h`05aT|n(FA9(i!E_$?%@z&noy0mFGhySUTNFu2zN8gHCgA$s>S3p zckrn}uj3=k1?{#e{(Vpvk+yMfrcw_}q|Vs!s|ds)XDv0kBx_>UE!jzhzAB*)BQ zY~C+&ptcCq-(1!25vXATRY52|up%sajFXftMoCCbUF$sSje)dy0O3Dhu)KOa(CgM65ZB-yXi zGkz=;l4}|(db99u^R1qH-n4bmiIUnav|I8wpD75Zeqw8hm=|BLWw)tp835thvsCsb zaH8z4Y2U$=?m9IT?6UU}&!Kiyq#zzP4Gz)`g5;Y`^95-hkg|uG&D82^0Erb#qu%*; zI|5ri^5R4j*c#94icgd}THZPF-m&CHU#e{=w44(^HlR9k3g zT&t+xjW(W=lfeJaH_u)|4mHc0?^^3@{AA9!j3tkajXG#XsrlV&V7-^Bc1I@3|sIvv{*I7%67vV4e*3s^!<_*8G+#vuTu)9kZmKqu@ z9(Zi$bBbZj_-3po;xa|f!4 zPdHz!2g%>iR?qt^AJPML#LogAI3b7Q%pT<~;_WbH>0a`4Zki&+)%!fKKVq}ZkI1Ej z9q~Wnziie*eqY(bq)HETj_XbAq2lRUAr-Hx_Im5vX~bhzeO~xVeR|k0acLUu*9ZG$ zC!D-B(X1^Swg%QS{?IRkU!49+70ikM)>9-@^)L7Q-fo_WRPj?V)uxMu7S-E*3MhQ3 z_EgT&*VK^k{;&trqT!L26VP}ST&e1PIK}q{pG2yTcSV+#Q}}G|f4l43DSWFAwtNT^ z>uA5hy!WM}-WOzRoKuh=YL-!2yyFvVY&NkbTUy8C9Np-QBi>Ps9rYsK z3$f$@BVtLmU^>33CjPy+Mmt|EQ)P2r)N_pn&@IDs`eRsg3Z(r@P?4U$Bzv&xHeN}{ zbw97GXsh3Oh)a%kM2sohdGOxe6d&(*p3&CnxQoAHUR%w`m%5&PdwGxkbIjNDpDtwz zVHnOnV5=Mj1zw?%`$ya??n>Xe4j>S0n;jv8MOKf~Ph zysgD@8g0o1PVf#>EgqnD*}}e)T1nVj*`857q0F!ur<(~5$Q%K=!~uC}C_p9wBulpb z=4)Y?F{r{Et(F)lXxB5ajxJh}$EGut<;&enfdL!&^$mi0bsH%+Y_?T*XKSX0==|Ln z!Ff`JKl$5n1XwjWcxE)Waxi*jsH*Tb-VrA|{+&omJ5)hTETtBy3B%0&Zv_26ep=Kk z97n?HoKsJ9p zjR`MgV_l4?Ozf+Y~PAyMA-KVU*xqp@Yf1`H@3)QDtcByx)!g= zw_U-#ZNWsU2m9xcT0ktkQ(1n;t{iWLogwoou2=0pvTG}wBQ5W{%quKst~M9jsuxaH zqU&6~Q30p97RdO&zUFAn{H3s%G{g%u#Nwid8uKI-{8x<}iiTQ(dW}pOUo6P@>044Jm zx}S&j!^G$Ue2vU!D^wH--J5`Y*0}g{zkbzXkK21Okn3!IV$xFL(Ud5kFb+zTI{z1; zmmPIZ{FkL~qNIf(p*hb1EZgdRqO+tsEjgZX#2uv(mUCe!#oP@3V!<|8Fh7qsRT2U} zRzk0E+v}vLuqi@K@=)a6a^AU(gwVCt`!cj-M@VXG30Lvlzl$SHK{H6gJmu`|8Z|91 zel(*)NxF@gQF9I>s53+8xwfA5f~Codc~u<8(&0v8(R$O0DCaVjJ;$eREu&I!M$!~5 zXx2&Po(3VpJr{`Ge0AC{_W~O7lJ^65#KGI?Xrlp3A z8A7iiUB}-zO)S$^y0L`(09v?)`|xE~Q2v@NFidNGK?N>Rw*S&DwX~mRhu(e?3*o4D zLjiREDJf0+=deL%^93Vj|C$V4)?Sh6JYs$i-&)Eb--L zk-3Ugrzw@~quxXG(S7_rdbohy0KcN&6nSi}9Pj#QAzTG=mkf5oVdv|vA8aOde~OmG zgXY3Ho7Yr-N8cSU*=n<)Z6SH|XI>gazGVJmJPWDA0Y6L==g;N}-<71eMJc@e zMt(YR6fC^X=2(?rpXW+*k)X8a{~z!4*Pefke`i~*J^vyetuTRE`nBgz$o?wyx~(VI zIxH0dkg$qdM%tC!!oA5OQXOOJe(sZsq6nGj)Of?aIcG5g zsd_d!t zn@tYwcd+Hf|M&7n`Q=%NslubO%6sF%|5l!(e;>cJRN+5fp=m{e-ee8G$>N$-^X|w~?b7b2MgdVHUFu%)z9qCCjod5#h*{$0Its6i|`E|Bms81L$H5NS|-&PGtobgh%CjCOC_ZCMy zh3=3&&Rg0U%B0^?@ujc2Oc!rt#mqyDTl<6`W1w!m&x3ADybLT<0)FIVbAKN^&tW|* zpjds3>cLJXctGU&GdCWlP=%v~ovj_KB%D)IJ))GEQewCri{a!n`=-s3kzZ0x7la4= z>SQy~q1@UOc+H4&>Iuj?E}n z-yN*&2Z6kauj`UGm^D@WhzvRv{)ZybL z9l1|`p7!Z~tDpb-F8|5OKgQ+XNBOV!^RLLxzw{~c+xdxa>JK|8w4TDT?T$|;elBNa z4cR_G=Z|eSrJJM%Se@d$P*Gp4D-y5$gR`WZCu+^dPgvwXAoY?nT;YqjH@iWKF=a^~ zcff2P6Q$sY)k6V(7fCb$xeMU5VrEcZTv$|Q&oBTOzgH!ZYOzYMrbh6`4zFsw2fX^n1F-$XM+T8eFw zAqV=kJCNFSqq^holLE|hv!dw{)rlC|a9%9EEf{{YG-XR3TmP*2#^e_DQ}g~RONsWT z5!-mwUyMUtHFEhD$57L)NQEe>n1-(#b>CQDo0B-gJn%Wn3N{GcD+BIQE5n)}-j z*F0z#2^Hmpjzkp;6-A3eN22fG^Bpc`*_F}7)RIsMc$i`n45}V6%_e~HZJPS5=3rF< zB~&V&0(G{|8DXYBZb_8{(IpRCL<&z7()Cnk$veF0#8Z*uv>CXSw^}33E9qM7RfPFe zq_^T|GK6n#iGvdn96Res6@FL%oKnGg9XRlnq>z~dH59tz!4Ya@qIa;Kc6BkQS+TtI zjvqh0gfHg(_O71icnF<2ERJ#fw!;5TXT@|Z-PJoAm3lApMUy?jHET0-G`kDz+J8Grf}8i zW}5y@*FSWdO6KAGE9Ufxc%F{*AuJ$agEWaoX%k^&(B7tBefT*yIz9F!3TMmFgRdS4 z+cWy3f9*1NybP-#>BjNp{R!}pmT_J}Ubxp~CiR$Y;zfOFngN#Y3(w)+-17&&x98e} z7W$ZXX~T|FLBhrjah#}d2td2RXR{-}fe)it-8Tze?5N^$^`}AAqn;h1nN>7Y`ItSV zA!1ja;Pp*??18?!%){#?)vQ@)T6MBiQLjHLwh}Fpo&=4?N{Gh?sPcRpg4-8l$=@x3fZ)+A3w z6aOMA3ta#7IT~n!`0U#c$r|taTM+9_e?X|^#Q|!n)g+Q-eVcv8Z`9{$G+M(e0#&P9 zxs{zZ9YImtc~{Um`9&XHz<2X*o9%Y0!j>q9!6;LdWjq8wcM_fU4IK%q2$G1KDe6`| z`x{vsl$GCk{_lMM_db5j(a$>>3Uk*6Lbk4(44q!>h3my21f6pNwAKpH#Bh+CyL;d=vIH1O7@y9TKx8XE4ws4ds=T<>-NwS zqvHEjw8ua5_F_xm?p_c)OD{}sYVVC;%ptx{SJr^u4xf|!l4#Gy#P<#F zY67?_KLp)f_?6|3xL8S|6+%u zT!FRNwOhLN3BHHhjFD9Yn%DM$)uuqUY&s9#Ds-gR?C=&C#5!`NI*ab~HtN+q+F)0_ zil?3r=s_u6lh?A=Z=9?WX35;~f-4zWw;?+6CG5+gMg8Xu*q<{sa+_8qKFOw}Pk-NQ zq0*IS>&5{qnIbQ?v-Q%b#~Sr4v;vm)ia5Epp+Yh0I28Z`%l7EVH~h+{#^;)T!odxL zds_m$3IR+%H0l+3!(G+=Bg?H@RF4fzqIYog%fjaz4W{mC-b4=^lp`U(B{3}0qM<(( zMIy;LMpWz=LC;L(&5=o=G&!jQ*7!d4oL~cmG=Bt^)9a$!#Q%9qLWMvSN5P_o$Gg3A0qi z7rWvatj~uQ^%n6te>P9Y%@)kd4K13OZhSk$)8Kyd&dyyC>2(SboqERzK$6(FB9aC& zYKp31-MKPVbQ~F4w6w8xL*uTKX5I)QceJ+?rjMXay-G)w=Mc~NALZpa90Ztti#$SD0tGC$*plx=)MVmbQc+k{UL2F{q6q&_J5)MkF|sM+W6IG z4I6Fq=TVr)^&_sIaQ%$ymt4Q)`XkrVT+eVVi17OpqB-s8&2?bSOkzfa$S zy^7plzy1RX2ZsEIulaG`9rN92l%z1hFS$3T|1w~L8&c!$HFv@*0&K1S ze#lVFSsOcPiW#J*^NZi2kro*$OwO_l*PW+1MxS<38?|e#0t$ugJ=#%NeoM?hWPvod z_qHn=MK-<1M+FO5LG&s+k))jdww!flD!_${T&sE@lpzi`Es&V`-ZPdc_>7IH!|kn( zK2zRtFh#lXRrF)h+I8sCNq+k0Kx<3rIYjCQ=Ix<*jI-W$vxS?H+Y?7dM|NH@-{^_rK=<KzG?Q|Q&M)t0VRqVKKqhrUgXbT@G90TIe z?P6q2@Ey)~TAGpB7%>hfgaMxNyXj@u|FXs+zVY3dW`K6tLJ% zDR2a1#=%UM_DU>Bem#`xMEooOeEFj7wgAfV}KHrH6mXf6Y(cUN-M5 z6w9u{G&8!T*af>3mF(`*qkk0J@FSC%PoLM-kbAY*hNR?CWgp@p%otiNyUxeqrgZ$; z%FuJOMoiDd^P~B~p+)VHiuOc)RZ}_vwfn0{A*yCW<^ZNPBv@ZbM=RnUC!o;0M!v9k zIwzWbLGE-#v5F68p4qxBFVb(tygqP3Xi)`aC4Q+@t~w2Jy`#wzSD`M^0CQ+X*fK}t zBAt70&iI*ax<_}>bh6+e_8#NjjHOA@WP`EqzK7IwoqsYRm%d)wz7Fm*7O1@ZW6)WuI z=1r7ryDEIQJJkn0+?W3{a!hgqz>O|1Cq2<3^sJ9jQ4Vt|1LAYd&V$h$Hu@qn?uUK8 zxZ~aDk=2O7a4PQtX*$tx6QRpfc^8TIQ7FjzBeF)>@oZHKbLg`fHD^?K9t-?6-a5@t zwfY>@YSLN5Fce;AQT3 z+R}-Gt*kK-Uxp5IV;)C!d)r`xP}5}TD;|T%rg*-j->AlVLaW)sP>Yx+H_SRc-7gZl zyS*}5k6mJ|`TlRT__~s+pdm%QSIvhDcc(k{0Sc*WaDkP%;d4r^8Z~RgfOsP29X&!* z?aGMvCO!z|7v;qFo~!Q-GZ4A0>9)%9^2A3#)>vzb9CRH6!(p7L#;=$Z@P+8(tH9f$PVF~Mg17tHTQGeHQ z`(tI`N!9V)-)0}$=laLJ4v6^8TUN<%cR-+TM&|CamcN4a4+k~E5{I|P{GY?iHWYK1%mn6lcm;Hc$gl8cCbH5ePuhx>ZLRTkM?7O4 zZS3Ij7Z5Zr=LX#;)btoHyjL4PI4gdUHf*yGG&g>#x2}#P_rWCN@<)Y>f>uartJO||QOh7s8#Y1lS>|hp5 z9u^YA7w<~5DvbY2a=1-Msv{yTzvdeW&nKbGP*;6ot&dpAyT|d>+~aG8-7ebbE|}lG z`-G(i>J;{bp>8c?*Qc=c)z3hPE-OLVD!;PPWC4@7WR(A_&95KZonB(OkcY)Q1fx}E zUL2Gfloxm9nQL-(F>e{`YIGX~Y5|K?s}Z<*MXZkwHT{8ozuJU&*#mMme-t~IF>f>M zF&bYtbtc7E$l{Iz?#bp3_$!rv|0f4`9k|pZwDIJY2Id}S#X_Gt`LiC!f1u2smpq*> znq|`ir?7NJliWUHfqnz!Su4+_Q8Z{w(OQ3|Uq_wIj8%cKKGe$kXzgglGGx`6?=c&K z*sS_GUyG-~EzxFk#NPFc4KCd$lIlkeESGnfwDCws@lz6uA26o?ys>5g;vgsTc(L6pZ%kwL@KcF zo$Km^e_Qp4DN0?UiiK5oTe~RHpLlEQS8Gx*Npq{M28SJ~776@<$>~Q-42{ugc+)cC zX-(K~fl9wzFMrQt-C96Jel3w5X+`9&7NWHrE~0;?nJnc$rFPkrulP7a`TL&!FO)yx zcU_e4ZS(n*znGi><$IB+C*{{Y-jni{|3tikmMNllwNi}SW_=edVJ(R*E2)ChY<(cH zt%Fuskv+wZusC_baBh*`MV)lio#N)l(0Pi#-^I4CZE0I_wmVFnkZAvdYjkYND|yzw zJydWGs$^ckewNUp(>cc|y#j)sD+aA9dlyZmmX(dlVW0n6iwPl>Uk03L@0IDd z!VT%e68-)n>C^Eg|6zU8SyeifVH-~Op#)Eykh(vnR{0H5fmi|0FCv@8* ze2wPk&uO%UA9qZ3t9q2cArJ<>BcYmhMIqhKaMDRNKC=t zIg_YqL@Tf`l0_?C5B+3mvfz4vT*QmjS){wWPZsHJg>n=g3dht=Rqkqmh|2puxZDIxs0wk zf+}d|gO*W(_U!lv8hG#!d<+tItmh+uk4^M;9V|5_w_(q*;m|!VG`^4*Y1nlv8YGsB z?HvPY;Q;Fg^YbJE&SXS5x2%dak{(^{K{P$A)fun3Qyq1%C>xeMM(mYu_$)RayJMBl4_zD1}B+ z*Nn*T_=G5myrq8EB=!$2nw_gJ&(i&ZB)vM;lZ4QZU9a*wo^`o;B*gS7SdnMd6n+W4 zJLU&(RS(|&1-8oRxRJLG^{tJ&CWdYsGJ>|eCe|TeKKf@uL|$|Ez}L>cR;n{!KF55MtHjc?0wMm z1@?XcED7#FUUx9B=U^yAy~~&_%R7F_H#LAL1bYRPC9u%ICD3(_#Cl!?u`W)tt)$lQ z+lB_Qr&0tQXAZ_r-f=e)E(;`$VH@--yedu!%Ig?QCd#)B<>MKAOAhP!g2T}0UqKBz zKIAzw#C`U6H^enPW~mfEBS^+5YKJpiQWP97-e*PLFdWJmc~|6dLKMRpCAFxLQ{#Q5 zKiSVsYaetTpN;;8McIljzNqbr`J1BUIV;AM=NvK~`##rZu2^+>PF@Z7{9ezsjO%u; zkGS@5aZbWF{^jQP%D2ZMWX?#)oBz-Rtdv~0a6Jj!`TQQoZ#};yT(@$KLhLQ#T^_$r zoK>DPncwelxEr~7?`gYd-dx-aNvM}{RS5H^XIqB-(?jV7Hskz z@`%&e8b={PXl`&V`%u}L1=u|(_TYp$*MYo?6 zqSG@Y`T_5|KK1NxX;-Td#i#naHjAR(P+4>)N@03Z`fIyHZ%*fd8LoKaJ;xQ_|DEHC z5`n@j zUGtYM$jlq=;|o3qk68B*e3_oLo*-3aA6AuZML3tEA~|o6k6Bn)Eab~Jg(h!mZl#}{ zin#!bcqq2ADpgZV?9Z34?}uq?Tp*s19WpXW}Uqr0-w{IMf=!ZE)5Kid4kmUJKlAPj~ zU*C_#P4)B>IxDp<%DcB_3~ydFdxN($RMPfI==`OTkxLUhdB4ps`?{wySq2Fp=i_)= zGy*+A(JC!evi!zg@iMaf^?FY0IDcvSMeaAx{7eMkZt3+zcWWRqh+n)ktq`b7-AA|b ze_8V?&gR|1W~9VqI{_KFtoP;{CSeGHRK?22QSMRaPJRl)MKKLrh2_5@0%(4!X3~M{ zk3LKr&Rwqdbk5`I?&;N46-!Z#O14q>%h&e}O+IYHJC-7cweUORu29KK3d8ztRO?B$9pS`Vh+e(%J)?!IPJ&o*qYv~8QQ+Yq`-C8+vWhDIqp)v9f zW?#vf^C}0|vO+}%L}2e3JZo*^?tSpkUmKmeR7#1ok0|k$28S9o+o_y)VP0+X*4a}l z5x3$?W^IwiJ-re~=-i7#=DYHCZc||ce%yOiB}5;PUJXN6R&1U1R_92UAl(*mX&geW z!lsx+U^8GEXJ#nzqcv0Ci8cP4f^S37sYIVX;Y^kmr{zTKxobM|0&~Wx98mnnw^($c zU#{G_rOLy1lFk;`4_mHe@)$`k+u2d6L2v1vUf!~$W_a%nmJ}mbQcGw+=_O~*YszZ? zCTptAn`ZZC4Q=qOr5!iGZPYI}Q7+pFP7cjmS2T^7OS;m?5~(Dihv;NL9=WTmRh#MV zX&t$1B!Xt-=bcAZGI9p_f^ULAo*IFw{hp|ksV8OLzNr7J=_$c4!u3k)!>FOz3Z&5E@hjw1pnqE(W(&qH+ zsoDGg{VrBYIb9iF<1`9oyoZeG_08!yTRM*=<5Bou`00zgrN<6#(_fxRFIs`rfh2cm z1-*BcpY#-xYI!G$*q(iQ*Ze-3mif~%T?U`fbCr3u0%K11bN?HyJjgv~P4iZSfQU9H ze@9zEe6o+@vE6X&?Pp~xFw@(2XCLSK^O*o2ab+yM<|~-uzium~c>x*byuyB-*+=@Y zyVL78e$vZH8cDAu;hfj7shq&xzje22za(YTu3d)o7(Wfk)SKi@IrBmJqO zZl=~ZYeXov!$g7ZG&Y#i{2ZUtw9%;yJ(xcsAd+`@6W?LS=PD0iU2XMOs?*!gxl}ou zx6XOBIekOP74!Z26q7YmGUu22?N8dq_T2i{?ZmfZ9*<`Ag8eeiY}Ou}ZT+bSj9K+S zFoe#z-ycF*#$zbi#aDXkr3W39LxbheU}ZZPBjZ|1@2K(K^48gX_s;8@KCCgS+WRCm z2FdUS+opH4g%iiHsC+|VFo4E(Ztncnj<)R4bHI+aJT|v(u7tv+$S6ah;)(-^#)uhc z$^{4I#6ndsH0~(^l|AbY=G^isv!kt;ZzTzNd7l>ho0N@p%$5}dpp4itt+Ab-R(TsE z>7_VgAuIMpN`+a{*8(?tH+JtoYfGgT6c7~qF>Y^+P2Cf1Oz$6Rd`&%>TEslIJ1q^* zi=P^<8oA7SHBz47@OJgXxpHImSC^KB%S#gs<6kEzkZ*LVbxvbb80l%6R-gY~lZfJNX7yUql_Fmt)wc%NN z%Utet1o-ie|7*N8VyS3S^(A4CR`7G@4o|JF~f zsS8V#RXMEZpU}mRt>hrF`mYbZ-p`=8mdcPDOTW<6ns}L|;3Ir|T>lD680%*ci>KE$ z@0i1eLo1HL;`dX}h^FZ_Yn-47^6X>t#Lp$=9O?_N+wstcUks$K8vLD825HKY#Il-OQKhf(ES%o^;oR$;+7+Ke{yfmIW?!HnCZsfp?4bUnH(v;B3Z-4@*^Lp>;%zs{w-X}ZX*x@Yhj1`|W@0g8WfeOzdM_$F7 zH;2FCw8b8cU&`dX!UNPU#clbAy_dQ!){780-ugI<6%zWgx@^f+>WM|E`S{4jb$_0)Nl)=u&wVb0>i8)wa94Ph9Qli7W- zXr@eqiIQxfDAT+90j-8RR%UQ^oQz@eWJJHlOMfz;AN!&CwRR z{BA={TDSIWZ9EH^xmZ(LKqNwOkd#9s2To4iGb;W}IMlqHPdl2PX(d-KF_yii&s&uk z+8hy{SK97>;Z^6p#OrY%`3;jk`IOC;1P*q(qJ_md$rGN5v|K=9J~i+|_6F1+n2pNc z{&^1fX2FBZ&Uk3$foxm;Sd2yYA`%O{O)*<3R2C_`Mo|ZHK22S8aE5(Ga*6r9^gvhkB+FF0%iAakUQPlh>0GU7b$C+`H#XdHMmO(X^6i6y zMe;P<%=ytE9+dIZOc^g|rFNaUKPbbP(=&*#H$N`#iTHv5>Q@o3$^i8duMB|hG94Q& zHPS-$djd)gFLTpzEu$49a5%d6IP(^if}LYo^*Gj**f5JpZ2VZ&;YdrTR{<$rkqxfc z)#4?whoe-zU!Znh)Hz=aq#=78-i_n2;#&4)thDHUk%m)8@tG|C9`nG? zukiQr%#^;$-(p|JN9&4dN5kL$$N`>eW63G1b&BX9G1dk(kT4dNfK!fnD(qs4^!LIA z$iC)33e%QcwF)Dyq|zZTADm+i)MnRDC3l>RY_RF_l#cz{FG-VIYi6qI$=+(XQM3UL zOe;D=R*K+!KXzF3KAcOE>`9f&>RCl*+G&bi!OigTc3V@vH@cwnXzWdZd<>Ap=@N=h z{6sDX72NXvZd=r9^B^zf#UdQDohcM6P=9W``t^LDx_h%J4x*KGRKDT@Dh2YTDM*2; zvr2oP_QKBszxN>{Daf3ZUG#pgXeVV3;EOHD|L4j(DS+k*n+b9K?_Ksl-)W}5ODd-b z+d?uCnJchqSvi6oM6U9us`H<0GB<;0`9MVuhKMu#R{qZ^98zMhLB6 za&Ioa-gm^S@eg?T!%W{xGl~Lt5s~T$!A5$S%Nkt6ZQba+VkS}#=VlgX<+G;191rr0 z=?6qw${ja7VN_`7@2b^){qqsOc_%S9+gbF+U=rtTUfVjkGL^ zpRu>Dyia^zr;naSLaY7<`}BQ3?%r>7_E|y2(rw7?P}9pK11sBEO6_=0PbueRj`^Xu z70%B0>I)FsX||r_dH?JzpoQ`(zDQh5dm)iR&DSxMA{DAD-VZgZAGz`sKy+mU8}&Eg zBVQ};6@1R3sruYl?_K67X6{TnKTKTfna*p?>KV2v9@{`uOtOS3oX5R+DbD87>p@T> zRSA1j`C%0+{{cRx#@%oBp{Y7=G`G9#-&6K#mp!KJcaxpL6PL|IYTQrFdo*}wb;aKj z1Lag!@nz_i(Nw4NR8#HpAEW$Nx%_)6|GDI^^j0H%ROrR}+?)Nui=}j#p8!p+t+euh zHB8xCX4srV)~^>YtTC_MC6_}SyLDI&jcR4EERGH2hKU1af^Yr)(Brz*)w~UK* z7}@SRp*c3C{|o9akEW z3~R80hi7Ee8xTsrf_|EsQ&2&IS?{|qsUb_4BS%^uRkfa{6e~766e`>HT3dgAtHK7) zmuf5>NNgnv%`sM~kZ9&q7>!SVU1fV!VIU(>?j;d8fJnoDx=?XhS{!4ZJjL;KZ}{3~ zy%d63!3qc1Y(hYNfzZZwXsLDO6A~CNLQ8AbE*=oA7Hf2c4?bF}21eakX z+>pZJ*goh?cC)(O?~}+Y+uG@*++mpBhs0!9h^=1}GAv}69-Fcg#6rM)o$_Fs zQib;^VH!1@vwx(2FsoVJS-`-cRTxBlE3pMSaue@5-hmUZr4)HR-=KmVYvWdy!OF6e z=0CNnc2m+;J5~FXNv5^wSUhAWShd7g3o9y4^XDQkJ-jXz#p6+Q#B~hQt9fmzB4EMG zLux>MF+528geN86^=?0Ugk4NAKj59YF&{hBhu(JY3t--HA88rHp3W0!`jfiRbU9L$ zQqVMQzLuIIX07K%y%fM{+)Ni9rDh%3u=!$?jYoHoF*h-M?wzRt`fiOxkpOV46!Sp!Yj<~yh8aIw@kOy@xRu{EtTn;%L z<=lVqMeRhV!-eNr8a5vMCAIz~wN|&(vCcb>Q(KNNGCwb~HwEUE7sRnc)mu|TR=y~X zU2QhpK|?WQXP4mj_hONB+iezpq($2=$v2;T^sK93bk|<-ndUJ72hlH%AM_y)!yXBi5rr3@Kjq>qt=oidwGB!%--rUBN{n-Ycsg-# z#QPGF8ZJKtcX(MGe1m0sr3{utqa3d8S10UiDv{1~idyrD&~SScPt;gaYqqo9%-&(} z3RMvglWi8V;@6^^$F#oZ2DuWu-RFX~>SP%to$lg7;jhGw|na? znm3(O)*s&giTCQ9WlGwkbHeGaA;-9qIP2%%NEN3 z!q-g>MJ!5Huw*9U^Lj9-GsZ}tsIBpqMKlYi7c=fe2~1=sg4g@GQ~3`vyX@ZHr{wo&pYs`S zU3))t>Q~#_3cAAsY|wN3pkQ^Swu-KPeS+^1!q{QQvv|7t)p$$MAURJ!wFSX|Fx~ih zMMFTJ25Ku36R|OfK4!@jWXsm~ib-p{AgkL?6C1{snweX_KzA8GMN8~^JAJNH^2VP~ z%i4wl&rraq*Y!S@M*g_^oD=|!OzYNI-xRN{PbPhxpFS&MPq$1C{;PBR`bNtCr}V!L z(l4v_R>3ho+r`okOaBUJqhIwWWWeHiyhlxPG6Yc+q;cg>3gFFMNHTl?dNx_)o0`n! zAL{Z8cPX>0h$RvfIViij3xtL*Q5^<;{bvX5{U`}~vJB2M-^emS|F}DVAPsGpY2Jb+ zqL}+g-b|!FM&R9f|%=^gldEKX*YldS$gTNPivCEWcXU|Lk?&QlOZP zH~U1mj=gy70^U}MQZNEXGX2(jIAAIOX6nq(7+96lkXyY?#EWYFgUmEqI<6jz^8gDA+%LlskdPUOgZyH_R zvDJNHQMP$Q_Lp$SQuigwmqo!BB94xZcKpVDspZRq*vw*I`(rPA9Wx5XFlph$G`ap zLXt3)`H`Mf_jYj7yN&b$s(z-xmu8~YR9pOXk_lKD^{sHe!)L- zw(>*HyZQe=-d32QX!Yv*Ak z+ia5^{0+(UH7!rDVpP0nnymw#&tVH`J5>;RnyQwrMKF6|tVh}%sj_n6*RX-ImZ_VPa|J5YF0f7Bo4Om)qH-j zwP!Z*Zpo_@hQd6Bd(*ql8YGu2<(&eXA_KhWJU9-B6x0j_Xpcdak>; z9_M<2Yd6>1Ttjax&ne{^$8{OkY_12mUg7$LD?}&zHrE2K#au1CyNcg!T>WR2XJU;E zE5N~bz%czO)QG*w`Zs9reFhI1y005De0`(KURg|i%+Pu(x;d)J`@kd*L~F7JFpdLA z6~6uqwf|L9FGyr(v@xPvniF5r9BP*|8-i&=W@f!_jn+IkPLP}xa&aQw*+|U*+d36< z^lqSt#t(V|wBEeDX}52gLSyM3MBfz(*U$8amW?136DUnq>PGa+@yCDvJMr^_ zk7X1@e)RwSc-2E+I6O#S`0ph?u(n2<-ofh=loyGrivKbG_KO!wd_g-)7XX9@lL=|tn$;RLQNr2q1t9r)YzRcy|#JZ?8 zw*H6s+eaeCf^{`uA0^m+{OxrSTBz}ViNF0>!f%29UfyDepz6Z#_dS9WLAI)-yDVD3x8NoYeyut;!p4e|oa= zqk*###e8eqPIe!(MJwKz#XQ3<(>Y_TvlRL5@0Xq`{Pzw1%(!>h#s5Y*{Ek1r+ZOj} zvIPcj8%AxVx}6eM*BB2HLqdxsd6JBurs*amPij2n|Em}8U`}W=z?tJOu>6^taEgtbYHop#t!k@?+ZPfitMP_mtUUcttq6r{t1-C{6C1tFTscsF zzaLgl#oz32koG&)93$InUCcXcnD>(TS42c$MzYKF8!syl9z(|bbDVR>7*_37)yi%V zig_=S%*N}(0sLPyOswLK>z2sAS?AkUD6kp{QDRNTScza)hoF@czC5#w0Ck{h#?P>g zqF@9JS_qfdqcCGFpJ<+s<&R-Ezm}Tg`|1sIPJt*E^43~0C|EdIre;gU^4ta}S@78} zs!9b39#(>DNZ_Er82RRyYCYO;;Ldfau7~|mlZ#7z{#kHcz(2vj6)BN@;8gfXhM^6M z#6Ge}n5rA>z*TIHK2inrH=k|N02WrQQbT@2LJ8O5O6BYXmN*&td6Hie^T!j-ep4(% z?EhyN;;&M1QiWFlz#M$O8{rg3ml3YQOowy)$qsS``(_vgz_~#M;C=b^>b0&W7XISN z7XD9xxnz@r-$(G5QZDol4uq>PMcMG(DbsE}&6fcUK2%w)u|={MMW;A?@QOzJm1fi5 zWzfdQVWpY*9?Kl7Dn=KC?p7cbI}L^mT3G672i~5JxJWYoh>*=c#iDfopis99h6&*w zGt)2f5{j($`b3^MMJ_Wd%~@|@#$Sm?H*-`M?7}Ga1JWju*Eqfe6Iizixr*%8{?q?U z`#;sy{xgI2Kf-VS4cYBaLfigI^|kFEl=NcEtF?_7OBdTV^y{C|2fD%l^$PM_SLAiD zNX!bnXmRz+Dp;g~@s6cnBJIL0b>=$DqHgL|Lf2>yyAeQBw*qs*!*=RsZT%dNaueIQ zh*mtgz+7ESg_5I-MYMB+elS}7Aav(j;vTmGu>4OMT8z5hr$zDMjuvKp7A+nip=hxW zsX7(_z|HC2w+K%vU_y7~4NT~==W~NYx3%c=eVWECoYyst)4a&W1+vq)(heJP+D(0K zQwICGymL0{Dc*fE-E+9}`#eW;5?8wCXy?T|6Z?9yd#>%AVAa{gSob`o^K_o;aah=EY%dG2i?h{$h+26A7n@MvI zS4P;W|1wwsKV%@LNXUBCmz!tHhurGqum%VMLZ6os0!NsgU# zX2?4dUbBl*6Hj4mqzjpiQaR}Z2bB-cjycqh1IQT)@7ER_;LuJyYP?&$Nr;?QISB9G zh7{VxXnL~34zr9jFm+x(Gx2Q=RtAs?!99j01)T8ZxvTX{iOscU`6iKVd<8s{6Av&v4>mfU6dDZ_@?Aq?t96viT6`*_8ZLeEy9yJ35Ndkt&aDE z?Xc;laX(O-EqFg&)DP>fIFg)Q5KCTPRFj-N%uE;~;pgb0ma2wR@ROjPYt1j-P_yDs z>tc?l@|Oy*cegFjZ%Bfhv)Yz_gkL1vBB{To#Fta`h<9m;!b094%V`k@Bw*St5oc{Z;>%W!Un{@5xJ{2#YQp{q{ht;7< zIBZ8WRJq-p1H(y2EJeg#Pii93N~cQQHGmlAwzDjjubkQc9O;98o!Ls+Af#BtwCz22 zxtK}|fC}lxRN7qaaLE%czJpK8AHZb>xJaAm19YpcEIZrElCMC>?!Cc$^6;x1(^`FH zFIU1*D#7jyPZds534{C+GWt-RD?us{`cSdeg`B?r>NE>4Rr|Kt`Ud@urW^pTDn-Zd zaP6^XYnwi>_deosFn2Tit^LAZu!6fE^s^UPXGB53b$H*=T_C!x#`ly*!<;+{Lql_> zE1_&_%-bFFjFm(mYk}^RRP7%5VO%0jnf{N7wjH6v4$aD(oNm$1Y+zA^I_qSmd2@8+ zo7F^gQ3EL!{5kNaDtf8BDx4nngTKPE>_^ghvpW*|kSaB)pIP-cNh17(TjM8I!_Ex= zfN4L$2SPmp9>yypf2tehgmU~&^0Nu*eAW{d^+Bh@fl+_C zm)}%i>hLy+wCu8|R-oNY2ZYA-mDkAOv2(CvNwfPn*?DHSIHqH~7U}Lg6d$Z_S2(m4p8s!Jp{hzxrF?U)vLYD;4U( z-#@}s(&{Vl56{5IwV0*+fzjmIe)M&vH#=gsN_SF?C69|AQiW4hk*tx7drMY=*9 zeO62j=+gzipsT*-UI)Lg;QzwG?=AR0?+O1y>X_ZUet*9r10VXw9I&4PV2KSvkSbjC zD8SC{32Z?ZFqYL$G(|4srOK#%n$+@UWgO;b%nU78c4bTs>Z*onj69!CR`c@z*&0jp zV+d9kKSBRa)xS#ptJc4B_3uKi%WQ-_W_MZw5ka}H-C1Dnpt%tV54BlW zujv=GnG2(~W&ZLTa6Z}Lyo!5s8Fg85IWOQu!;93oSIt7|VTnh^fCYp=5g`vI*(sbk zFoQNmk||_Iv~Opchc1VG22bmMjJ4$*23=Bnk zx%d*rS-%EXybEVo@n&Aeu_O?1a>+!%Nq7AVN|j`u1{DC>pm0bJ+kPJNUMxvJn?al)zK zc5_aFIZKK<>Mk$}qPd|?0?Lg;rRNxpGYcq*Z)?r3qC%GnIG42ST45~mmp-E@e6y%P z%Y0Npv#HMUyq7=kVr+(Gtcf)@fO?tQK!;@L$b0@x)4wT|sVfn>vt)h3)J3a@IXz=o zg55({4WdQSom;-ux^r`SB{O5oa7y9LDAFnGD=DoS#drh1XmxiKQAnCtt?Z>u45;>I zurRVC-n+&-2|+JaGCIs$ajdGdOGC%r8ey4et<*2x0J}PI6{XI24104}1hpT>LJz(Q z@qKhxA5B)>&GjJHBV3OqtDf>k7bmOcd!q-ZTgA-NZ4kL+q9K~Rd0w)rDb8?lPJx8W z{^rU@tkdsBBK1Z!`_PZ9&nmN+-nO2HXcWftldYuxp1@Um-6#K{{n#kS`$s*74 zIc+|@oat=)XieQ%Mk6j08DyxK$fjaasM1UW;eTumh0RaHKMdCHEPsLiD9%q z=e>)?qYsYQtk-jwi@|J+V>IF@$1$N^#qrg-9z*KrFeCN7zg9_1VQN~#&B$E%%j`5rp zIpn(U9Y~(h*tf}a+W9mMH)M*02K7}Ye$OHXh)UyjY_W+kZI=a?^IMc?Y)O!++@^}A zs^usS% za#L_mmd~4hj~&GICumU8@gR@pjqeG_N;9d3UvNa^t(1=0+@CH$eLK$LHy9f1uO#IK zzI{69LSLdGlC1o~>lI%=2CSYZ?H%5c(Hz^EGON{w9RIM>9)I|MuDYdmE|VFE{8H`2 zFbH*h=LNPv_WU~!cgCMG_G%&3p&-Y(dqO9HH{X zLqNR`sLH?a&Yg4|)*JFCD9J!(x~ZB|%@(TOSTp<^&54Y94kv} zs99!8Q{u|$0AqXH8|B=ia!UPjHd{-&#qTs%q{vWA2?qt`F1D)>mr$|}=5k!1vmBW{ zgrxIa!u~>_1ha?XYJZ9lkN&XE&K_hI7~X~Oxrc%!a2OFR*30#rlot+W(Dv%&%mNL+ zj8nEfdbCm&$Eu-*q0gLa4c7})-Prk-i(qed-PnC&>;@hzz}*cvp)Nd=QP^DgLhj8Fpa ztU7hlA~Pt3RHJimc~;(m+Zj65{5LVLlt#6kq9p0D2ciS4Hog7#LP5*(tIZSs8@8DN z^(h-{g1FQ67(oka8=g@D^(zuEO4#TPtId)x|7{DnQ-H>@8ta>K*f#)!1;#7}#A5kp z*UC-AdTQ6{k%Qze8!=t~>MN7Zbwqpdr2gr5zW;k4zvj4epc5;(bkNmyFhi8P(F}PU z3`^M7%q|R!GXJu|yV_j9gY*_hY`M>G0~llI0)DJviRf=#QYd`h#K}=2OfGIwGE+F& z7kT+@=lV)q)ydi;w^_D@WYwQxrDWCfu=l=iV!upQwcAzcs`U(lxABNme$|`Fs=xE| zPp+L@2;Qo`$*K@P?6a>L&UJ)&VWQ+O1NM-uZ)iBh0#b9Etz^}oT^(!MgDO_NX6_|< zG<6=OuUDc$Rd3ovgKGYnNt8Apvl@jybh7k^UrnMObC;`5mt1gBS9SgQ)8YEe?%u|w zav?40xOb~{exP5u`CFf!-#Px!bvpK|yCmhXTd^_J{0yJ%1OW!NY~t)a>qct4>W|g9>_hWJF}rxC z%FcVo%{IAq`0Us*x|HLMHE5S@^2Qd7%6kH+L@?m+v{%gRLzN$avflhjWp6mONUU@m_y4H?d#i%G{(LHiD^HMAa1epmA!! zm*mf~=~;Q!ZBV??L5kv4Pk4P9*%2JG-9W|Q7B#;eDXDy{#x$>{&g_{dv4AeL*<4~f zhLoy`%~q1ePp|aGum)Cm4~SP|g^qgXO;avgqB(1m9q;y0|3P2tHZXc)iaSv`tC+rw z0g)b`GZHyd|A~&n+>Rp&tN|v+B09b}U0aXpQ|uEjtMWimz0h?s>yd7ndVK)xJ7CNz z!)hJi^TbiAH@CaYz1(`|6-brUdArl?!Ykd2W(q?tx?HhPF3%i~ms!$Kc}10|MvOew zBMP#dTBF`SS{lI7>^{dtoSLzMQ=A;yw1J3e3Vl}GKRjVPGP)QND3S>>Z(&!3mY$Q(Kawe zEH*pY>%60?B^SGoSF_N}+n+-*ngq?OT1W?>I2d3I&A^Eh-WXQ8sx~BV{;WEg0RMz& zu+p5%ERiUbQ_}BnCo}mVA6V450oCGoSg>haIN5wEIdd#?W)`@Ma=nb(xEl9YeAU$~tNZsrr=r0OU4+npYD z^Jno=lRn8(cN&S7oFaN~9t`)UFI1PBm!a+?$lZCKbhHaQ?M(IzU`KF@)T=G-71M82 zvvuaEf7ld9km5~0#blRaFw2&e$*U0xZ`zX%wSQ{3JPX#De~}{6a+bwm$gcaGCLIQ2 zj$SD>lO3L|ykGL6<)Ffsxi^=b?C{L2SUe8mZZNc3>)hoHqz+bB6csTOZ)R|`wDb~wOJ?d@%Hi=E_$|4L7af|kY1aZ; z2%~p2Im{X}oXCr^5qZjt5hm%NJSiv*4$2*>&5s1-yS(U}UY&{z*1_@>n-j;Fy)GD_ zWy?R9S~4z?8iHyWCkMr!r;JmS@eyS_*&Oh=P26A(RpOuN1ARujLgP4^YP8 z%GkgQ8XI+fl=(gcg??EQI*@PgP6*^1?(Acj5>26fU;7C_zH>%y4wJQ7zmf=o@A~tp zg_%6TVteE=`TJC9Mn(4f$R25_p?q`Rd1B6qQ>fW3yk&H%jVzv^FXK2o#4lj{`55#u@;}Bq=D5s)P^GDkyobXWu0}N4RoHbL* zpnY7l$RiS9{7{`@GFboiQ{=(}qV3@+qe#jQJMPMLSD?FM?vnL&?cvMdVYp{UJQis= zUbm?s3-48pm>;F+Fv-yc5^W>FW|UQke#}>M-nrWHrb!3s8*KX3Cd^9~6`1K`1hJkq znPmrSIe-An`!Yk3y@@6Vb$hc!=&%#(?8}IVxQxJ##A3`&@So_nz1p^UmA{vtN$PHl zq@kuJq1ku?E*S&OfPE#d$JR^IjgPeSbv<|>HCQ~1Waim()UYBkF>O5NnbQ!nrIpF) zMdsQKJ2l(f&p+!iHDvQWqSI;{jz36w|rZ^{xL* z89UycCyjS|iwuY6Tdq=3FMne!(0EmwX%xN1EnLYiTggt2)R2Cg56oe# zgEhomIG#3VGEt(2oV#2k%T}i|^7G|!fjrRAkAf7dr*e0qxxa9 z@i+ePh_VSWK2=C2NOOnr|jUW-JMIVt8^ho(71ey0c86HM4gNC3sCclI=ztInKF ztr4Q-E}&SslM3G;4{RH4i~90lyPE;o2Kl#b9YAUr{il71(GaUcP5YzHd86}2Me-8p zU89G|;2&yoyKBxWH_L7n1w&1;I7GeM8o)a`YV7pHu~pJ)Ed}4yC(vhi8WCHDAP>r; zoDF5h-X`vE>$t^c1=dOS#mu^B<8vDLb3#p*+fS>_fSdhRUT2;_%Tj^k?5D}DrDa~A zsfQG>aPgsSX%&w?j^UFQ*S@W=Ibwy&soo$YOdrYTNg?OWtdf4+V)F)aSz&Hwiipnh^D;4Wt=Gvqb0iJ)U+WcU1%Cay&aeBHs}w;@?6yt$gG4x)b9#a zh2sWy5X{Y))edk~86H%H0Egh!?o&ClMb|vS43&xVYZB=CR_o~4M2Plh>Xz==#k%K+50(} zToMiEtV8in<#+wX5!iQiM_=) z-8sDhVpZls}-z^(#74(Z@zu)*Jt|86JgK}ypu9xk@Fkdv`kAgU*XrQT~ z&WoJQ#k_L5%K94C47=dBzLD^`h^?p9Uzl=q*jeOgNTX^o9VB>$bO=nt+77G{bGSZw z=hsEO>$t9(R_$FkjlDXdCe7#YQ=YaY1FUV!I$J1Q7DS@2PvcJ0W4_`@jErex4`vy|=b=PMtb+>eQ)Ia;q#y z`|Yl@_t+qv391+mw+riO0sZSYL2YiL;_zT(E`N4AqcHljeaOBeeJORGgm9{}j z+qpB}Rf>K>7v|?ACXYzYXjnr0nA>p z5wqSi_;LSev*Iga&^@#Si-B?+yfaj9fNU-BMyWM@rB}XQ0#}lWebFZkcv7!lr2AxS zn~FBv=s1bK3rO<-hidzX7a>ex|H*)>LM_aw&{oy&?@OQe$I=uk!#Jp(9aIAN017uW z2e3?Kb5Shs=29t8e}HP%`aa4+>uOYq^C#`p2mj>Q>7cs7f52HTJIB8GOMyawY^$>n z9!>Pk4=>k5@kI|DP4h%-7JfvVQXR0U1!Yb3(!9@nWg!1Zoqv2F|NitQ`Gx-G`Itgo zilG{ht8WHMFx^4k#t7Up+8FJ*z`FneZs6RJk%R>i6m}heMUw+vJB50#EEeU(q=0Gv z*EIw1ffzSrulh}Z8+mm4p;3Y#(nnh9FX;3$Ot%|!R=FJZJL6~dRDao2TDFMnN0rih zI@}ZEeIO>n9qS+DJssmo!b`ZPPo9x&clo9`xJ_cz!0CFZdf*^6y(#vp>>lh}IdZcL zGT>Xp#+Nww{k*5!1}f|3JsshRm&(A}W9{$=zp7qTMf;fs1d9e|@b}4)f~rJaI|4fI zzgXxzAJmQTivQzRlw-qt&1L2+M!_X9%LhkwDlNI~Q(< z>g@|nrjM@p0*I(K7#db@1ZVoH3=>W0jk_T(!hq%(+zb*zoekq+AcvnW~oCL2p*RZkMpoA2s~bgJEHm# z_)&Wy5-^yxQKJ%DLWBhJniZey9IUvD^683qgD4dpP_h4|W=J=~xBhpa6Bw*`IHSLE z)0_6!fF#Xts{o?V;2LjZl&$nW6M1!Ww&0ye@YrwSAmJIUez6P6d4vqn6Nz#;9am2R zV$LCBBXrm0qASnrx|GUPn8~1zk3u_5;(PKKM_EP>ahhhQvVWQ(*@8VP*uOJJnD}7@ z@F~VqZaLFZwZbqrWX47T^Jft0rUX z6O1hb^yApFEqjnHV0+@-NR2Kk<&wzhHY5;zM zO`~g`Q?5NPgpt}?+~YK^hQQs}WsVp%y07MiHK?4DsX!QhjFHi!u@W~!&2#v&Pc?56 zqrubOS>=ck_4i#u`;M-E-I;71K+mIzmyX%SlZaNrJ;~k$J;LYp7t1zrY=#-@jg^dT zK}#}1^Blqc!&cm^MEivDLZG1*3=hS>Ufqyrj%UEj)iIn2aMBi+Dtzs|09U`lch5)C zX2hg#@#J9gv!h$!wuTNv_n>L^nTf_W^=A+)Q*-y_s1Kz;CLK?NccGTd1mo6UfE3=V zg=uI)Ql1aE(Y~ox3?UA=V(5fNmblC1Xva6vE^xb{(_a5AYVe+l@hlbGA7TMGbMbUz z$&Y}<+kgiK3WZkFgMJ3Jnd#vOyU+;jYa`Ys4Q=QA=($Qw>mg&r_A16mQZxr{>;U@V z-qjOB0>Z=>-4RKd*c6wLyI{#AFuR=^kZ;T~^-8akjas#w1aMrDXeaMOSY)<(QdI|C z^;>IE^-x{)c6bG_+~tx2?y_{Xy|&wDCMjKHcl8@&;6y_gC27j>BzD9m59f!1+hq z)U?&}0~SBG;L4~R?+0;M#pigBx1EEK`weY9d1`QXq1zt1ZCj_Ra=-i|i(QOFS8R*8W1a#hs(4F&EWySdiUHDf#g&#)>FEOga{tm3{DG3HTM6v8=eZ(xI?IRPJ;%6q zPmKB!>hg!#cMDrgv8P756U_b!aL1;`N<^ae{KWYWD%ydMJGevP}ISlbkODpAidCAZP{5J{e|c$&kgLP30g9^jBSD+ z#Y2~%ctB5S|11n@%rRRSD@>2ev&Hka^p8ED{p)rO&tg(u_3r!xt>NXisWiZ3Lbd9)+Z^3&!Z>2!`_1R?znkNKFVm{9B2`zc{Ll2&=#J z)}sa569>%EUKEz1JIGE8Y1Q%;sHsmh^QXBe*`$;MTRVGmjA8(CB&W&&UH})=L%oRb zT){n?ZONKwxteH0)o1ZSwCEQ=wBed)YvA^$4tCYk#Q{_x+FA;zi2hDtE$__Mgm?~H zO#V22i5{fCym>2KTya)}n)hy4Q+l+3nYA_}2Q(FD*ewm!C01!H9Sln#0XrY4uv%|`sbJ}V)DF4^r;$k z&OqJNl`}x-tC()MVjxZ3L%qkN5f{$P_Ar9NbD;z0%0lOQz)pt;wfI)6B{aiss!=!T zjH)Z)MZ;i1c!BaF6gQTpRB8*M@UMQBehc@2PQdo5VOE&)0@JA0ddm>G4VcB-D}2yS7bPdnogo?a9Qv*5KYl1aQ~af{c->fi+;Ag*Cm zAX%FDNa=2Fr~VEdAI0ouqP_(D7JHFr%qctR2|rfA`^FEy4^$7flks7*I^`7?9u)3($nY% zg(ZEHQ864HgRu|wyG|{*SkwN|LTl`|Grugx7jhwbgEIpyRUAMOo+F&Xi03xQ1l1l` zHkWlliEzexDR+RNB9|EF7%tHCglcQzkpMhAaJ$I0tAj}ztUQ86cT&5$+x(OkgsX+M zbO6eO7L*v5*m!8NkgJDttTt1e0pIKW&xG%G3^UR>1inlYn1NFQ@a^cQK|UX!OuGGF z!}pJbrtmeJAKGXjIWdIt!~6Y@HChwFCpKY*Tb}_lB(+5s`C?arZ`J;|X3WqZ+=1?$ zMP~Rjv`0yhucyjYQF~ep`Jvu1H#>8nyzKJ zST=!C0&8#e>3RPne(8Sknf6qgI^XToeAIYCh%R{489rDHIX}c{`c_ty8b8l_V+szz9+!ELHd>9EtGy+Z`bfS zvCHtk<>MdXo5AP6c4)aBJfp5K0YmTuXgCxEN7QKyp&(#~@fHeLvI$s>Y$=IgYA^GN zeacOoO-%9hy*2P5_IIn9fPhN@W-OQ;)o`J?1&qTIA#(9M_0vU~9N0MlUw?%+A%~2tTlkIfSISvgyatWF z*4+RdCMzsDuf;|g2KB}0M|^;n2R4XlOvYVJgqq_ZJ3yGttwUDPT|jQ!RId*hT^jZZ>{083%+k=|9lGQy$w+z_$aI> ztpVgX8$OM3t>E)^pZ|={Q09^Gqk6Z3&zF5d@!5g5*6@iA;?rL6i4MUhAp{@S+3>lf zHGB?T@SpLyg?R*@gx2t}HNhwREcje1TE6hx2tbcHA_N~7makU-6r2s8DY#v%MFH3K zzrbgO-NMJ!tCjv4eL-md48dD#{d1eC!$Q8@0q9{34Z)`vYf}rKNoT|75ybgy5uYmw zYb)c&ntwm&E%-3_P+^BGGgE{-fi*HZa1_0rvCPBaLrleL4Zya#^{n%7dB4F<^tA9<+r4#sp6(UOqRa3WWYOtO@cCeJ0G}#!IH%xd2yMS3 zh|pQ*;cww)ZSiSygq|YUL4<<%^apZDCdUNj<;y{u$T=pI&Fd=NkCJnd4_7I)YPhv;HZ>!pXwttn={vcCF(x zpf!B{*3H6adP3{?+}J&|f3Ct?YyI=!^#ObyMn`xXqMPHh9P1eipR>-xuVACFwf?z* zV7D}WzCPc=XVrPF-xd)l^+k3q0o z!l!cppX#oy%2Wy>Bn z-vk40h)@G&SYWi|g`v&UvSE+is^(_4t1L5CV99t!`{^yTf9yO>2Hk!=-gGCnU`}(& z?UAjuU)$V#W9?4_{dG2UZ2|u#?aw%S`!GCdhlQ5#|Ih8Gx6uBvu1)aA+gb3BI!pVt z&CNqC;2+-t{!QASarXAHZQnZn|GEA27TP}+-vocWodtjJcdPB!Ha9=Dfd9EI;NPVE z8E0=FW53n*ulmpJr?=4lv2&Z?kGHenPbZRA`5zXYz|fNi%YSxr7eSk0oW$n}qu*QK z*1drKOLsvIU=!q8ctrKIix)m@NATvw2b^k2P^pu|r?)e_b+|XBcZMNi5dLoR@e|w% z>iRIO#gTvvR_8t?uomBT;)HBLm?8VxsJBj@u$;EE3GaqYIYyWf_*B6?j&= z04KLZ0?uoRfJa<#AS-bj8L1l?#72smH}XEH5NyQdy*CM0rm+>z1L{Iu$wBzmR5*1d3eReQSxMjk%Dt#W zNQNl4f@A$L!SOYg?5|7ynI(TljZJWLw9tGUn|FuYE2f@AbrqMO9`xe`)B}=DVRg@& z)dc|g8IXxPnUKt6GwAOVaoH!kas0@o|2J3zLv1AFp6VcdT!57!Y{15e#aj4Z*j={Pt7uTTh?!^sBhA%L>t?;7G$@Rd;xK-{Fm9s$X) zK%vG*xYEp+81Q^^s8#LZ!F44oriqw=0jhu$Zi>b3D39Z-SKfepsch>kuSKRmdB1KO ziHkYo?*R-O8zNm(u{UZgVZOh_WA_x7lwk|dR#F5IG7UL~D_h^t40^vr6)LwF8$~^x z;Pw{oARdSiqoG1aqsNRprSkC`;}*Ye}?%7pZPr=B=dJY z^ZT0slE;dfvmh;gAN(kyl;3~OA)R{U2?l7kTjp;)D;i5Fg z!biZurGgJ*wj^nfvfN}Im4VNPU9EaZVm{oMRw9{frSWJ%_0f=ZCuCP>$iBTFko5;- z^Zf!Z^EHXhX_z zfXEb7Li|yO?ePzBnD-Sa zOGgK!ji9u69AC)8w$lEPTiyqfK^i-rTt4q2kbv8_B;8%ec5DkyMK#(=! z>Zfja9Hm?uL?=O9O5A+0u>`RIAXbDUG$B}KBt8(xAZ#l@8yufUfHavA4Lw6L5Zr3O zMz4}0OuWU;DO0c|w|sbgYFNX;)Ub!Y#a$Zy)Udbl`+)hJjx?sXIg}dK6My_3jlWCr z*AsvF__MS`eO^_f^)U#=y7B@5tX8(uGr19+*VbHnXW>dO`Y?m!;#CU&3LIW7%X$|V zTOpDVZn#1~p}qLSzTK!pU>U>dt^ngS8twAoc)yhkK^IP*DqE&RTrZqvdjQ8wAutAV ze&9*g24tCzU-%Q=m{^1djN%({#>cbDa7 z#@pvv0vw3+Y^T>B@H>DLv+K$xe~iuMyt4b(t%rCIYuqEposzuwmq#F?uQC1rj}xxD z4_*~Gs|-1#91=8p z59G8{Y$IHDCc|ZCGF)~h!)0eCUW>mQ`M?0l)A>-u|B6u-y_2;B@rUt)-pNAmWUWQV zDf~6yF9v@J_)GGhX!JxHSG%Rp(YwhARh)#s#7tB)P;G0@J{?UE1c*GO`9 zs&oc|kQsZ#)h^GLb=W{az;Z)QWS3>(jzaP4%Q{dt`CWAJb_Cg4=WN_9U3rC(RZeNt zh0eHk_B1_9KfD)SK^?8P)OlvV#|KztkC-i32^pt(=l?VhSRLsY+WGD_()sMqCdZcb zdB3C4(!-FxzJh&J$LkY;9Qi?~?+!`-RMN?%Oy`KQ;$`b&>a!9Ll-tQRYjh!(5j`=| zVw<>3BTcB6Y2572D#cabhtXNdnYK(gaMnw-oqi}AypJ~ralkn#b;4J&7(_-Pn#S{1 zJ>W$d#3Nh{zz>TcEY{v9G!ap7S#A2RWS^c$=5X)YY`8B$tc9}trRal2d1ZGllJV+Uw;sz7YrJ0Jy?;p1xIop4?44N2e=pRUpNA5 z=;R#lhe@{5Z?KTiD`z7=j>CIJ6#CG3I zbvn`-*>8oLT~s1*LiIsk&i{I`+K7jgA0+++FPG4VTV%-3N|b0pcHJ91#9v6CcL?E8 z$wx5H;{yiuti)lqP9=$pSRYsu;8Tj?|! zO7u79g6QkoVfo_S1Y)=0yn~<*OEqyo?L<-z)Rq`1i#L;+q_QZG{@olI`X9#!=AUN% zcMnAf-4T`xD_c0PXS=3jftp^$GaxMZ0uQ1V95a+tkBSW6@r=y$?uWlOKi$*^WT95isv@OPz9TKu6~bmR@wX>(u_OR zx*rd;j^W{H^+G1efhY$7P!3w>IQ@1b@;xGsLp_0S9XVlv5OUT}pPRvgNltd)T7_0l zD_HZ%LyZZt_s5y0|Mue{AG!r!{-TidPuGW*=l(EHXi=7^ z#?u-MBl;h|<4(O4guXJj@L_Sn&@`RakEo-U(@@dC5yjXr>S#XRr*3!ou4;6pe>As0 zMGBZ(HtG?tI9K+4u!WTOYl1&Ut;M?(-P)=nH2P76gNZ0&Dghb=`bI*hcd~flhIX8z zJkk6OG)zy(REcL7+dLLX3EB;;O^-3jE?@f;FSc5$}5j$ z{7ws1o^jMu2qrq0YshwL@)g2G3-P4~zaaD>cq?1JdQxF&up{)h9TCAWv@(9j&4|WW zQCx=_8NZ{AsI<0JcgH2N?B~j+Yx|eWy9H;3HaT32Pc4E)-1gu_Xc{!k)43n;(?XbNNf!q@P8h#fx2&LcFDgS@y*VEY&{o2ac|2h5Y5MBpV4W*w0 zdhh>=emIdCnNqpQaE=toEAyMlhwDxX9aZtY9l?BxZdE}i17mQ2Vr^kOvmp?rku#E^ z8A3u*hSIO-gei{p86T;XVEfrTs*^Fyq9X473=+vA=&$oNK|kZK1xRy(Hhw7tRd)sn z`YWDQTM!y%6pNswuQZ`|R+>z)!SQ2u`iA2gXz%*9B&qS8gbF{1N3|$LKvt^;;^0yG zUR!Cc(EJh3aB8kj1XtKf-j?qO6o{Eqy@peD#&2aA)4hkHpxyZ<#=r&{qvoc|A-g+t z47oBfD>;sCiEwv^M7|bsq=-Fvj@qySjh1EL4GvVu5H1;TOl@qj&hVtpfVWCFPF6p> z3XO}^#N~UG&uU-oX^a|AZ&LkpoGbwqAZJ1+H(^gOtN#$mgp1H9ejuUFR7cG9)5?Y> zMDkojGTPOYp_)MR2b{+J#vl=^vs*!|lQwDn9+PBH$r1XSN9P@8t+08(7?=k@wsIoU zTW={xQ}(Nc_wo)^Pb?vX#}{Fw&W7~I^^yD(XDekN zX5vViS>IN*ZXBYk$O$N|yl_XaKwqu|D+s;4Q;iV}rSrtI$Kemr!`(xlxhtg=RBp1w zstnB}4LjZFw}pH-mI4OR5@L?(wvt4Vfp>{)6d?Y~G&GFv>J5d9@sn#*Uz{(*hax`z z3Dm>$t^Qf6*XP3EV`qZFX@iBtxB<`VqAx54zr#1?DK#JCfCKmuAC}nzmHJFdozGI= z>r#DL>M&{x85T|{Rin1zl#CocRnKLSAfTNoxJ&{Er4P>wz+cdgO4W*^!UGs)hT_r& z1pAb~lXR3XTglVXbo}KDdGP>)x&yaCQM94P59K#lo8a!*onNqi{K4Io)_V*P5S7S$ z@QaXPAR|)AS5#c1-q2sW=Ak2z4IUP_JWCxKK=OGmWS=?IlBJ|LuA)(QE$0*3)+1jZ zvcs#zi1z00`?CJG^lcn%G;gYZ`8SR0ekadq;xILD9V5$Qt;10`h3x0hZjB>APO>C! z@7e0^29&zOoSAk%5ylc`n;PMvwckCEc@SW0tGheWF9@c0lXTnTxI@j~P5{-eP64d| zgLe`*KUw4$p@=a>SD1!U0s9z%|Gb3O(iSHVD{# zsuX8}&=~lkgMbZtDUPo1QiDbbb9thR|jFOi*XVYe*YHFp&E-r(|# z7u^BL?%g~ch8|v~8<6a-fb9d)A(^LqIJ04T0MQH8lKZ(M7E&){^1pC{ls?_60}wAR zj*7sN&sM@EErKK_V?sELN6Ha|!-3#W*_wk57D}*!ECcqK--)|Izv#(9T_dvOuzYv} zC1uO6R&~EwWVx+G=GvaiIQS{-J+=*z*d%{{4YJlR!+*;8A=3^pt)osO-*6vgo9c_R zKlr6U{I2h@#tNDvMY`=(BmT%@IKO)<@A1H>kWhRj^+K;0-=sTz3mkrIG~vD*40go# z!xWDu3O8`;^8LTEiOw7D#E);mC5UOnj`1xhP@8tkB$0UA1z{-Xi%r3Us@)?qgz*VZ zFt%6reVkTmRg!TG_Y%}8JATs0+IJ-hni{pOcF z{DNT8a??|$KN=*)Y=Tb3oKvmt`9UTUXJ8^h6E$k8{yKmRfDbZ}xYRQ;k+|an!Ywr< zumk6mWYzy6Qi0)-;{L!VQ(@xDtp$aN=j-IEr(|HFZu&`(MKDvblQAHsdaVxbOe?{g zo_5%Lxb+^GsXC8(g1lO~O?H|uEyOp9&_WQwbsw(Z0V_-g4&3@JQlI_~1mITk z=)Z(tHcy38@d3Nl7rPhF>Zx7Wv?Hh2AB71C@pR>899%<}15+_rU4fSs z&{Tv9o?r#nvjPTtss9Hm$TvQQkiTUCk@{&=TOyv}Ue z7kx08xWh~wi9`_S3rVR_ubtGi5H7iqAU5Ej4M$}^_2*9n$uDmKjC(YUzu;ND4cII0 zC5)YwbHRumSQPaim6gSE;GBMB)b^QNI&)96=7W5fA7==)pwd zXV(2D>&`>nyu@)4UU2(7!GVHicQJ5ht-5Cxn}U#1&#@-@llkAuH_jo>i#6#XB$2yL z)k^08aSwCSW1xO7{sZFoNzNKI(u7;6eJQJNPna=4lk`<_%x&3biam@rt(ux7Zb|YCNjas`>4{F|VqZrJ_(EEFBz$Y0F{gt?jnnj4?fqsEJ! z=sZ&PmP^Fg(#O@f$>ps=?I$DV9Hh8QmJKhe)v0D3^5~0>W8ujCMwG1k#9$B-NlIf7 zl>clpaMeea1`nae2n*Uk_!FFXaCe1&mj_lB%=+r?U(xwgZ5aRH?l>4oO5st3cLbC} zj}OJGM?3C0%i8!6uyxeKH&MwIY#tjd*z|3Jjb28YBA&|x;={1#k^8Y@;6!QQQd(KO z2Neo~_+?EWXR40N>rI+cj$^vg>(W4^Kfyx{xXfhGy(&%~x695#ow}li3EM$x&iYYn z^&+f}iuNYew~C3Vs<{~`s7hP(lZho-gOc(CHXtP)_;JFMs6MY1e!CK=R16S_659vQ z>fd!>-G{({{%m#eM^G?)vCmHix`+{tuyI?`J0a{exk_TXfvePGx}sCaRKfiO2$g+! zR!_4c>J-)(@NXA)OpF0czHY9kd2=X-6X^AX8t5YnY}Knf;Y>&)3BsVLBX{R|O%X)0M`@+V+jalOXG zgJ+cr+RF?H8vDk0)e>OFf#@){)IW;7mwzHJ_*{Q@5FadIfnOPKrVKc6NcdI4#gjco zsP{e=+C9M*Z;)v+Hj*uV2uRpiZk)a^yDM6>28)P|Jl^nXT#Y4pP5~J)S#@b34AgvW zCHDg$%LI9|K&*Rh&$pHQ44SB$4oFLOX-Nzy zvK5E;S9^6!HKd$(0bEiiqI|gfYItZRgz5VlRKbH%I!Q{e5gLz6BAibwL;?X_Dj$J~ z0az9n5;Sx%46B^g<<`DC9VJKa=?I6%GQ>8@7*>`&jNzaW-jO$+`X)MzjFGZgUY0#l zB_n(vio@h2ifr#Z!vO;UR9Ww#NXMenk@Tlv#ZIZYi-he5>DluENnEF1dj`N^&`A{j zK#Ii@!VidNG=bN}6_G|C9Tct*iv|sExU&zpltB#p#vj0#=~@1HaXR0oJ9G(>f705SVSMMRRdR(rtqi{ee3d% zg#Y?o5B_ThWfxM#dmZ@i${KKd9FfZ-y^bIc6OSSyHYUdx0W0hEG!jV`+Qv1e zP7Bqv>d$^&bID3cgMCdD;>p!OYCBdFwvrV{$TWDT8~j{+`P)^`7!68_nhH=TXMj${ z6&kg*lYrVxpj^TApbX{*)dryIGA3{LBl=L*c7ML=PaG~1%|H4alm<;^v*6H>f>@r# zsl`$83> zi}7t2zKOj6b828shXoSi;S}mpe`hJ!;}#H}c`V=9H3VE0-(o(YxW99GI zi&obzLRRdik`8FkJ;OI4g6wi1*Ti_gjys)9l%=~WU5w9`H5z#S_Js^>h$quRjr~A` zbF5QKF&#wMZ~3`K zeYcDD0`!2>z*?MEa=1(`BG}%|4(PPvKNB#(oA#drT9ZM90WhDK0u5FY8}BAb>oUcHj&t_kv=9ze=;s594{M+s7*QM_GHgXR*(rJ5;OJ zg>tr%*~kcN3djdlJP&j--1e}{lF0NnJ_r}+*`!*PE+7fvt#LBkW2*>@<1)8aJ@PDr zQ^8OW8~8ME6-r{AX14ExRlxZ^nvzaV7bxgqC7{?%P`Hs`f%5L3sH>oI??(~d1E(Mq zvbL-9&<-jsn87*zW0i_Zu^H!h;&EowZMBkig(ks@!T4~`QdsF5bOX` z)14j%qfaUBHp08sbkn)ci}Q_-B2Eh+?(2msah-#2)WLD4%DYXixlk04NkNr2a?U|j zvsvU)-nEcRHa+FX;aPpM#ae+(_l;Sr6058kf0AAhfuk6H4jaa6$sJxo@{ggUjL*&KvjKW{%6@JHU}d`%*`^b}=`4^0 zgXA~UDd+c4>?DC_L`MY6V!fWWNqVFYdd`{z7Xm}&L{I5S@Le)r7hyq4FyH%RZQ#hC3#lvdWemvX%uTTV+cmZ!ce!)3{P zaBKjfHNBfJd4Z6n#iL$_?2O5nwwAolqVyR{-jLpC9?vwvTnRt)sZg7{h(}z!HfN`M z6b5R)ATZ}@U^+D!pzz@ws@K}TU4@2w?8UGYm!cjrG&!)BVt1QL?>4m)lDb?ZGy8-> z3Hs$3R#zFHCRB&_2~=|1w|ev(nKR~NqOMjC;e~9U$Cv9oGFK#XuIMHc1C^<%Xs*fP zJ1}i9^*0#hLx2HmP0_9%ps&1GM6=G9-l}2I0>YsM1e9cg>tJ`|KD}FUKqE5|s%{&4 z4RRy1_oCyCqaH&K+aAMiAS=FM6J@|y$^a?mVinN!Eh*rl6o@&=!A0Gc5do{!-f~!& z&1wjI_1jEGDXUHmv;;CEKze^n+{)|}aclPmMI3hPLAadj2}h7Tm>K!&%Q58>0&J z_7>X2N{$~f#R{xCemNF|k?zZo6AM82(yAc{9EGhqy&SwuSCXugy6Pmnp{njk@*cve zspmmF6i?N8jv!7GisKD=j#2F~#yWJ;9-V|YBz>lnTsrAporE_eZPZBxI%$ng!W)ua z)=86e(nC54Z%8t9QlU z<0e1lwE1dD68)PA+fst~d_t|(F^Svl3J71>K`Y|LW$+beZ)F<4a75dUUkpD`^Vp=` zRH|^|fyu3;V)Rb^&0LyclMzxuE%_RQ7xC)FGGE7_!t?M2n?q?&ClX&-%IH0*vP-$aDJWVf^Q9;Y^)67CJPQW$MX&lRoMEYYVNt(V zb;B*|5M1}EPCE6|kkrHK_Y;zOlltWuDcj?3!Lmxh?S^F??86UG9MAFG@-nw&x2c}+ zW5CDW%<$DyWM;75{rZ@^Zd3Q+m7Iiblvv8(nqcpOW%T;)&`x0yk&V{+?!mTfeXsh%wf~d#UAYVN zRx8c=td0F-?WrXiZ>rjRt(c17dJbq@o9J_;Q_T5J-ToLUvlm0slcq+Li~9S53+nG+ zN>!Y%$FsU(y=jAt!jc*nt*xlwfWvfYR!eS3CY>SI(Y-aOtdp9IfLEcJD#8u}+~M*S zo40i4`ly)BTy5OvNDK*2Cz!XYCgWK-KpB`nDrlO3{v4$q0ZHJ`&&^`>%L>wv&hFLf_J^WC0n(G4hjk@{SUBHGURZk`@lt|zoSvRBT{2d=H2aSFDqe$$w zD(7;X_h?Tt7N}8DMQ#G8i>>aqYEVd8_>-i-Hn8yR`;O8L0nzCvi1E$IOt{QIGo;T3%jkU_-O*sy0V&t zf-o=QxSmd5_g!`17Mw<%LXTPhCwka_h4E{fCKb>y7-U5o_wa{%%1F}_S_Wg z$vF1k?&a)1GysK=>?#j3K?M8_9DqsvSZguuiysG=7HYF)72HQW?fPz2sP5{E8_;90 zM1ik6s7_>InQr0d%q|PVhaCL@d#|}>cRe}M>MpxlhVo8W>GK|VMZkQep44By$)L>wdvQuF(O=qK$0D*j zH;-S8rKWW|{$ZqmchwYr23V>2*mjO}dhd^k^0dh}?u_$C<{5rxT8~6eGHn-dyJ)1_ z#ZiymzMmmOsaDOtUhgk)zrK}V2SwVOz|Zx)GeHnus_nj+jVj906uKtuORL)_^hP z3XH(2ng}YmGR$_Jvo_ua?VH6CvYO9%IoI2RO~{D9~x9)*q`%^uhhk&Z76jC zemQE-m){2HrRD_23);D*0IY2#2k;;>)gC->2Lg4%3WdHQn-!`J*fRj#^gXv!XTO7T zL1ncNs68*J!CXP9ddJ;FqZ$_pE_p&=AlTBwT zpo-~>-tjV3QAwCEM*3;E?xKWO0tusZLNDF3Q-TSJIwAT!jstde24)>dH zAy_S`%i>Nju1ktA8pI7o8+2~R-RYoKuM-ttSO`?P&zIjp@1xfOB20eo7#166b8PhyUyoezCkz) zp(RNw5>vpO`Its_sS(gsIgQ~wXX6HXTfOH(b`|-C^m-I9M=4*dF%l#=2c!YL#ecPf zDg;5;Sb_jnrjF~(K=DnO44{st1E_ldDVgA^4i)qlP+I{c z^&UD3p&Pi)5T_%~@-Cw{q^sw4<$lDP|2)^L^K`wHsLeNSD(Zcf^HhbBy}~@kgprRZuU{J6+VXuL(lgXs+T; z!0z`-z3{r|4Ykw%nz~HUwdqws?L`(os0+JTxCWK7x2#dr9mW0Ezy_s$&Y}`nqmDmBtxsGuhH_4W zc;3P#1;*EV+P2W$+~|3Z5rg0lgy}p=+TP^v%xuSU`Mn0`ZLl#2dPv95vh3L)kL8GF z+S^TgwtbV(L+sgTcR`M|#PC3ef`PUpCN5;YzR<7sp)f}9}5AydGdOzASvB-fR zN)%wCUGsa}Qm__CS;d|zplqMSQCBE3Ca`m>K73jDX7+G&`eat^i_OKes(l5WP9as# z!_?|Ioz2B;9RA3b$ZW458%H;#vGB%GFcCrS1(3NdHJ{x5)e>C#cBi^tR}#rers_(* zybP7x(!7$tq7uw?pStwmc%H=(|4kR)j3SnVS$#8i$CX}I2L+ONpbAofTj@k z@EHx^21|e0{l4^jrq9L0S$2TNI5EE14>v=TA`|_4S(FX|rA@3a>-=Irqw2d6u|1N2 z3n{V!Wvoyi@L8+_Z~()NMAh5Cv<-t?;NW8_{B5tcm!r4B%>4^p|CKG(&s?Z~Xw&*< z>-rJMG)%q!hcoKe`q9z%^!W3|{<_J;=$A6V$g)5D%gkZyqfP9}>uA5pjZvfYL!26> z9}?66{a^=9acJ6E-iIyUhM;E%mtyM_iH(9d{MqrBj6Vnd3aT=a!G(xtnyP;skwgW< z7S;+aFM{!gb1gtVdi@F&+Swpoq-Qe>krtl zs#W%hq?#U}PGq3bq~o>tR+fSj`!J7$)-<(wP1l6fw0lCZCYr@*T~Qmyv8uU1e?BaF zp>>_tyskDOb^RfvuGe*4G0LOsf-; zss~S|m`2KOfw?f)ht}2OV~5G8k?t+a9frV!Ww@Do?8vg*k=S7?%T2{*T3N2c7(1yf z7b1@nhMp#z4xS%s)8T_Mr(@HxofmE|yV_xnJ~L(a_jue1Y`pRlFR~a3}>>lS$-KL;ka5GgT#qJ;=~|vVvslss+@X|IQ1ZL${?}E zhouh%=POx-^x7cIiW9fo2g2$WK4?eK7hepOi*9L6G|Y7;Hw5#HE8%1szg?%&8IE#! zhMA*8=YThMrMnld$(3~MJ0Lf+U14UMtg}fxfskx3nAy6U*)Bsioaf6+TWGhHe21=e zmM_BpoYY}&UMo7hM7;t)3(T^!-;~eGPB6Q{vPrgwXzk8@VjS zn_b7gb#44E(lzrVn=Ab|ENs5`qq$sI*Qj1*g|DIx-}opE0u$m*0Js`Q2sD@>=7;B{ z&x5~r?1Ysl>x<9c-kVkA+cLLh+TM;zRXby7K3jNmj&Yhf=af1%2m0cdn61VAgWxY5 z?OmAM=pGu1@5`^q9Njn5xRT&KF+`K}0jbhyd#(yzMa>SZ7ILzlPX2CT)!j^=F}19? z^`_{8495`!M512E;aQcD04%XyX>`Nfw;&;8G?@BiP~SFd`mkJT%Hg@R!#vZBX#oQR zGN7F+eTO?n^_6iyfT9B$Y;KGz{bxi+u~||DP4ROa`U9UEuA$&sfYL4KZ9!DzsqAVU zcfL!9f!g9w=2 zuSc4gO={I&j#1cTLl#wfx|+}hL=ARE%BEmgPl31s+(B`p1&Ik@%lhs^@0dMt+zFF_ zkz*HFgK%b>aMlh6oEMvLCK1jH191KgX(pU)L*R_@cMd{UHrs-$HOhw4Peg|QZ2>LM zXopBq;-0gQ!mS%9^LqwIjktonbeXnRoshwvD+j^QBrb})fR`G?D}A%0ydgF+{BFeu$(enovUla;qe?} zpVN0=Vq<>V%`vu;VyK!qMh=uO?ETEd3qB{;#9!spoi&`TZ*i!wn`6{Y; zwo=-EnO$;RVt#y8K2p&(6WTzFMeefYlE97F5;N<pEXlh(O(z3=&IbcPCu_{nmSj^uJ*D&T?B>yo;&Asx04c`h(_TBqqw55K zS~dJ11mu7;w+7$f*RxuZaxo!~OUN^>wv#3DF(vlr4vzzYMcG0s*ZAPeWGD{oQ-mGo z76&|38h848GiNICLrOBUVJAVZ;kK)XGAMuCNG0G{tnU(lvHE>?F+s+jmZ5PWs>PU3 zQ}EScd#uVoG=;0;=qH3BU%nU&`5_1dhMa?E6}w8W%y}RiEA#g1MsO}A-mPA8(>8Tu zu0FAUt^C%hJp9ra3>hQ)*KZ{*0_NPlBg58T0t=Q}wNe^OV`HX)J(`WJ1`x9PE|^yT zJ7Qj|**aq!Gv1}4`YZ_<=La(0<{R^pss@lv2Z%NMfBdmGr#M{8rpCpUfFM*BFqdin zUuVv@Ws8tU^+QMMLRh;uErD~K`$i=Pt3mYEi!Tp(7x}`S&^TVyFrmDd^}X{KsXoUD z=gsc>w7kOp1}wtHDUmD=imJ4kaki4n^b=&vKs*V3!Iq^bwHS$0xgan)-fq8^t%dAuJ;{TpBg1Kf>g)e&9b8$Y{# zBeR0>iUK>5g%miG)B-dQv7+Wm$HN$kJ+ChyRfPF>X*uJG2PYm8j-j>GR`O4L_eVk# zrjnJg2kg>fLYRJUV^zHb~oBE>2DRN^aYlb~e>;c#_y9Of}zF?a<*u1C1J%cGl z4zLiUJYsRmpwzKYW#|DGcB5U*%J`1{eiKUlA{qdwap2g18&?Q7B^f zlSQ}B(Bet2urlJrVpyxzo1d>lZb*UEsFk^|adG0(_XtpCOsz&W>Wxfxr2u>$KhVc=30jViG>d-1!;|=Z{Q>@RSI9lxG&*2Cm`8%TC*mly9KzkE zZWW{vU(vFxach&Z69CC(agF-pOClQku-5p66kBh}ypdy^qaMEkVy&##KS8oEKM_@P zIe#Fh|9%M1AJo78DC6a}M2wf~kqhI+iD&iMie>_Hz+=dWDZEgh;7@;7+@Rc`Y@O=VU*c#vQOW`?*lbBw(6~i|fd)?|*-QI5(qCFl(MSDB&tY)FTiXuYUM>%vJey=#B z^SsGCF6OxnAGB$+y?WwNb0gHOJt!{4z8#mzX@_hc6Y3vRh#J)QuW3!~C<$ADFR1h= zTq3}dVVopHf!b?)my=cm?P(yS2A&|+`sgQ!wFLcCMFli#^j`3W-Iv`DZ>8y_+S{E_SIv;7P{z0`ChFSp{qb%a^fU4*L;B{ zG+jT^S!XgHEgzIWNHHBoS!+Hh=mOukpj%MCA>ZH=*@2%b`3di-rs{!5Ox#+4L1>st zs2}mMDDnoPc8L!Sf%hCkx3=-Ytsu;*C_1SV=^(nwle{9|S4$=X3KzLxNJIuoSk%PidG(xOj>ePX1Qy;7h z6s|JM>!O#KMORDuIjS*32+@fRsUz}YD|ruzPGhsPakIA}=7B=?=yrVif5#E~a9IOq z@SmXz`4h}RK>NO*zC|2J9II*$){R(zebO7Fc@sWh#D9rrb?-80JC8{|YdlvyqPI(I z6HkE;j#8v-zK6U|4f-Rp49@GWMIE?$0ZXaEz?nN7whkHlL4ByrD>BN>{fxC}R_|w= ze%-YG$IolBpRxO8tv`A1NeFAcpYajOgzRUGLuIhA$bQDyIcMxQV11Y%s+S3v-p`oV zQvF~a66KDj_5adK>X-eDpYA@Rey#6aWY*`49cW>6A@YI%L3;<(H+@Y94z@ecl=}H4 zK~f0J%>~?1p+r&l8~{SE4CX;)4;Htc!)oQ%r*;BZb(58R0_VQ3(htR z&Td}t9JAmPRzWNQq+qEoc=_LHtf^6#v7k(p?i8|^X9mFe;{c8Q`DU%{B?V`@iXgxz z=ml+^T7X#Sc}6}u949fd4#06!so~#oiCP@${S6&a)x~~85pUTpO>MODt4Z?o=E4pkN8uhsn z)Mc+zM(-7gPzGjEo-fhCWf=~9@m#8Ie^|gRVD5>yd?0o(fxR0@UViuaX7$f2u7nkF`Jj_;7z*;cHE@Cf0Vj^bUg4CR{w#>6Il_|6vNQ%oh7iJHX zc6mQUKhuta0EZnw0=4^Nt>HwVHflw|`%$1FU~`d|ZWvu8Kh`u*)a+{RW>FSAH>4ra zRzm&GsA@#GBsaWmLhHU)>h`={{}QsO&q}2$dY%u?=|R|iv1=0083!M-IOlHPm=)?$ z^o@UhzHuH`O^7tHV#o0tM?WEWRq;9?%o| z5OCh1val12Pw`SC&I@77afeElkDh$S<8yH{z{wrtiZt>T43K}-4{>U(en?Qy=?90} z{Tad(h-no}x#K)74|lwTk&NRV^xM=YS9xGx`)}gP6g@$6>tv!CKYaVMS_{xV09RP; zrdjPKTkZC<+Px{X-RsPDuS2_N2%GyDWbl{PCgQoe@_hOm@6`KAp3C!%0$R~9L^4aH zU+zR55|a-7(hkom5B()-Qh|)*Pdy%Svz@hC6)b-Ye8%eUd|_@(=^-czA1#>H>Sbm>v-Ii z{>gl7bk*3rJ(&S&Ya#Z*Xi0FmyoVaZm3uv%qo%oRckRpc&DfIZyZbANM}>QPa(wxx znNXSUo995A0Jkz`n(bekr`b+^FwOSKCj3_a;vFtXQ1vX_PKE1&T56#(v;`}RF02cMg0mf&b=r1U`iHg$5%CRk z4eXj+06RFB6y~H?&h0-fI6lFlF5kHuG4wez<FUd%RlG-?AU>e#*?9 zgARtf&(TkFz?F-d zlT`}dy$z0qqg0x%`lHUMn&xM~xf{>Q*|h2vtyGQq@hv%+q#QUZueD4ZV-QJKO&M08 zvUvs?+C%SI@=HU?x$>Bc2~EdMRxeyCHV$XG7a#=gz|99BatCe$IpZ(SQqpUS7WHZh5g#v6FCeHimh;01 z^=b{ZgHXQ?Y${6dfh;s;kva)1{6$CQ;Cw`$Zv&U@2MAN;@o^;(Z+}e@5TE$NQCnYxd)Mq?Cb!zhIxuHCP zg$e-BveQuF!HKf5u}!^rF`y=#-{P}oE{q?Hc`(;db)|-|Eg|H6T^RD;oC6520)(N= z^(>gM{w364@|XKUGM39{unSD)0-LFMt4ylg6Ue*BR{AY6(Xx*XVV%E5ZR^HQ2LKsP ztyJDCbXts-E5>OkCKHNkKqmt;FEL6kKvrD|M^Dsk4StWC%vX22?iz^S*%J!_%qpS4gqe57n)fOOH|1mPq@-ZC~4oUSc-hmAciD1lf%*_6|5$lkTA+Ac1 z#ot*crtD@l(Ly1>Oad z!rUG3Qy69|rAScIlF7Q6T3=(14CBbh`kk!ao z^yWG=6Yar@XB?za6$$(4SefvL>RQwWFmh>Sj%_S}(vk>AfjAi)>358W5|jNgm{0tX z`NofAiTiFP^tI|&{N_yE4SCeQBjpk8LzJ)I{|QPSN`*v+FOYfHyw*`fk+~nsv%cDt zchL$FMaFSo(fge5>8Ag0h#mFAU~9HdRX@*{ev3eR71|~jyQ~9303L75Ia)x9N z$Ylp|i!z|dr_Zls-4rFZlAS1+erjPqb*FA)A=`LQq+?GAtERHsb0FeOIY29y1EVRP~AnWj+3y2GB<^z%ba|BQ%1@*kW9Yh z)d^66rIm}Nm9{efavFwBO;5uz_maxy#A_?zHSXp?d2eI1r$5I=?fpj^ZEwdc`pUNG zcte+?lvX(w(TT@JM%z13ndp zG;UwU0Jkx~xndp)@N&APiHq=*X;ecfQul{0Go}FZ5XO&A!lAspsg*D(Uks(#pKpC` zQlfky4rw1Qt-NQj+UAxaAd3J3pIOn zyBR$;br(i(mYGYh=uS(qnop5C3YQ}V zw2njX;Iz@v#V_LB4%cbw^^h?x3WVv#;Y{E3Mywz+agrKe;YE$m%j~#GIJ9HKg{q5C z%-sREjh4sY33u>9R>Y`_r&1(QxFZ@sG{rRrjMie*APf*Pb2O2HsRor5(hci3Aj_8m zl=7sgm2-t`54Q!`I%u+`;8{Hja)M$qdPJ`O06Nyc6~#s{jK=mihY<5{dJp=LbGV|T)-BuKtbGJdH)dg z{TzYxbL6bxgbmqM#!|ncHtE}f*}gH4t1Oo4C~)Q_PKRq1Jg$C5P$D7HucEwhDAuaq zAqhlfc~nTR>l#Mj!^EV%+rN2=l-aw@vk#qPujG?$S+n z3!&aZ1r=!;pF&nvgGQQkX*bsO6>^Zt|EX`aE!n{m@Tr)D)iZ`BDfNL8Wrcx9_8^y^ z=1U||Td7qqArUDEON47FQI=Mg!hq7k-~?J}q51;FG8IixkHNAEgI!YLK=ZMB&ZZ3@8KfWX81Bz5L8u{!1+|*ze zb?lsOr|fh?x`C*mh@hUlbhV4MC(7(1il+1Z|7$1ueJ8t zYp=cb+H040*2Q_6H;d<)VGM0k=OLdBbu{%obTpP2^3cwE7d7@MUoaYL*i|!yz4t|d zMe{X_F2=KZ2CUP=O4hIkz_EZ{dU=vuqJ*p1Gy-*^`a^ABpSl?@p~6xa!GpiaJU5D> zf?q-gir~Z(egikCb!LCK@)79u{v^!h@_VT7q&9ZOM#h2&R7{4Rva8AG$AKv9mE9qj ze%=n4F434S!?XGw6lhFw$>c*S3z#~M+KNEm;AX@wtFiDdFrY>+6l&Gm*RVfp)xc}< zSM0c9fZ|-oJb9eil2#r@eTm&9znH+~>t)dFi#AZp!=lsnoR!8U?3yuwugOvih()A%ae_(isA5Fc{A#??Vw>2E)% zE-@eB-5`4E?B?Ig@SD4`-S`UMv2@b5!E2Z_ds11nx7G>MLgVez> zDrjTTF@a=~Vbvic%sMNrI$vR14T&Qbc&4m0QFS5|ebHPUVZ z%CP`F3P8?aRd&Yl`R{T-U2!Ix&cO~$e7_?2TGL%A1^v(xSu)zC7WU)k(GHwv_Tn*P zPeFU9|GG%zPx;JatdX4`&75{zsODgy`oK%1ToZ%FRc(n$_E3<`ldJg{i)Q>OmfuTB zt&Gd9s@-xuS`$&y`~nEDcZler2ldAzAOIgt#>$dqo2teZAt(FKT6~l!vTf>pv*t(m z=+ZT5LxDWN1=16#q(og|%QeSAz2(q{+USDN7;?C#@IP3KaqKNM<5Z?egQMZL!U`4x zdz%^}*P3D5tSwYhOjLOFyT=geknPZ%d{osw+%GUol9U7~lH&pgP=snLDq9DE0WZ=1vdf|_g=(!z77g+~K89G?i8f}M%@&x^+q zOhG)S;d7uP1Ir0&FhJ=Qh4*`i`ov}^7XymPA1F7EF#-E#Q0Kx|vI)EbVC~i_z(!b& zs_#RK68T8+H*f)<^T+%6fm)81$h?S@a;QR9?8mgOR-u$yOM}JSh5bcrnF)E#_`HBg z%IsjkYR1O_?zP0n1iYMp2NS2sU(hX92*J0l=mG&%!_g9T#uf5co03?>-R5i%MVb5xMKQ0#-H-z=i!lCl zg)TB0MesUbhOi8ccEj|SOYlYQ2ivW#Ou`GR8&MMZYoTjQkzll_DW4Br6%vU_j8b3R zTdz;9IT?vtO(eE}H$Z};h=73cy-tn9T6_Ur=GeN-EKe_j2mu!+$|;h0L`G2&zNB(~ zc40fZ(6)lEHY`HI^zkR^`O!y$BaBDBWB1G91-M`KsCg#rDBz5RYJ!YtGqV`Xgr6M8 zIVLFR_aUU7J{L}4njdQ0S>!}#8V}8kD7jM8@TQdCrmhAf&$|p<*h?>i3d;u zZNfC877_Z<9NQ|8FEELu(=Id1-+;Hy;6`_FgNLc4Y|HzIY}Bb!PA496Y9J>Cd)>C; zNutN0hPazG8b8cwog z7G>)#Si8+2v}9{A5Doao5NVYIo!nB-*ot=x^T96JY&r)~FlhbHO;(6CI$1*?TQ?WSS++)vAjq zV&Q|SlW6Fn;lI*J*qjQgmwIW*UJDJ2h{GbF1Ev6_S`~jK+-dq1m;RhSX^M@xTrb5v%&W;H`aTo zxm`Z& za*eNZv5AGpiQM6^6WS!moZiHMC-}L^VoMhtwnvn`M49%-55}|l2U2yzmiEIF%oG^v zFmeG0_CO`Ljd7+Y_-0)-n^j-aRU=t-hOXMYrg|TBIT9;Rg|I&Y7^bvv0^DhypC?QPC#h2>^C}W* zUUW()UB3Z!%C_qI|6u)Yx<2-Fb*J3K>J0dxD^N_2QuZ)i3$X0!)HgRbYJ}F^C@g%E z0Jm#^;|Z_=4S~pJgc1mm+X~3Tcke{!fUmG$KKU~-8!Od2_w|Gdf$tqjvg*{5TTS4T zH1Ht=zDEOZ`UAjkZVmh`pdWy>hkk*SiiWRKS7@dTBLe|4iSf^ZIA6TEF>hguswS@AmhBAXtb_03~O3xvbm=93|=!hWJsk3gBB&+J4 z-=T6~e0VU(plTZK5mi%!qG76rszv^HQapqm1=V;~;*w8Jnj5wLJRIZX*>mN=_`~TL zQN);`Fi)L)(mC+hXQ8AnZNqOwT(iIjOa)a|k4Bl_v`eXug#AQ*KUdB_NVhc{))Ci(a?7%alKX^A{r!}v2v^Bc0UV(CMKLubef8x!c zPxZ|@Ii5R>AI7%@PZ;Kpzp5p?ks4kPR;$ZA8D26!v^U}T<9k>XM4>Eb4$T!(?#sDC zH}XB<+>1HIWgCB}#$lnH_Nxhx=aa0B78#S!#(7TTbLx?aZsT@1q~X7F8wFS&;($_E ze3aYpF9QT)r+NYDQmM2U$PC5RMRh#|np|Id=k0GEZ=w}etqxyGLj!@`$j$;g+_=z* z+*j{7xgUzoMoa9^i5v=f41coI9(veK2h0ZcmNo7;=t{ASidfVXf#uM>?MtENBP#JL zL4LummS6S=9Z+iXtVe!R(TZxrUFL|<`GDd%3o;*&en37T{eXNxcyN|>2PpLNwu9(w zqeeob0$1L9I2g)r>5>_1IV!=VGh06-sKNT7 zr%J_xv-DC;=l8z|o$8MH43^fBU>au&-{Jy`e?a*(zl$OE^}pI9RA-`${%@~qRYkyH zh^TVJF`lBz5zQXj{%9phG=%vi9R*$!L?qKrcX%|j=`o&?x5mf(V?>p7Ff!vxa^j54=#rdhoSwwZj#wD+ zfso%rAOR>e@%@f9@sCVc0g!7L#hSaHP_x99@wp(#3 zFfTohns^}U(EeDg>wuxp>OoegE<{ya4Lx@nf>_(^MO6RdOI|5cs45gZ6f@h5uF5>h{Pb_FXg&+3H4 zAeXTFeN7z-kh-N#{QzKXA{vV{EtZC0|0d8(=qc+|ZgMy%jyKOVyLlbEh5qv2(BH;P zJI=DFVj*8VM}lr`#g{`H_>M=F^+vIEk7LUA80EH6+d1X0gdOkCj0{Xh5m)-v`QF~D zwjFgmCq!E@^@zB2s?}Y;;L^&`vA(8A+wz|Q$TNAUF*nZF)Xw$*6Q!zi)^I_k{g@Sa z!3@1UoKQuWn?72N7p0<+5c2SW11$`;grIED8HkOea+$&GHDgU z$||f=Z}Y* zUp&7teu6&1@#c(hk>wE%?GrLngwfHrg#`HCUrBP!_&r2c6ycZJc^jKD_=y1(8~77y z1nd8+gaN-RFyLv;fPdgwT?NL7Pl0g_PpH3vAIRTH_A$K4;V}wl+1||=I5@H(Q|?q? zmwibtOs@84!+z?5n+_Ky(9u#wnxSheYv;>It3JQQf6c4pduP!N&p1Jpdg)}KuOaI*>K5iO0INVIQ$ao z0Jqf7lmpmdV6Nb#?3t{fVLtkSn!VOp%8+@Lk6XiZaD(?Q3vJ}r7Hk(}W9Y#RfCX@l zLp;-`aCpJS84cS-vRg>BN;1A<;AO#q`s*cswf7Ba!(lrxNw(LdU*;*;z)S?q0V_m6ndnqN=<@3pIq(A*z1jk z*1V8W6Br5lK!^yGxEgn1Cs6g|_*oFA&-CltTnGs(Qsl`1iYd((@(I5=|Dj{NNuVCf zRixEP0a+@4s>y#7&!!NbKxAUh9i+%4D{=A+)-TXO$KS%TD2>x{Or-MI7@@Kl*;E|!e z3S+hG1;R%DAUvzBxz zslFONgtwaN5&TKMg6eG}h3ehJ}Sh2Uy{ z@SYA#_wk_{)+M+FNaJl=LXDb*1+9S5ypeiSR?b?H9$`F?9NMiH%{mh> z)1b~ovrZRX=N1~tpQqvy2+Z?WsGCLzuQR^^ueX3d;I$3UY8v_=jMwjj^%k$2m%Nhe z{G=7ZbCRMFy3<@=gjUEFceK8z={;VX-9Jy(-0|I=4>JTN_nV@-jVAAD>cPX*i?p42 z;ujlM)#{4x{tPmjMICyU-;R)yo@C1;9?*T>thsb;B z%z11A>`?^WQ+YSHj+Nartbn&>$Zhkrs3C^5nE!4vnGt56Ho+ti@MQhe&;FPImSG{4ZP^P+Chi99h354nu*1_C#I}>kIu1 zMxoo$O8?Jg0u7{qA(XH3!J5s*_1!=Nz>DC6JENi#KEVL2-!3t;WOKZDWKQGrX4WR z!b1jQF4dN7HtW0+Dt)ynB}zRD3mKM28Z39L*5AP<&jTK1MS@d&dpxVI zIhMHI>>u%(x(QMZ!v=dh`j*%Z%7HaVLyRZ}-bp!&Lo<)KVc#F2F&;YBcR>qGyn{hk zmc0`dn%Dks?VVXSg!3C4Tp>Ee-nsHQ(#aG7SgLYqw|Z&|{PGc|A=VC*6M{w=!FmFi zar8K-CNQTXa+VtcVRjDt8(Im4p#$N3$OD7a57(QBh@pe9N}g_~Hr!jZuvcV3C)F5> zP%$QGqCE1Rx;UgXcj8X*z$U%~iwfQ8I4t!hesNoIR_YG59(Cw;;PGS$ID%{}fZxSg z`aRw#-_4XHx){6*q>6ccg(1~=r96^Na37J`^5{V@WP#&=zN22mh~Nm39ZbEzNyeLG ztuhZwUfgw&XeY~-4Yndq3WFwst*`q{@TpacZ-LMv&9>Yz$R(Q}+b3@0S_B`@NplTzM*Q)2-lhI`X%RVeY%eLYH_^)XnJ`@EW_~RGex(Paey-~a< z`DxmR6~TR+6RTm^ihcO0pjM~e!;2xS1qjv~;9i|t!&llMeA|5Wpp=5)Vk>^$e6@hD zv_ZJSd^Me~#2{QqIFtBO3_@_UPUZ5a7=$REi36HEck^;;43mt12g@L(v zfq5+WgWeK@x*nv4=@xu!AxL8U@k80d2(&=pqZ7*fc&(n)EesNvomJ<{t((_NG6H?^ za*^pBkF_l|k7gXX#p;Gh&E3!$V+^fsbqZbaY&BNXwfR%D`fp$(sbz$&B`Qg`%5^%T zvhK<;8x8yuFMKCX6byjZy60f{2*rh=H~rMYr$lq9_Yw~WD^#3sU!=q@U>r&C@C?*- zESu94-ZopY?q%65R5?;lo@sQ@Si!ZhXKGY$0(xan^)N%%5=WQO03h*220hxgqd0D5XbjRS-Qxfi$foI;l_P!eFrEF>{CIL}; zfsfe%9Z^{ST+43aG%*~nXupiqI|>0VSjd%*;7YGR34Zy9L*ygp&Ii4{q;kVukPq#D zZkP^a?3QpeTt|QY82b2i!Cd(H;ndeZ9Oi74w3nJ?97t4weBJmw%$QIyn_Swnp8_vH z1Ck7l#B~gC>Zd@{hiy5u+z+3!a^>Uc5wo63kBEbW@SpW;{cZier{?L2ltjG_Nn2k8Z}72>czwmCt2eaIB|fo?aZ>VQr5Pln!TSF z*+zwxx*rC)8*lwPM>#>PsG>I$^m~T>9+f@EYEF17v-vjrMjbH!}dtqS!T2FoNkJm(moY)A_u@+4Q*)Al3Dj2Hn8!Qxc zAVp>jm+uo$v;vfdQ}iV$Bt*-X`s8|1Is3*e-g{q(E5V7X!}$fP1;lS?zk3A z5RbQMG=m*YIMoj+gf%BV1ghKJ_)S~Qq2{e>G($%UE>hQL2%jGKH~91ptN7!u#j~0M z{>eRCGH8p{yWksaRkzEy7R!Xs3XnfdhligJXwvsTGe`;N_e<~_lwmwps|200Lmw=Z zgSpjkgNxqeF)9c71|v~2MR>K5cmo2|^!^4og?$n3958qXxPhKpb^K;A>Q>Bz^FrL^ z4QtgCmkSYFz_v1(0sQfg;#oZp;=+me6-0rE5{uRHm!?%uGsjx~SmCP27-pCJaREdQ zWBHk`;SYoLR(7^#(r`R0C*XrWIOyp0k9b-=B;YkUa5=(sGvHxG_c?e!2AA-$i<&yo zdg-;OX(<18UDVVWe~q2CRqI{8^=S<;WhB(?clB_t>yIbcjGupwmL7YU;Zv}}Va{s1 z3K0kvv{OuIT{JY?s!CraK)p{;D!%CmaNGB7>{cu|%DIFO4m{5T4%ppxs1jW|(q&wvNuX^eC#`xBiCQp32=g4?0> zULKJb=h)Q`iVb;QL@*DwIKz)<_U$7{?yxG9CH zjIMJTSJ}B?g?(pw&e1~ZXQ2)_-Rywwx&z?&b=p>yyM5(p4egz!>;`mh54YdlLmimD z8$7o?QmGNJ1A*j9t-tvMOe}xGzpoVDxQ%i%J(*GOHn!v%73vl0eJUkHk!aGmv(^Jt z=}y4X8c74>zko+%dyX&7C%=m{OvokV`%{jqLcEUPyidtGPt+uNkKM{2nxa^)ZvYavHNEPy)f1j^3D4|X(upp(=hTz=%541IrhrrLk02-qpK z9qC1afc*vwO8tD97O;3rzy?DSC8ZYC?9)j_EbH5le?2;IWGwDs8`wyby&i7-6c>b| z(20Fts0JW|5MNZ;7E&MT&Ygc!;4h%a6e6_n9;{n2!tP0NXu!9@}Zv4{ZPuiw6b#i$CkCevh+BR0-FfGv_$DRdVm|{K0?2SH_lvALw5i*k_*Aap&)1`(Zjej zxua?vpvN#K1xr0)4Cf7#_zCK|@CM{JWjVxyF!}KvjqAl>=qtxM2y@yfPXuMc}CQ(q|GX*5KJsFq7vNck+X-I!@8$gHlbz1))a&$F@Inl%Tv$6g0`lLw zSnWFgr=>yE&BxaLs>XjkktF{?O zX_~fPwOQK7%4gYLH|i{<{VOxdBb_4JjyL?wW#R|7DYgu^s3%|Lf@NfaOy|5om+PTaZ!b1|Ktn2Z0m9s2#*3&ou9kBlixfJLDWr0DgYDCN*HR!4xz z7F&%v{cMR+>Cc5Kt#gw6-eB1y`m1YPvA^47azU%~XsKwauU=Z1Aj>Fk!jVeheo z`Yy*L8$lmqF=fDFN(05pvy+$B2PU?9`zKjgXs5ZXC)x?7oVu`U(_0Fv6(^PYd`DBTR0LjIsM=om zez;Jdx`T5I#|z9eWE@~)>Y86sgEJdQNei6^cw5(4$BT}LPtr*(%|=UlDiwTKP@TYb z9xt|_L#0Nr_Oyx5_}2J1*X;ua&QgI=eJ~uOW?ARcN#m`v2F2YhEzetCYD1pesfT%| zq8@ug)usW`U60i@%k$1{=&o%8Tgr1EbRR|TKgjb)+zbHaBl1jsQl5WE|1a|VXyaeW z^GWm#$Zj=WfBZ)q^hK$+1f)4$zdujtdk-{OtshVNJ1Rh-A#`aP5%7Zilmo4MR3m7koHQg2Jkz|pm7q>#9 z2I$?c=i&HOPxrSJoH%KIhTv&|n#GB=5FE(|6PUSE94o#I$DAuvjs`Z7zy@hxV+m|@ z2$<~Pu5J^U$Iv-lJaFUSa8(}nAv{>U(0-QvTn`u2SP(CRR>!{-{7c5fEB!jZ$aw~RS)bx7IbCo!CvI5 zB%!4bX(`dPynt;S^$chX-wys6w1F70J+zp}W2kv+{%vo%G!l$V?UwiQP5ybkUOwBg#0SfH~!J4L3;-1X-JWbr#Puur>;9qW_x=mq&GF%Kp5$NuKW?fPS;+sJNqp|x_xf-}|!Fyr#F z{0pPAG1_1#tf-~7Ex23DH-@1cW0eD~NFD-)=-Vl9ON~GAo{jd1hB!vsBMpAy+xP{n z_J5?Y0<2*gowr4-8s5OiYJ3bM>UmUQqrG%NgLt6S3nmEM|6>+7a=)AcUqSa{3*uU> z@!iIk@b5i%hiEZ|d5HE0 z2qI8azu^8z;ASiS86~UaWbis7V_0Bgkdza*3mjh9VI9-dsm_l-r5jlZ#wK!LagRwdjr4zx4 z4q$x|uy&T-Mxv%L;87p4JzWOXNQZgQ)>8;AYaX;c4GqH-8_gIE^d0nJ$R!}ZDO901 z<`A;_b5NSeHofhN=?GwOApL1lfP3SC&+`x(XXzs1vrES>5=%qgF6P^Eyw&#^;QbuD zrv=X*3;dnsrSGVJ6J(PzbY4&N?%S7zw~q{j=J?AsnsSYOJg)Gsxq=B8hdBjXz>$z8 z^~GpL%}6D&d00kvS4swxF>rIIRONf&J#~qAFag14{2KQ0xDy{k{`Gq z556Ycs8+*PF*$YFjaXx#g@`0qM)jOa)rY+WwL5@L*^3%A8GjprvbIqQ{UesEQ$mOh z2S`cbRHG_Rr6;Z+O%-Y&{R!k{4J3y26=@*2r%HA+qg5RU*7Qlh7rGIaC~#LZXjGHj zXNH2@YBj!*w%Eutt^i{IaanX1|0tMnW6}bz;wKq#sg%E6$_qP$G2jWM<>v0TflZZc0(NT;`@Cu?Ynd?T{X)K~KF@t4X01x$isa`r>*`t>iM*y!2NiMnhB@jBa&O8S8A;lgR#@<166^fx5gfL$L8k}YOuyNxk3FzZ)LT5@eg*` z=rr5AJ^E+VBOk-fr-@*lT>+V3OOW|r%OMjpPPYUL>y_0ae+XS;_yl39XMQ<`w30A5 zlXU(4s8gnN{Wn>EpsrsQ8Z+}Ce1IUkONd^(7y1(TZ=@k`3QYBe8K4$N234jY%8{PN z+)zb;$%OdmBZ!xxm_K#$3+DCqo_(b0A&SjkdE+M zsHr!5N|)XLF<9Om-_d1P;90Hf)k;mpq7U>i{svrx$or1O6u%(|ZjMV?u-a9}bsU!qCTPR(Did-)fov-t!~V%3HEBQF6j0&F-u zI1z#xki|(HqHJXHPcnWxv=~qNhRoqf;OS}3b)uxYXhA;DoTlXR=v-riW44Fg4G#PPNeB)Bb$1t74TEul>u)HMhFE;SR4xhB_VG5%$} z3-_M64(}n`^IV7PnOe9ARa_xW%J==YxchZ*b*=zsVM$h~zK8di9 z^l<+;%?g~(+iJ$IOLx?%aq)VF7~GC3W>AnxS1?^4xQrU84zaA?;VEN}t@vArn7Xxx zXp*V#LzDDD4QP@-%AiSRCTdMWEg%NZN2iGL9>V6W=-|MG{1p};9Oxr2vI`fbi5a|P zA=`-3ZA7z;Il7INY@;*UD0>7A1a{#+5{4WzcO0=r9QTSiO-2DA`cAYjXy2F}ky7|wtNj8pp^)jNBkDsf(?WKM5UGlBa7TrKP_bQYoAvU(zk z^U}m&DR7hXg$?8UizRo1C*QJs**!~3j zsRsMbI)F_f*oV-tSZ1&n7lKypw9)2u$lc(R%rZwiU=ddk5A_*pVwdm4@%dYg%t5$i z&U+Csp~$)y6v@~oy)o}u!Q85{{)50c-sRaU~WSx^!U;DP`H4F{VeQ2;YCL~qi4K`c{d~C0~vVBiBv_u zj5#w1Nd0uPNo;nYZgwpp4Irea38@h!7afgdA7iDZ4~Rv#7&!Y;LPo0xj7e6GLDp!! z6i+a-($$9v!kCW$xhze$GJ>saMCl=|*l^&t+Z;$!!)|&K)U#rt2tiP?_SE1a8 z`2P3J=@DP!-}_tABi76BqpSG0LLyHlCSnv8)et znN11X4lrw0+2v;6lj_HyKFyFe>u-ZCr0aYCQ~l__s=p#sf8hVB{-{v>KOboWe@q8Q zfj>}hO?VS6yNzn=8$;J4AU59^*S zeG5IC+C_TSsDtP1F0};xAFlbsyY|jUb=S_lSa)p$@R6=vdueZU?MXe-q2MR6tk@&< ztqFTN#F5_~wrkqt!sa&R0|f3a__-7V7rod9u+f@JuK`k6{Sbd3UQIEmk73w$eVZUt zqpkyGMD?U@H~fAF!>Kuc>a6mY9og79nAeAll5p{H} zZ-TzE`gKtxV;M8FO}##y@`^IBfZCN~B@EwaixEM`_Bs>t4={i&Y@R|ZZBh_-yI}JS z#E;m#rR$uHQ2nxl9iWR#W1#Qbpgh_jCc{HE(z6^Q{>1$zoaq`)Kfv+lMgJv~kM5V& zA2VxRVq&ao!G8%C%t<`IU)OoqtP>eV1NxREg+Ocga z`{=gbFzc<7dbTCMu}=`zgFeA|k6XFV!$1i5pXG^|g^AA6Z)9*K zUb~h!)ToDXSCe#Ji{mk(k9%sbOA1)3p6(~=*rU(H;L=$v%-y~Pu@MD*l^qh`E*UP~ z)jnmBNMFIF+$)u0r^KrYQH~O!(N*hYZk&qehj9Wprol|r3_?wxneXkRetnl+dQb={ zVt48s1yBABISQg&#-UsuY(|)kF+9P^!?Rr6-(Jda?QOh-XfdkezM%y;Uo{#lsmC~# zYY%q;Jh~$gZ@;-9&XqnbxuCu8o|F^bf&8y6dm1K+tFUO=sD7>L1gqR9O+#+6gsf4= zA)Yvofa^e*bqa?`7=dx*6rDH==XLN|V&_6K8WFB@OTfm^8x<(;mL$uGF)5D-~-F)iQfFL zi`6)lW?+md=9t!mo~W$zNsgBs2?g!2jDi`@_`W1NOMI}FaErqviK3oo=4 z(}49=9ADIQ0uOUNuE`ZpG54Rh33uWZw~O9|tR~AB|M>}5j$49XFKQZ&nQ&nz?=_18 zJhI%7uqc46!V%sPzCffmoBwg}KN;}mdM{O}8nfQS>{X3f`D?%|Lt|F<44M?4-w%>8 ze6Ym1wo*(r{Rms_0GckvKcvV1-~aEw)NSK4UbXS|e~-ccW6h8$DH4YL$h%(--(SSK zzz06B}|1xk=)m%?4RIPS$&~WP@vHz=fXz028_$;m?Vf+mo zYf!hV;4eF=Us^~z>|5+ZU2WzZ&NJII_KN*+&{pBJ`&8sY3?p|e8k!{yy}_|?NbWru z*;Bo?;7{!7=uG#CqfvlbX*a)$K$zzv8qd(wa4eMpQMr{u6bJQDE-xPX8(t$eyr82T zc36d9i_#jLVX|7;C!&Uex#6_(< zPto*wjP;1NEF;<|l^mey87iqC%=pjV&HQ*$lZpuzq<+{=NbN&RzrqKQdKBWKHi81K z|3akpXhrJPAoVklI$s0$0+lR3|2hIFHUWf4-3i*mNJUhB43B=xfeYrGu@Fu;# zdlJ3pX#6dDX&jK=I_TzB^ve1v{Ei6lCPICGy3p@2W+NOVhz&emA_iyXkNjJRYpo$| z?SQtkly}4VU9+6VVW$yPqvQ@DnX)fNeo5igStNC!?$vECfz&6!0@0oAv6GA-=m1C$ zdqXK^$?ImmGmfZz`>vLfaBKUTn0(onC;J z99Y8|K3t0tR%9jL8SR2tf@h`#7E6iui@>GuLerZIi2)F}Mng&qFT}k-3sPDjO_y+l zm*70c62!(KSGgc;VOguT^j@G8^6^{X0R984UEz>EsNDs9X%s{4UUGMs+TDW!RJ-~3 z+HA<`;}PaH&MSZUG(Do*XXz1>@NWVBRpZ}}_!s|qdc^to=fS_}__rMY2I2i`{Nqse zFzQe)frdXmfyqcEjZGoYR`#AUic>$sXhYzWtK@09zB=`1mUkdVCQHn5v7l~^L06|= z-P2Zl9iBoNKBuZ{@8f(Xr>nC{hSCU5QSTiWrX5^^u#7Ru(1DG3QWapOIj*TQRo4h! z{{aZ?>ARtG*>SZ#Y{r zgBl7U7*5>yh*`R&xNP}bNL)ta>MaqM_H)C;7`LJdBkd$V(Aw@#3c^*qvr7RDTS}lJ9mk zW;<6xqPi!lUB{Y&{xP=&qA_6zM1Ra2KoY1L5)M5JT!4InAkhW{A?BYUc)ofIo^_OQ zDxBlMa++Y711zz`tX0Q&mK=LJYlRA~-nuB__>l_EOY!%b( zPT$XBU&%mEcp=ntt8jOf^qdDbfrad=U!K=JHy2;kLq|oFYVb}rAt32>cveq>x8b7n zBSbE+Q51iTif@DmeWI@UAZsp-06zZsRjircs^(hOG+49bhGfC!f|;B$tAiMnI@v$( z|IyGg360|t&~gZ^TPtWc5gK=vu&2hkVUb*eVJqeogJ(PJpNrLpO+r-TY5Qu5E3)Rh3bs%81 z@c|CsO@Z?Wwh&+e@y+MJL_59$>^pc?MIK#vK)HTo%GM3>G*rNsx*d28BKVu_G@#A$M zAC)%A&laA(z-+)^k)!ABhR+E~9ozGDYH&{utQIAkjd{#>GFd$irkOjpgS(nkT!SWX z#J1WZVGf(j&?L;na~KI}_^DDg2_w-cS(Bn3Y8Ot&&AfCL?xyEq+$Tyw8`UcvS8Q^Xyzz%fwR9j-bf8)qd8x*O&M;<;C9}H4hM1K`X1&1rkuj&U zz7d~$4oHz-b}fJ8$m)eypE9n?kM;!3O4icr9Z;>_`YVU#m6|X^}m3eL3gXw zM4&SUK-e11@;8j_qB(3NJ_!VP=qqE(Y|NqY5A&x#x+~5d%sw~drQP_HooeNZXP{PI zZpVQZKTYZ-UduljpU%F`tTZPdwg$yAMd?d-V{SwV&doTzbwtgGlUR~o$WqAh;ZK~d zArGd)8ZD4x5?Ddpfhjsr*u8Tfu5mwnkOSgc-M9EFREZigyS6Caq)8t|jIZxT)S5_E z%vL;m{Lxf9v(Y#sGtu~gCxxt`Powc2kwTUsmG;h#g9cn`KBIz6i~ht9b%je=;d!ZW zs;i_s&$wR%mW-D2+okSE^BHv?(2Xt9bsGwJC(#yqx-0l_qcX`(<6pGE0Y(=>C-I+DZY}E-@JA#T=^@pwUVH`jFDtW--pVS}Tk`LqgVUPacOYt0KUd(7=&#U-^%#kfe2H0M zK+G>T^v)Ld&L24%esjth!)#2nJHO5KM@K=*8&M!PwZdt8x4P)-4(^?ZRIGMY1fsHv z<08Fw6!-!K_@kh^+n*V9_bYeX-dOL7idlvC7+95hJ}d!MrjKx7CzDfq!IPONg@pAS zP>Iv|?2qnb>WL3f1$=zwF%hX#&^c<+2_}V49L9o1e5$T%TP$~9>WVhsX{-hnogzvD zno^yPHxR^uC~hhZr7nZ2h5AM3SLkLg)y;H(?og+p8B~a3g-^K73CIp%%#JQ>cc;rA zr?CD&c!zv^4Mvrg8{}B#4Q$^Tp3?N01FZ$M2|2dhM5ia2#Pv5i}&$os=4{`IHO^)Q76AGl7;-dM6&dIr70Ku5@fxutF$)Hg>&xV~T6!IaIIFL7lp z^v!^nT0FRnA^eT>udc(Fe9osJO-Wicu9d)UJ6_q|t-%1n9wA78Lc-jHQBvF^vf!M? z%1EL;No$!}?yCCZzr-K)<}q|TKy7a*SZ8XNsusG1C_2VX&@SKK+iT=9;+<%3ZkEe9 z-$h)E7`LEQ>&mE@6StCm6IG7q*@tlSs_+bSMK38vk<7x1#y9v#1oF}Oeu=#MckPV6 z0mrpqVdl9qj@ybwJZ00;I7}}~KJQUUk+j9Uw#Du?dLQH!$1&e_X5%%g0fvH*sdEF;1v1A>tm_#Kr3>_p!>aO+ws`P9Tou)moM@VqV4z zEx-rWKk45vVjktI^xg+42~TNAl@AGyEeR`(m@@?&71luozc-ag7rb&453q_khA|{FG^8Zr(N{xK z9l={8aWDQbKKtxyJftF%5BA0@-8+AA57^*7eAxLRgmadEk^l!C%b*WM`E(5 z$u)lGd{J>AN=8Hc>ww@a?$O12I{Bl2v@htA>(345_N&RYy-}ANwH4|EQ;~bXr*7O~ z0tDA+1fP6R81)uOU2sHLo&yN3j6=31cVN8p>K;2ySj19ORB@+IK1Vz5_3W*TPe64F zi-Ru?0Mu&#Wes|$2ECS``)SZ|D64hJHyq2THA4QzRK~K+J+raF5%V#gJyGRu{6vTT zQv>^LrQrD#f$hQ#jZlu@m#r&ATBj07!$33hg`E>6gW1Dl%-bpJ7ywSBSLQ7??PRwM z`Hzflv;)Us`yOxO$4L9zWiX89vp=qaE9*<}?OgL42SY#e`HawDxLPB&m>tbsmUJK& zG73chon-Ib*G?;&R`%ZR4%*&ZphsDR2AqyR>N`X)f-^6oL`!?mz?&BK-a=iu@&RGj zU{?Nzt~`}Rjrgni=YL}Fu{=9qk%oAuhIlz4jswIt>^+V@*&*>KX6n*2So&O)4zu@O z{SWq@$*<;kzH1|!S#_}4G=8nUW)(xTG0Hw!A=Gw3qiWqDVbwh-(UMj9c+-MaQ+4IX zb>*(CJYQEH!lFj}1^h!+ae0HWsl?k0)0iiJjXhZBxTE%nZ9Ety$*XA^WOf)n{Q(kV zmbNhlt!w8GU{-A%5#?Ta1A;pj-vvj{O0!BKhnxP z2%WF@YS_+FMRnj${5Mnwa_*=ZF|_W*Ep47i#VOj@Din%{P_~y%4BG35G<6)wY)D#F z=0ujj-#q@U0#f`b>rsm|`HT3P2{>^v6<^iC6DEB~?V)g<9??pvK~?so#3RKCd!{;X zz|Cb~9X#kyC#__y(>`I7wd%L+{7X!2#Xq4nPsy63$JwZV6lV3^oZ|D9|1lI|32Jv7 z^rH*3PR&J6p)$(u7Fj zCkNdFX-M_PeG+vI#mcAwz8%!-fYShHYb|4o94_p@stnkOLg8lsj|4?*gh&5t)Ps`m zQs-0T?;9;Z1)Z2c>!Gg@rxoX_T90kIpju<%vEpA#~ri9h9g${xl^Jhi1Qq1m;o>e^W~@mjn34ucD00=*xA&AVk1( z3us9%bXsWCJPWnsA30TB8oK7vdr#PS`RYXq5=QJU{g9?=@qolZdU)g-8>kxGn4d*c zAU+L?8_ekAP$^d3_>ft9qJBtIqw&ycy!WQ!LkD?*0Y;2W%`h9FZ^$N$KS>J5T~7?6 zZR(#wnfEytGJjKN9bhaHJcsIs*&EIDb<@y1h`;3jK_9UE5qCFTU9a)HsFr_a z2hQ%IjaIF`WKV1QfIIR4)~NxIL1;NVRn)LNXwg%NLlb9qar1nJZE1!D$Br8xl64nl zeQ}fU+iA>71}f0C9^-4crcX`%8K%%!P6JB{Hfh{beXl#}2#sCS1>aoXBw&dW!8PoE6yl$rRhM zEmOj(wX=<_mKsjmLicI_wW>am8@EkCI_t0@yX z0Z~pmtSTTzV~CRSwLU9jy={3{3?y4J80DT^@0ncV&e(qM*(;p}w(rWF1GZp6-q&?_ zuj|aX-8lb%kMqCdRvV{CCvJmt8DF@K;dy#hO{m-V@W_-4!(Y69Xj5rbp2|9uXaBNOu{i5sO*sJqo9GTnElTl^!ea^-= zwG^lU2O((R+QyyTwT~S^OWX*r^Gx369#H2oHrgiq{JU+Y;~?xjH-*NwaOy#q-vMcw zxfB1k+Q!!7dsgIHbd7C1L}}($lo=Zd37H9T!;QiTj=3e^e!u* zC|^yj4~I00Rb(VaQP8e$+RQ60}d5@i5Lm%&@fa842@O;|788B zk8bL%w6N4a7acMc%GF4QhoChmacDTGm0vL|hnzrv&Al@Hn%Dx5Gks!g!Eh*$Uub1P zz2)Q@xpucdJI`aZcNwR;jV@3&$y(o@{_GywW~V|hQV}?g>EDUdR?d>^V*?^uqhtNi zr$>#7&8S|$dqHPX)6c>TNFAJ~j&GrktWlrfz@2%!6Cy?7W<;us69t{XH+6J3?4Hgz zGJxap>bkdS*LZv78aR=U+h@0__u-;jQZBAzeRorha^b)p6>lD{YhrWe%6)RMh9PnGJOH<|(HCy>QLB z4)64R>u`0(Ag+;!`D3+m6~(`?2B_EYem-(xgj#bE(nNs~Mx8A?{#(4kx@4`(R`zX= zIlTLoW+Iy2#-ewlC<^YjWhbs@!5!YEESNawA`~2~3%PwNJ?GxHn`-)%qz=H)ZwqB~>0>^d_m z;w_}t)i1lH^Ij@O=W%)iDsSUi9p0lmkINTy9_}wfZ)#^|i^kBTZtvY+g&!WId(3wm z?L5XrH2Rsh1DkONzg73?hK7bUG?ERiXx-2k5T_Om>8rKJH^VQ~@bd`2KaUOIChD@QX`R2ApaIwuh#w|TmltLy@r06$bJAtE{1tus)}?gi`dFDx(|kslx3}3*$vu+ zMJY(0wFn9@xbUt^l~Y$A#_G@O>L-Y#+pNxaBCU^ySI2o5J6F;ZA@$I#FHvOj#hBy- zf;3;{URb**#8sw?2VxLUv?*B6sR)X7Qj)#lT#0*=XHQ1uU9r&G1c1U)1e-Fu)u*s# zo$LNddi^oC0xfenFt8CuI+o2Wn@130t2gK4Ld@LDi^9$qi2WaCzw1bm@dr%K9?{Vu zI9dijPht=?=_J{Gm=l6_Jgl7c|}x&uT0imq?h)TwMC+CD56hiMf{Dj7y}tqa9TI zqX-p?b;Wu-tJ7JLvl8T5q-7e!ic|CpvJ|EV0aH_GFB%Ir_E^X*X6pZ+q(9INZg904 za5-E93x976TWX3zmi{#Tc`J1-*d#ce?9cm2J#f=;9tQ!(fql6*#$!Y>?@f7W_LmL_q2@$G9EkqJbAcdey;Z$_$P$z`uEr{v)l=-2 z(sE%}%oBGoT_E<2xQ&#Vpx%rG`@xU25Qk2}MxR$1X8H?PHwc$-KOg*<#$NB)5cYpB z1g}c21jI;Bi8DdTzMb)~ZgQkOI0n1%3>wkYh1SD%prrClc-kKd10X{{dodJZ9uc^a zDo&6LhX-lsUUXTcp2fq>5A?ApnNZ)dP5L{pGx6W|V@v!U$czN}>&2%0F{kkluhOHf z7o{F1(^?XOGU^A<@+Tx+Ta{dvsUf0zjrbUHI!s@}$cTH_IcDia*hf;(nKs z8nvw@(3HPC@-IQx;*9}&UFmlt)|*_1O!23 z+HDE01Y6gUDZkkg9QNPv#(`Whv1-@%R)wGLHR0$AF0;bKP=%?ekf2^f1v%EPi_Ox- zj3VG;mGrH|4?#)&@GX3b{7`1nf*=>C+Pf|bIx zWM^q5no+BM3k{6$kw)!xS~>IsE94_@Aor zzl8V~fiBU?8vpGerxpHRVuommzZD-hNVkByPwTlp({NtkxW02X|H< zz#l9d;#FuE7{7+!&eEMMR+Y)A2i#2jhg3InAHMQ)_#mV_Sy_Y1zc=Mc_GfrY)l<6u zXsKVPX8s|*aPM^(OIUZM@IPs;bXS76FaF!p+lw{_uT{`@EWqJb8{oX>o#Haakd8hA zXk@Z;9sN}5E1*LA1%Qyg1P^I=fQvryt~pTEkku2v>jqEp6~;yv*fDh^s8>!%Myu|~ z#uL(k4oCyk9>oqUT9&yN#lCe&#vrEgtGF7wRBsyl%w=ft|;W92xT8%Fr zoC+&>BxyBSU@T9vqpNa_?R2^=!z(O3`8FAE8QFgjuX2q72T!FePb$JM=Q^3CQ6>dt z+y>IhX^)O^fECm5(m3HZu1CtjDIj~f?5((sT+AeL8*(*!1_y<1hL7|g5L;R{4BdA5 z2cPaK`5=jxJa~*CV=kt;(vg+RR?M@CZsR)GDm7|NFS53VA&;9c!YKnku;Nq#r%-a1 zAJ@{uoV70@JOid-oyxjJa~h|Z(5x$?(p#ujZxOk^68tM0)s9WaUw04W`lT9q@8<1)N z(?^GR9OjXvB2={a${J+3=4kGKt-_Sts151?3{Obc(%h);G+V$6Pt>u72=}5Oonp47 zv+&& zOR#J4c^NEunWnTniCHeDb}gj1-`#ffp6p7|;79i{Uyr=P@Ig9Iod96Q;m#2{SvDAR z9m!qIQV>y+&ybuv$^x4sG#4B3$7};a=%W7uA8Q9S35gz^#t9f9?Tix=wPGIViTZO_ za7hq}a~rudm>T#Ep%zeWj&UI`xt*Mw^o=##y6p=MH;M_o<@Dt^*xT$i=0X^ol!sjl z4hUB+4cA=bjud!Z?L4>J88?*sheZZ{L|J!w#GEwbD-f|f4~()h4!=Iv9-*45VIi+z z6aJWuAk;tNRh13VMphu+=IqX>#X;D&b>*M&-O7o4Co6xz$`o=`-Y1oxQn9)+vE;64 zPx*HU*`_+18;Kk75fLkBr3Uv+v#t#G&(G&z_i#x#BMH_3)Qq?g!pHi= z8)dB9ikA~c#zq`DduNmI?f^(GJIHb3kDq-P$o~**vB+=2NB@YYRL9Lt!G^K9Ml|wt zQxt(29F3AnGtJGLl_;c;Ep$~D@1n~}N)|&x6^ZN5+lyT&(Ll(8hg_K;s_}6WaEOl$ z@~F8;r=iJLY(xs5Asv(!YL7ejiT0paS^Fy2RYKmh3pEy0r~_YF(zfP{khImK0`*iL zO2~%fZ4UTUDSUYpxrrQGF0_GQ+8qTKAljxNE*B}Mx|?`hOIJ#@Q3;&qsj{F& z)Wz#0LCy*#Yz1BW}~Pp{2%Bz5cA(T{9?+Fxi8#qi zcy%fr@GM~T1b8xTNh!F)ow1?dwp;^A&xE%uUY7-En6UCr}-TJnd-QlOxeG0m!_ zh^B)&zE!+2mbT9|HYhLb;M|g1C{vUp3Lfx_Xc(fBDn)!^(BoyV>E8c(HhO>HhUNj8 zjE@|Ug^(0pK7jl-tFZlzYsWDE;|c7Ae%Auvg1}QCIG{v8Frc*1EKlNq;DEA!Ap?pd zM-M2(pV10QIO#n7qo2#Tl1pQdTNnp?n$%UkW1_XT0~&)GYMsdPXU8P`$a=L4@2Jt< zVN2YKMP?(3^|h_w5p}sb7M>kj@eWXrs%n3NNCLLg)Ti=@WV`!RT{7QRs|jzSGtHUy zCe-IxJe{(Ndl|}c29Nu?JKv%bEr>Q68ZJ!zS^c|0__^^;@N+*K@y9=iXZ87dvC;jx z>18!|E&O!@fkCgM`p>rFD1aw5+el4q zq8P!IC@$0$;YM&lqDhqW%~jjFwAEH>TdS>FTP=;zY7k@**~A66ini*+h@w`&HQ(p! z%=?|(pzZJT$Ir(@^1id2IdkUBnKNh3oH@*mVjl{!UtR_iPfRf$xuES*j1wKqj2qGV zIz4xHF+PaKjL5;$5dC11TNiiC1)3a?;_iu^1bVqUJZ4Q0MAzN_L!Wf$pY?aMYraB% zw^d^~35CWFD(eG-QEv~ z?`YPW)RJ~+B@@zQ2;&_Vy6JI>xhj;Y6BoP^PM0t;H_MI73lSgpm^_;LWj*5UY>3KT z-P~k($E>Sp*ettl-M+qGr^1?{Ir7v{W4J*_!RAD9&7Z)W>%KyFEfu&$7PMJk(cYMP zni@meEiCih_DXVS#>F&zF>5*9(9}PRyBHn+a(6#zLsY^LwMu@sJ<@YKt9VbLPf$w<)5e{#!AOC9cITJ6R^%LVDu->tPo-iWSP-8Bv#^Nt z&jG&6yR;z9mb<;r;|{iF-nq8iEq8mhOXZejHrA-+TuY(!0mX@Ck0g!3{jpfCW45T= z%qMeX2>p0s!CoiO%Zg@J zxVnEBrEb3jO8r9RGX;n7?dCv1Toj97^k4ED&oWyPTD2Q^Y=n5@acJ2-l`64?V=!FZ zTHHpe9kyy+Wy6qU$k-X2o678a+{Nr07WU)Uc_{5y8o)6{f*6-7c5csIfhwbUUCaV> zN{421tno`=>k#&a{+_Pi*xwDw%t40(Or8r0|L)Z~7NZHEh2lFu#EIoZ3qIoG;_Vv* zN1;(>eO0^GO?NQoiE6h2IP?!JkzYkR;|i7%r`=t9A$Tw)&yOucJ{?U++Hcz6Tsm0m zcAlX*7;Cyv79V-st#*f8VoA-DNb;T+9S6EE9yikO4sBW=@udIzMUcK1L*lJ3S7yex zxrvNKYaBeZrEBA_JMp8JI$K9s3Rt;O{M76?-~_$@`AqxAY+%e>(~kdhml<61JMw3} z<;9SfUop${4(^bf=#DqU$OwLtWXJA1dQwmPo3Zd2=NJp)8wNj5dDjjX;vxZl*}Tty z!zpZtPTYO0oas~e>%HKJa%>~RTQnlsxhfbLm1Oue{G@IV>6&=BgPIh2>xEDXZAeX( za}us#4-qeswhuNBK+FPrGmM$RwUE*+epPsHwyAXot+JMZL;G*}#9^S5AnvgnPt=cK zjn!WN9=d<#z~kJjm!a%6dLzk*!;52$d#e=N>HHWMT*QCRxg#$}kWO{9^&f^R(K3== z;je(OUG5pDGOP97tWxjdOigDnWaz6z{uq}Ta4bq`K{AubW&bjh_k}t}3~STXnZts` zO>d?POP?_Z$5k`>22ZcsHk5mSTVElx+uZVHbFRKGH$AI#Lps0wjdbtwH|wUv7Ossg ze0s}<2Jd78qb`qCJe!y|;K-^@UZ;3&bY{@8?uARYbjJR?Y~7c68_M69I~rWtuYe0v zBWo#f&(a!GBUo=E%xd z;TbI>hOZXt!tl^(caL<{R2>~^d-00fcC|^7y14uB?5T{ETn6r6nXC zr+XY6<+(~|8THkUfDCmEsyytap5YwmUY3#@tmGWf9eJfDLsvh$YuNe9tnhrLeqBgU zH zf1wv_W?4@L=TcUxef!HQ7#=D`_Tt{YZBAT{0qjfDSd^37+)Xx(Hb}l4==QmjR%Q4{ z!t74La{xx!KT_7+22AK-P<1d6f%ozxq`yg#JJ(t#v*Qt`j}uyNUnCmIk9tpc3W6G? zh9yL+aZZD|>B)rCg7vKBn`$=NGeivRe+tI%Z2fgeO;gIUaL0+yPGQlGfGH8WF ztv__QZjDifr*)r;IxaWz32s9ln;W5j0qchr&_WRv%exWvcwf~VS;3$ERD0ERTz$h& zpv>*|H)HBwUI0_er5&c;az10W&%$Vdo1Phax0?a)BL}&OvC`f91d*&|cL~;TvqRW` z0<^@*ca>|#CM1r)B0bp$@(zjoT^-Eo-)~m;=${Rj^>3R1hNnW`JwE6Asyt1@JFC8b zL^G+oXc(&L^2G3*^v=hCU;WJfRh^6QzN{aSQ}pxz;GD{tf_u+{p6ed%LC+sRUg-JPND}$K z+x5>o?M3k~R)zE5p8iGx-2HPl{%yPvk<1MEX>!q9dG5h`^BIO?^bN>WrUM6TI3K<2+Ai*f$Mnn|H4aI(<+*Gg-U zQysWaZJNLM7nlYAkutR`E~1Hzu3Ug8NS>!nIrH z^53t(36lqVp)cW4-mc~D$z`qsan&&`GwO?mZMj#RiaK7H8TFOE_pNH!mVdUrVP-g!A4ST4tu zaLnKNOtN7q@fY7n1rON4NOka^Di)zwQ(roxyO9%QyfAvOCHlG1g+o$T{EUol@b;<% zr`XBNpyp(z_siVn=BJL-lZBt~WoPQ~B1UPlw6;1+>QX)FZdv;W4}{|o==D?I+X4Iq&o z;y=Rh|6KTgXmir=ua-SAIhAb`{3Po}S@VQ^H|HMY1?Yq7ve5&;5ZtN@lev{S?gt+8 z+AhrBs`Z$!SVI{3e?MeG?j6!vC#YJcU=iQ$gFmBO>R|-i8W9+${4ZIW(09$=WJ72E z6~*pn9^kD4c(MmLT>$SCz{^SKc#!KZW#~`Ro$g$}tAD4u$6Zk0!F z{S=V<#v{Fz@74ji`8kip$aKkvqb|eTS$BD&P}~U1+s^H2m1%0b@`vsg-^y|Bh7z!JWaHBY;E?&xTL`m6#ph!i6vZklKNQ}FhK_ywt(R$RL$id<&!<1|M6 zz7ad(i^Up5bjf7Hwv%RjM34<#_|Fvllmf}1_jWIYZ^zG}w7z$#jg7pom_@UOLF_$e zAe1YDHPyj-^T1r1Ds7{^*uuh5v4sP2O4rr(qg@vHO^Bix>v|O^R5g4ao3XZIKy}`V z(Lu$^d^FJmF+TJ&RNm0OK$rdDpLceY&of#dp+g%MgL>ylGydJBuy?VkN&jRXmhP|f zJKh$jS>NBBs=n7l_3io}%j*AMDfHj^pV{+Pa#O)8sbD=Dmh-dy|9e#ji>{X2^o^Vm|l-kul+ASFXEATj9q#Q_`33ELQ?nn_~|YK*#dHi$%y8Z;EWyn%J546 zH!dsLJR;1?s+oXcfuMRz#nBrak|>wj%-+ONm3nrH zdM1#ESjKYq*%X`khq|xsw;moOWv)huW(wXyL2|w6p`Vj8GGl-3Y97GK_6Z#zvWAr! z{5Yi^i(@o&udMKR%M251v>?0ODwWBwp)IZsCEYGhhBm})u0Nkj9BxPbyla0KP_3rI zx#+GTg6aH)LNC@>Pf}&@LDC<2ObAoY6CS|_vAtPxs)D|$VBT72U@@x4l7(#y{fqXA z?k6BelE$*mVH?M~{s_z+vDr+xjUQ0aTQuhv*Yh1_?-FL4ES!q_0LOIbp93mU=JGgA zcekDK8u9yHKmQgEZcSvXJ$G4%;1VEp5oWd4Y7b!!#@XFvlGUAoN)@0{$GV`2 zc?|A&vDl4QGreQ`SJv|X^w|DQ^>l|nxA;E`{GW&Uwpna>mK>*gF->LLXe|zW3-BBDx|nIV&b%xqG_5KZVq5c&W@0dF>lOaJ75w z^evsoNL0_|`q65aI?V*-v}7=cb!Uy+!>Hxub1S1K4<@VxW*S)TR@)g^-BIrMzq66p zQp-qu<45Ahe7gsK@26QFhP3wSx^4w(vzh<)2wF1ulr|MOy=LZ@otV)OUpHMN0%U%* z4=AA@2&Z`uFzCVZU|Cb=m3f&l{T6M@Ygm?#;uH{~Bv>?WTqkcS=Fh_jw}_9zd82c= zj5%c9xL*9B6BJ;}Oo7q(l2bxieSz!C_Ca6BcQ4Mc_RF_jb5n9ED#W&Z=Ik14_#w2f znD@IrVqsH?w(WCGdu-ut`u$iZcs9H}H}Cnwa$irr| z*Ddw^FFyVaJ-E1d>oY3ON8>Z~eCRr3>}1`DjZIp|{lr@>m9?lB-ROM{2U*p%$^O;T z_{E{pceRz_xKiC!=c1BT--lfztm7U9l!*Wmq4esV%);m9T z@*)~*?6W}C8rq~S7G3jBRpv>ZdMEy20{Y2fGAjwflL*#TW-jTs=>5Dz!(07g3+E3O z3311&;3W_vZ>z|eShO*}qQAnytw^kQiV9b{E?Cq>+eOe8VzsH{P%afi-?hQh4R4FS zPqPGOk$2xyjJz8uN)55Mdw!&mH~a~S)f;-X-c$K`ecSC;yO0~%o9XKSItr}?D|Yg; zx=}ib8>MsSTS^z5UrJ?~+N`;nT8*`P`aDp$ZkfnY)$k!Z98xSv8H?SSD<&+(zNP=-;C~E>dxF}bL$iQtd zBuv$r5{+kaHW-OUvt5sJUOY~s&bP&5ahN;8=Yqs-3qT?ik36km`V$Wgt8S4yZxEAn zW3G=*-ptDeM6V}jTl?o&N!`}FOTD^Wc(yDWTmsWk*`k7KN{vN;c%V?R@ z0(?-bEx=k=yBFZo&s^+oeR5ax%#O4Cw&)zx-Se1Vc7r~X|K6pT$H_4-m~F}6Rrk@u zCT#a}=X-?KfJE!hY;X(43870tsP#hn+3xR&Ok_Rjp}3v-ZrE|*7jSum?2X-YIX2Ax ziX^h3TDMC0gD_9Uy~0Okkz2{yte;jk?)Ip9jm=wQaeY`St`-*X!}U6zVdT_um=2+p zqMSD6%sT;P(blc5^J!L+bHet1t)h5Ta6oP6&|yR$Q}+&X1WG^D zN)dnE4|=qsB&`)+y@O#=k1^|UnU14uG43dHeSU2te(7lt_?Mo*@1F{R3m|;f6RF(C zf#TYKg`Qsw`N$RKs}IgkE59PL+J^9Q#1&>PCjU5dt7mcQ5Vxa4b} zy1_hXv4F3fbpNh1u0!0&{bPxoZ6<1Nq--^oLOFFJ1nBj`dwh7BOAO$f5i?}`D6Mz* z{!47j-MUNeG7LWitJYGF;Yq@<4$N&_+7<7IKJ-4N2=r~`6%)tZZ;ud@K?CEJxN)}I zX@povu1oL_Y1Q@aYRZL4HT9${a6igQSwKpgo0J8sMoAmplHsaW$&Z?iBoHqH!qVMrbW2j%jF0I9$p>p|l z#dpF`;&wbtdCKkxv zn>!OlDrc)@C=(Vu63K*U51FusQ`kdRX%9KArica1_K=nAB)ayH6G)eyT&C>>CaY|r z6Um#3F4%S+GI-jT7z2C9nzm|G^a4v>l=6;GDRhb7AeSC1-1nSWr8B?0vZ`fi%~8L< zV#+P-@3=fVY@JRbs)jAEYRO%=Y06i(wbmv3D-8uYhh+VD?C3%F4|$>Ny(^Q$7A5v7`k8V(c0q&twE#nE3RY(A4|d|JKLxnr&P zR$u&8^0SJs?D_MFo(K1_l=k)SaJ%{Xcli4KRe$gAs{e7ktNkwG3GOS$P@~>( zj%Q1ZMcw5yl|Z-lRN+2VD6$IK<$vKd|}Mdg?vZPpReqtEBwh<*fp!f&wEyA?pfg~ zRp>$RX_Su@RupqjwED)_z`n78c-{xqM@hO}{AZXybXvrcqzR#beqA%h$45b*$3K@t zQL`nXjQ&Uru8@q89 zw3b1*g*u46%O@1&jLYnC1)om=maa*&a{yu#cbInIck2VO}>uP zlMTif`6k=mzmv$j zf#R-yY@|L7)SZcslV+jmQxzPm7b#Y{w)$=zDk1Cwe3*Cjk@Ve9+ z+NcDWQbqLAXSlu4e6*Qpb~~rbcJc>d$w@k!G0v&9k*x{_9PGy2=?y50n_k0!GTIC% zi)BD*SPBF)qKuk1U_Tj2M$N0(54Soqr082Vlp&+$rS`*wV#XAG_l`>Tv68+(KiN}M zg*cVV@~z#uXM3y4hS>acXb>(*HhiUdOQLXkT# z%sx#l1*NEMIwTHioY{Xk`Zer?FIGuUJ7-*^lT~Tw$_{3&ax)LMftkf8TBQtk)p(U- zaDZnw74ElUHMIt14}$_T;jieS{FrPjxyp5pRaKpJgjFxKs(+K3Y%Q#|7KT_0C^Hnp zBWH~pW5xba9~HwK_oDlxT5yqXi54vo*hAdj*_iy4#w=ej6D`ad&O5b~3F}pEW|W<1 z(Ydi8ZnRulT6}p?meYPj;D)(_p`8#;{s$N9CGHoD!#zr>LqE*6| zU+r?q)``RLK4EA`YEt%=k>u)P(!!0kAi<(t*>;sD%~Ld z%oJ3r(zLKr*LLmiRBDe=#n@lI(0e~6``IFgUGqiEkhGIgxl_*Ya? z<8Sq9J2tQ%zpD%RIDvl(E4g|)a18$xR+lM_e+nz(O5>lx>Iq7lz6t{G$ z%3q2#oCFU_ZfQN>dE|3@zK*p00MweuydXyTXjkfX_= z{gbG>=(fZh87kLRBB>5t6QvPKeyCz0u%i0JW^DYyc=T7CE=U>rG$Hd;xOp6hR%_fD zOpOZ7%IeG&`zVgiM8YaqEucMQ-;i|GnRAPopR%dS zi@_qY+nX)w=4?f2pRP67)D7s1p>gonV~TQE1vJZE zA>Q>K_GkrQ4#-n#On!3M(+UfS2}N5eeG&d@bFO_w2KmquZ_Y*DjX|I6VC_ej{+6{L zEerRfvBv9YE5va?gyZL3d(tw!p?roqQkD!(EmGtiUR1`zur0mIEwbh;=dd0A&QE4e z*XuuZ9r8(oP?L>N=K$O_{YgYUk5AI$q-$B2PNF|j?Z(lr8W2-~a0-)E@tWTm&CG)b zu}Z`5x$qpx9UzaISoo$FhKJQJBueU+m9foECEgn-5zl(Fx(COu}R$5k4Jdk zWq1^{@a;+ileh#0v4j0<=G(Sk4rT&`F?{?G_wsQDWTg9NvjMq7Ko)o)GX>;bfXiU^ zJJL*SAF&-6nat|RGzUQGl}TNlkLy~{0+J;OKEWqk7K<;qFB@G({0ED=(%#Lw;C;WP zt&&gA9>faBcU2sMLiGb&9PC;j0$lselo5Fj_E|Bvud*IdR@$mp7n()T9W+{vRuA#N z_V&Mu{I7xhVp|ZF%=5p(lAn#Tys+eZ_G^4t@)iFpEV`O9UJpOfZtCo%Cj1>>IETCFlJCq=$?7DoXS_qj67{El&9 z;txnn20q+_xcBXmmQfdT%WtF^Y4q)v}asysE^SC~=NYwCeFFaTkkYW_MSQz|3feD3?0pRy z%I#`*KS$)qN`jR$+#w)$G9Dx({teYg17bIpOBYMVhU^)e_X_E^1Z%}H_rhzb;P^te z&_PY%urHHS->g(*gq6m(+m5u{A(m8wsbcIX)bpLxbHi0{j}qSxCmsBAUUHjm7TU2!al7?LUOSRdjn>In<5OgW zebV~F(xF|{@UTlbwseZ zhY0aaf}AOM;TRAfbG=tj@_ex2LU%hosR}kFA(e*O^}R()l|MN~LA#quY_+A~KKC1+ zqY);j$#MoL=dYIYgz1D%rSzAGEY~gBNO!sq=!u?RzCIZ{{?(3wCWwuJ84kP?i5kQV(GFH@2G|BQmA5$2 z@}+*mUA1^)NXGzymF^8f?Ic>hvaH79dZlItPcZDT=aDIY3~`(2nP^eaZ3-Mh0e6p8 z?F_4GW|1>EtlFfik@7*K({v#tFV%cNio|-#BDHy-gcV-wFW~0>IfMjC#u{Vxf#B{d zC4fDpUD5EJ3Kmu6wW-VOxTBaOcNH%H1~yiq!(O*^nYtRsfNR)mH(wPdH<~Fv@4DO0GZk7)`Tbgp&mMOnLjl_=Eug=A(Xz(#xiV8{Ds;vZV zJxs~i^#fSZMAc|Cd@&?8re*vAA2o5cscvsxrYGtezuc{JOvYR?lBxOw651!oO2i;c zU~99BtMl38m0harLk&YM?yJW&4|-bXqZ8Z|-hxq6!y^yr5-WubI9blVc2-}^1oosaOH^(vyXN+<@O0Ad8xtG6l4xl(K!blv0gcUi$|!p>m2M_2 z(Q=a&81P0uc)0)kl5Ci%EQ(Oa9T>_#;a%}Fz2Be^auS(~ju8q4DHJ7IDlU!!*oYj{ zlBKr5$7AwePd4wtw(D!DlpiblfdVeKr7w*w+{tFXX1&P8%;zQtZy#eF4%_7FnGsiZ z+47HOEEGvaGQE3xjVr#&NcQ!Skj%efSnwF%?m$S{gJf4jL)nSS+W)x?Qh#uz)q6(u zuJNS4PWAo+ydL#NQ!mk??MVAA$k;?nTAxjPsxSLmU%aj#dIbNniU4Jj4qpmMCfYP% z95*K65~EkL^h_~Sjwegoqx;^mWWZy?kJ`MRi9L7F@DA9=$N6x_+~D=|k+4a!;pjth zV>et6cyuFEKe$?B>c>lAvF}j~8|opp>Oos}qfi#%o$NY44*F3?i^|UhhpQq*SSdF! z4+m{IV=0qY;YqZvAqV|H^beYFU8mZXf{COUopAiWpERKHCv?6wE8ocL+kWe3%%pp+u$grAFlN$6ekL8oxBKHPKa+kd+;!99 z^V!i1JcD}18(}x5FpJd9iYVO&ZD~K8-=T%G%m3vT+w3Tu!z%|$j*O1Gwf>{lEz?IZ zj`e>uiqwkqUde{5Yje`OO4RJUZ1i+6$?=K?hRM?xyIBWV`C50W|Cr{^3i zA!>ig%~AX8w0LhWf^c96L1x+0+xOyEmuc2MqWX-YI#h{0DDv}xQlU;jgX^{lT^ zisH${BN&Ru!84w5L*;-HK+(~WIDFP(sjYQG!juwH5JD$RbA7{$}d*CyNW&Q+3uIk_-aPF?ZioZ7Mg1M#3Q~K&dmB{$Lkr^?HPm%da>exSwC;)B%&w-J#bFGz{ayUHK4Yl>-+560CZ zv4()93?|>>T_(HsuoAP0$*PY2vX}fr;|8%=&BslP;JxS;UMXPd@c_yKf)#tB3K8y_ z71+PWP^xeQG`QN`bD`DwK851?J%iv=O>JE7e5U!L>Hh!^O099JDKZlDcH=nD^1(zZ4~T#1dbvh)2iu6>=_#5T@vsD6da7o8 zt%9?0HN_A3-x)X?a7WcTJtK5A)zgpy@?oeNU2BJQD?4uy1fZV?V1+~qvterVgs$w4 z15_K7#Q$sDZXrs0sFG4C&UlBZeZ7ykXgd8YZ6i6svJfIzVvN8M)A_Ig;rjzJCT+~k8|bydlr*|@!xd;C(e>>d$u?oPYh z269{(0~v;!*pF{_&I}vK%(y}`jJv-w;O#d-4-FJuTB&1c9)r0CE5i*o6IQyj=n*-J zYB$k;LS~l?Q<3_$t~^TL=F0S`xoJ^DwA-JgIUt&A4jc;KTC4|Xy(V0*J8f+Hkxb-) zY4$4MnrM_dibUr-hlW7y26QlqLc|k`5}yj0zlM2428}oUiX>ObZ~c(1)s`u1nCXfV z_>${a=jZBmqRiivSQ4463!nlYj$|@M`o^zT`2jy8}p7 zuf51h9T)*cJQ(M#b}w9RIXkOM_rW^wX?Tr8ZUd~cjDbvevmv+p19z%quGsqwG1L-R zq|9O}ao*G=|C=M3>2{M0AELSU7zZ$M4s$-$%SGM=K z`@6^~r_YD{N0IwIAOCax>fP18`H$8`5H1cOi0e;pKZ{>I*PjUgCG#Tut$yX+AqGeL z58mVDBf?#%107t`74 zel7_pdkRX^0u8goZp^+U{Sx$7xov1`+)23n5}W8hJ&=hWTJw(O+g*97SC|xa!4#(D zmw8v^?ZuKJNGd+P$><3%i96WiWzWBTT!AQHuf;n0zSN}auNBv(N4n21wsyy=-5jr| zEiI+pT-r@!CSAz3Co}e5cam?lVaWt75;`l54mq_YTVOod*)79Ah3D-?w!af_5`Yy< zc%I6!fkso(B_DBZc==+iV)$t1rAAl}wby!u>SB$>3E zUW?H=BOY@vgfi(7CDYf3dbc21#iMeVP4zq!;z=6*&(wwMtKdp45K zQA?Rn7gt<*ia!*2m%r>#%AzPUI%4pg^h9yJ%4TupcJiq!ijT^iVWR?Q&C##*>^i;4wL`nwr8W!>O1ROr%A%nA@O$ImLM*;W8$)4>Y zyjNu($8HLX$twA<3fyl~WVO2vA}O6S_AA0qpq9BGb^nOFGol~<0K}!be=irXqod#K zx!oc90gTC}1?cu`<%mm5(g%1Z=P22&+MN<&p&bk<*(siL6dLxD5H- z$o>bRCtroIx*FUL-{&P3AsLqB@I=ZJ1Ph(}_+mdhAIdJ{VdydwwI;h&VVNIOMkz_R z`<}**sFTVs@V|yiB<;iPEq}5b>OgI2c?3Az4aZTvN(Ash z!wGpS@M5)8$gceT!rIVc)qi1z-Ui}gSyI5zQ;O1bw$KeVRWjDN5%5(+~XqeM$Elk;yCOuu9j*}zuXtqTqY)++5 zq&@2@b9AM<+HX6L*7ua}8!sWp5$u+GX1U4mz338iXuZo!{tAtDRa2X17@qG~Rl&PA zaN8pjB#pRU>h?cTUtU<*sT`tEXWG-Zla;0sM)7PWwbarpcgeLTuT#PM?3bznjxWyD z`Sr(o)`OVwPvSs??A;qT5$>xLp>JNiCAw-h_da2w;E8oeVCECxdz0 ziQY2rdn%({BzA`}TSBSq#qN#FbjjRXz>5y1!Z2^{fRoj|)vlLy)5Pyq>pSG$>^|_H zf|PV`>IYwO6PaFgh)F9)Tu_o8uPc+#6n-p|82p5p0o|Yab=P8506jv>ne`?J_}Z*FlMn?hbx0tfOPr9t_!fuJ8HVWT-35O>0II z(+IV~YOJQAp6Pm@FNM7;%m}AMgz?WT7x$@`Y=*9OCxz`?MTQLsmoy0VO?TWNhOMcs zgI9?0a}3sl1?hgxiojJ+OI+wXWW`U38I8_{`pL%lv%&TQrH$x4!6bUTNM;^y?`*$u z_*Wpn&u9bK9V6237hk$Eggh1v7<k^-ml`IKk~KVNI4Z;4Sx51OJreCLt1%@S=0DPve1@BS%=7y zdG)jj?G==A9-r=-6GYoJ?qs7e`<%_LD*EK2V))6S#LrdwVEsm54L6v7V~|j180~0( z6wW|}uu3#sTapuN8tTgwSsB}Qgk@%vp=DEWZNI~kvND!^yUtL89|T zb!a$68m^w6Bfk?5#TaOnd(|vCvBq7qVBo5TIL|j?u=7Nv6p@A&VV*?x!@rEHu0>0Zyl#@Z^yNZm%T zIR%&7{Zh57Q!sk?JvV@#hSV|zQaT4Nb)OT@nY=Js+zBLAjJUQWePqRmx#;m0M@gRD zGYV|Vq7q6fK2MDaAG_y7vx9hDP zTd&AIo-xq^(1m>ZJi~cNH_qiLba!Bx6$EH<+@r6ojKXwJ znw6+!2v(v$Y9pR0=*_n~?zGTK6j=^$I-QrE`aA_!L6nt_$M!&IwY!nOn)Z`9MHXLm z^zjRyow0E`qtnMS(QWZ_{=P;OQqJGmSU$tkiwH`e3(qptbrfX@bFR@>1plfat`|of z1Lct9*E!S6PhX7FTHU_U!N;O8!eV21%*V5bwjzclwU+s%AKM`U$~}@4?rU6NeL#KM z=IZsy6iM17?h7Hf2fPU^aAsL;WEs3^7sygF+m{1RuiC#R)jsH`#tHHJ?w31Z-f8ar zp#jM#r}LSr@=Y_|m8@J~eX6E(Rgrrb0mMaKlnRakYDhb&$UU(mu+bIw=K>Ug8RdSc z%PTvXs)fR%po|?mwrT|2+JPFxSfe6JdV+)ea2}+HHQ40J)aBc0c(OEXm?^x!&+L^X+c(;Z-q$qE)h7fMA8zZsB{Wlxb_-822Al+STfg)S*f1DMKRIbT zGi3pss!_Ym?u9((3P$6Zbh)7-fAk?nuIJN7)0iE_qSi*PAV)@}x^p_Mf=IXGhUrJ+JK zgvJ`Rd4TYyfrKP6ii`B!r7oeA!8gsAF}pk8m?PFWQ8^7C<|i9AacONf{uklad^-*s z@3A7rMKzEh20%`Wfb0v9RPZTW8*AJOKbb$(*x=&N7+1E#J6qjY)8C9`p{}gfMSlFe zEm(wmz;bI?Ezlz<#2GH4mp*rQLwiW$FN8yN2%txiG*qk6g`Dq(kRC_6Q2PIx4{gjm zgxVgW1G68SZWM**d&PC9Ewfig9 zvMv=>DiY$rBvKDK#d%m6n7BtTF`3AVzbX7dsm9!s#iKSZylYB)FxHx<-O?!>#eV&8|qIa-(Cu}1-4U@iK zOUQDx?oXHZV8V5sF2@?T7}ZSCp5SUNZ>1X!jl2|&HU5JFiW|`FA9hNdogHTnqUv~J z+KY?s2#Nn|coT8ReoOqOg-pwqZOgl6Px=zH1;HR$bp1XTp^%s?W7AJEDKY|rx7Hi+ z3yv9x6q!BIOOfBxiXDJ0JDFwdhpAu}YXn82tC2+KPq$I3sV&-2a*nvt?RTs?w94IW ze;K>*RDZH}J zrl$Vmo7DcQoln2gaGF2=MC)T6{c8P<@8hY3^zl~uu7kGdH2>f9x&14;LiBw-C#fy! zDx>;pw}FQZF!C>Yfw%i!i#4t@;$z?KXT)bMh$VyTBuXKxo-{;Bv~3Doa68Zv9kFc` znYP7QJ#!xY0%fdw&R=gZ$y43XtYYU!K>U%cM`m69uDa>5SlfWCZNFefmHn`!50p{m zzgI3uEE`io+u@Ur5b`3ft!bDhsLg|y?Ao$RxIZdo`T7;?f9nLoPL%{tNN&nBOSk<_|~>M@bQE<|BW z77Eo}t-v}Hr)i=d8bUcN%nAdPg_iuqVXmI&%DTT#WpS>~?crXxr#(6lYy8moi?jTT z5xGqM4c+o3EI+Pp1Zaz_E^U*xtYfSu-FFpAj+pzvq`xk!)>gyjhderXB!d!`kpfXg=OQDHFYb zNqCu1&iL2L{d+{+L3Xk)aZLb!ckuK2`z(WBr0ryJ z%rVmY!m`Hv@EM0R(j`~|MeA+`ADC5^y$*1@fPSm&JEoj_9JD>QvR!aBM%{3Ajl>EV z-<#<1Mx^c{3cT&lrD1HW*W&C+zXaoE7uUV7N%v`x26y4yAIiU}W`-`mppX0^xr=};z_ zNMPsqockNsOVsFn2GkP|w2U_FE>HBsp_6Box<0Fv8Lj4r`)003*zhG(9_2P`xW{+3 z$@*Y^Rs%z9Bq8NfEvA8zURcr@Tz&Tn(ekH;a#XN!7YAff>Qm4HQ=ePpDcvndU-Y@G zFF>vpjWmqg5$a(IsbREPaiNUi?(&qU$*o=BqjfQ>?O9<(V*xYHU3h}8c4nAk_H4_U z5a!7F!#Bo~V7&31J3P$OsbSO?yuo4Ltj2T?*)siV38|x1!>^XHMrRYxOYHx~6ibZG z^0Z*lsb)cV!7U7V>i#gx1~tU&!g0PoIyH^&WvwF}seKPrGUt*01 z>uj$N6a-8;qp4;zI@(&(EzNOpQzaB8{zdoB*slo7YTIBKu<}{_?UAT!+?>O`qeqve zzrnj3bv;37qB8QStfdQX>^Y%?lSwZD0BBmKSHDYFQVU)>GSy!nK7O< z@e|&GvLW!dI4lm>p{BgX^ z#Q1h_j-Zg|2NctZ(_CqYhs0sT`#Q`24)|Y~Adwu%f?w7x30{rzO(erV-zf?n^`)%C zCNB(F&n@mPl+lpiXM+YRer>Og*12ru%%6m6x_PB~wHuQ3q#fIZk4W~NUE0rzc=75N zN$shPWNiC-E@u8D)aJDuZnRK6G{(2I@jC>E2-v;M>AsBSoORn~KK{&M?R&cNUe>@% zg>7O!Y9){pg^fy=ktIu9UFb8BGu0+%zGH!s6NQ>JS;QK(#+8PU5Av0vN*3Q4oq7&M zp9q6!P``sQ-m+nWF}i$_@!Nw*{D62*`pCQAvrm{4nXF=szwQDN*_^)jEfDEzJcF7M z+_($hzHDsMr~3ll{DF0^=L|{XL;)jxx8VaUy9|NLybvk~4Ifdsb^PBB(d@PjE9WwL zC!E7jlPpY^NVkR8RT{QY%u97wC309qQUvyaEjas1|$uYaAkUW>t}d3(K+!+G|0m$=>n&| z^>!~DNsnDm8)5ikW#`%sCZKJLvrta&SkXMIBpQ-c?(~Db4>xlJ$4{vaAHBdIMHLll33W2r8T}5F7lKpCZ9s>X*4|jWfu)lP_ z-+Ow5RBpn~7~x!5j|$w|TY&4YkDkEGg0hybc4vM_BH1VCW-nAZLdN0ATX;z-y_Z|C z8N#+jq@Z7ALL%&(oADp2dNRq_)ic+Aw=gA;mR(hZcR2sL@%_`OArZI7cNA>!Eqou` zM50h_t4n7`P>Jk6_XL5)(M;ouWEtl&ZcJ9q( z2Csa7clx~2eL8Nd53GMTf%QEHn=;hJ$sQi@vH$YT-Z@=HHGZ$l{vEZ~7`68buN-z} zl8&YpVJ6_V(h+c=JpY+lWi;h(kKpeH&CvJ=XS7XQbbBE0wYs6uU~f8bcjw+b!<_H>olPH_>D2}p zBh9{%8oJH;Jg|5|FO|`mSH>dTr;3Z*N`vb>kZdCXFkV$3pv&M~~{P>)5N;p2f zpwh1ZpHMebK@N`w^5zx^8l3hMe*blr>D=l^{5B|pAbvX|ll(XJ%7o{gT%`Ly@Y@SD zAqJ{H)$`ltuc;sCLc{;$w`_Kc?Eew8Tu21V1^FSn?S$>VC%5qo>6Q6gU-7&qtET6+ z^cr#7f8)0wM)3bPza2sc#BXIy~x;o2fw*h+wU3MH4+aS*+`l( z_08Yi$kq)#m@SLlj}c#A@s@jOgmq(#T3G8_$Wsgdq~#t=eGn~3!cI_Mx~7eBp8v=5 z@9h(_`1k8CL;kG@`FAr3#=ke;^DX{Gey;eur#x-n?)Q(r=$Zf6cE7LO?)Qowzx{cK ziK+?o)ODO>s1AEA1*efYodXa3Ez>`<5q+`7rzsa(xC605?)#$dlKRj4NJQZxi42;O z3?}pOTKW_sJ4r-MPkXG86rcBMn1`>hh2Ed`*ubtl z^R2)*A!vd+y((DYPAt`GoFWue(8k(XSMK&6Zo}3_2U|~|GTe6;-)=vKQ^Qt}W4C7t z+!c(Y=e}A9Kfw#S*YEHH{rOX17gr!&hl^VAv!7nn`k*%ZICzIHDNGN zw@;G^g-9$|s6f@8k5%vLM!ANg47Xz8cBaQIN4N#TIXIytmFY7?d6J>JsJkAVzlGv( z@mh$o=P!G2=oad@!%hr&tdASt_1;iDIm5OjGpf}@KR8RlY7(EvZXg+}M3Z_gosz%8 z7-daJvaoPIfxkX0K7ZoYIh8KsR|#fl9m#gOT^Si3K`t;O%1Sp6ob`@;UdN&Ct|P6R zFT$g(GijV5c#CiMJG!qS2rso2xKHVKQhNCOVj-#6^lK;3gX@;4H(f97#3xQ_kzT1P2m{I-Z?l8fuWLHA+uz_PO zWwb?(GE7#pZ=k`zW5vxOe<%`Yo@c~oU+(Gcer(}Pgd6ks%tOM z zP|4#P$$09j-b8(oYf7SiWKLcGL_O}~c=P~^ViJ)PB;R!PvPfzgEOo05MUvDB?xB0O zb~d)f=55hJQL+gVl zb(VXgK%@JL(&ap$+9#ILCAvhWGFPuZOLQTFk`?s31VfVH;}o|>Qus%d)cw?CM+$yQ zYL`E}YU;t1%k(ZKK#F_se5R914y2^E-pGShRe1!$p31VY*lj|c^#Jmel1C&ajZx_* zdEcO>-uxu(fMhsY!L7!al?tIE2T6D3Va8HdZDF>=At$Wy!^UkJ7E0iS5rLNten9SDsc0E``zLByr)n-kbNM$j5yG=^1 zefj=;a#AvLadCT#goj%>)~0AM=K?%{msT$0_1BHO^!jEhc$Giz1zY*|ql)G^goRj9 zcZ{1~W(2MQ_txc18@jyiQ~Gf${o}In92@If+&gp&!Qq8Jei?+>K67!RencNlXU)*M zeotxX>FAvZF7Hjq#JReUQ%^?2H($k?{t7cNorbwReRJ>9MC(hwxpUOqzBH$%#t$SA z#$0!WHP`+Tgsm7pXI6Tc`}ZM+=Yy(fcIHgM{;K!^0I5i=YcpeScE|XN3#ph24&$}N zmwDcBZtSUzVDhBNh8Dggrsq}+FHiq~o9V&C!eHirU|jF!%Js>qqX(t(HaFMcAzJrx zbKRPbYg3u(m71oAi^?@TGPIsY!d`Ywzut;5t8#s?Jg8Y2)U9bA-8-m!IZ?W_qM5ty z6APPX4rm@dXlY*VmPOaq9ht~$OO!9U_TZ-!YU9bDfLzDn-wpR5;0oe$V5WjIPiS0m zw1Nln)w-HJ)lIJH~E&8dxpoGv2Y^ZjLoP z$}hM3K{kZ{-pr8rz?%iNe7m6x6{Fa?m_jy?GZ-U=;Swj?NMb@jc#6eYs-Z(HM>E-fO>JiBn&ZD_!R3?{{1gb+9@Z#`={$ zm1k^GL~Mpmg-$}L(csK^Ie0Ts`p=FE#;0zbyS>!tH$|xAdQ@Kf5LA8*iW-EwsAPk% z3EYt0XQSdx{Tu*!uO{;_&R0&U2sl2g9>ZcT6^}KX=~zjeGU;xUsm)#s^}F%}AH62o zJiLC+vK*a!R=>yg>DfaL0SBG>F!MJE68`L5}9 zHhiJN#JBD2%&2#fTg>5A@H$nw33Kit;PUx6nn7ey_8}|B5 z4Et0+?En6NVgJJce%Q5u+OThdKiZ!bGcU{I-<*#5iH2`-(}%hz3EqtlB%aMvJ($`9CC_d$Ew|+e~{?CuN*@9 zFKtfrwpjEH-|SU4Jh5eIZu&C!LWy>ad)6F*~VAH zH+xv+y!2u24qth;D*wV)e!YXrqK{SnxbgG8)?W_2>WxyjNbLRbZWX?bNe+B=K;r}oHGBQW$Ieq)~&Fz(! z)4LBJz541W7B`8YZC3yGS+$xLsS%3N3k< zN@|lBw=jy>Y;M|3%z|I9ZELho!IaR!G%L&6)-0lx`tqE*LG@SX=G1W^V{xyBrJd;+ z4IlODI6JD7%FH(j5bbbmqcL6Eo8fK^1Pzuqw#`Q8WE;9=QEqz2(hcljFe7#JX3|Vg zPUUQ9gEE+4o$2Dvr5$<6yjM#*^1jy2;VgKTGs(-Un)k9EwdwL}(ovhGVSk^}6fCEpY1rqe=)M${%>Q6B(qa+WllT$SYuItos;shD<73jo94#di5{s|2U2=2hHl@^w>uT2#E~0GGo

FW>zQfGWnU) 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

K2X9E+K4?e=%zCU%UUqU0Gf=^GaAj5kdmrE{>Bb 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

    F!)tuBCMeMcH* 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 z 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

    &J`TO8a8`ZUV1(@N1QGJVN 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�xwv9I-d^w#myWTMiN3dx2j)4g~c)< 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

    `TRy^`b|k%5wiCmY=f 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

    PtHrA)SID#N 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π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%0DIbPfElZ<@qX)T!G)n(tgX$4 z0Sm*}jtAXwYr-we$>@ufdyDrO`#gsSttar}&EnyG(pna{cNVUnT8fQznFtRDH(=jG zEaCL=IV?)tE4sOIS8#MOplX{f<^?^2b?1wTpXRs?H+VIk`sgRrn&S;60~*4#V(y)@X&K{FT{O6rhW4f5~`elHVyW|$0pW%o69at4qwc+ubK?EbQyfhgg#jN zUQMi5Xc!in^8t##xB-PXEo9a=K4Gf;8vZWv61Yy<4K5!>LqZET{@tz&R8gmjJ%PTc z?&`(24okq=7rk(L!(v$B;38fZwOD-ae(t!;21;t1iG8ah`252L)^1=G=+WRX7@EC- zEm>Ef>BuMVip>4yI8dqK5pFL9013Qo68gw<6}g0ppd*yD2? zz9&6FpTpLoUAl3NcHRe8}0kp#r=vL|gT=`y$9a*1% zkDFBB(SPQ`^{>G^ZtftQ+H^Y{KA4S}m1n`NtKvPjeh2u>Z?&Lir_(HUi65j~tilhj zx{6kZIs(sZ1_M2g!nk)!7j}GEp z$4}xulA>Gx<{foQFt$|+bFUQ(6Ta zEne}mCCfwgtD|{VurqE=N<{Ao4p8NID6?5L63#69%B`ah;)P~A`G_@*uyMo-=DF_` z-oC;xm^Xr)627JYg!^B6_B=n?suM-(oJ{UT3e+!!BBeD^mCJ<$j6zw64br*A;z5qq=`*owZx-FW!3 z-FUq2GhXe90`L7eE#`9F@QfI9$M_!s&1)skvCV<(3!Qj+sfVzx>OC0k+8pPsu!i+% zJ>ZWA2EIJ=85}oE5O*3+!^&-Dv5b1nF}G%8c+qtac5+VS8_J8hA1jUNj@!{G>l07C ztc0W8T0tFg*Klq^8@9j4VK^{*KJVl@5m%m1!tD!>Lfq5yeD&VxuyVq8{!GyYTrPEi znl)@-gwC7s;a{-HCRaEYQ4$Y@J2D&)hu!*DgRa?yK=C4q?P<6ey2U&Zr*Y~*!{nl{ zxMO#$vv(Xs{k;IIWn{62o5h%DSt5o`t_a8Bzm%axlc3#KU#$-U?`czW(dZvh znrB%g?tgOf5>x=fNEa!s;bt&}L_l9BFxtJ$zupj=! zf_t78eO%8;@J;OX#(x~kX1Lx3#X<`M44_S!2-KX<;k9NVH z;7p9E)gKqC>~PY#hw#8H2^_@ThJSUs$Y0%F4x@zL&%@6!plmrjp+wkew}GF2xC9zF zgkkI`Jt*t%fd%%Ralqs!{B!+DF#OG8KFoI_tkl%T*SFr|l>L8+HRk2maKUYux?u_o z@%X_ub&bZ=dFMHE+>PUU4P@WNxl!LPZ*cLez4-TpX}m{V=ivTP1{_d# z1(Xu|`|fo*fYsowxJ5M(&eiM3Q(QB!)5C+%=Hf^glwc1}27Q8#bB{2aq75MQdo`Gz z^c+@2&BX-6MLdVm~VW49^Plf;<*~nu(QQPSdq{T{APJUp9Q7idvG}0 z+h#nn`XLy9_%d298P7(q9)?lkj=-2VA=t}44^}^Z1LZU&z;k|2yz$}&`&6wF?$<-2=h?{lWiLF&JL&75=?y0Bd#50%M=YqV>0X(0ODk z|CDzH*N2?txKaZbEIGuLHh|yuso40&1l%!gGA{2sPwb1>uu>N*VTU?u_9}22x=+>M z?5%F#@nkm-+BFM0<(0)}Gpyj#pJVy$sB75K>o&`pHXY~e?T-#MO2S87JiEND7cSeg z01rGVjBA!@*we!^A>!N-ygjNDy1eMfy{m1;gZ3rajq>6hZjT}2cc-FZ?K6?SpCM#XBi`XF_P(NGx*fJ8Zb}7Hu{U=ku<9!d;!6;Ad$) z?B9Bk=?={o_l0hO#^O$Y&ydmJRJRv&sX7n;E>a8^zSH56%emm=cm@_O$inhH>aiBK z#h^lLXRNl_6}G+_2)n#Dnp?cP1&_}!4T9ah?U7nhGIphKz!h0%qnaFQy#CvU4Av#)3F2bVwwBw zr*{t2PoB?wri*^=g4oke-h~#^ro(dASvY#tV%+^!VphyUobZP$9BMqB zz3*BahGrl>-IxSboGWnW@ypO**KO>(_b1lBc2vCYHx9fP)_~Y~N8rNO2HeRz4zD$d z!#^)i!5@>W;GO7-cv`GKhp0-5bKHrnLoq+x^KvAwQB9m#tSruk`uBx%$DXkC?Khxd zr;m6stq-iX>&Q~-0=6wR8#9V0;GL0A*qG{CI2;s;oifF}juTt4LXS>ElU|o$VRCQ0 zQl%+7yU7)sTzv{hY#!jJlO1rwo_kp5YB{k-ehQz|O=gu`ZE@$Ll`wDDakz7WGuw;J z@#*ky>`!qXu+qGDu+g>R>*X~mD`&|!W<=NxeV(~j`;oBRr5?dF+ z(&7G)T6!hUu~NXdQ@io}>LzTkq8_YVR1wGiC<|4y-Nijmv!Pt&vuyE&-r~2h?7?zO zJVaO7%QG5Oz#`f|uu8pIc;&f)w{Yx;QJVrW<<3YL+`kNe+Ndb3ojH*Y62CJwxm_22 zzNQ^EJvoMbZLtdD<^=E?S9I{SSPI{e+z2&xpJDctSe()=1M5912~gubKAe$-Uz*FlOx&{4wAxK3MO~cBC!G_d&Z@-s!h6t;>1F>)C^ywH_lna5(w!03RDKexqPu zLwuy!2U$-Sir+~phOcMLgDy$6vDW8!yc}=9Ky5AXT)7zr+{oefnuTCj--%7N%YYft zq5N4`41PGWg};0G7Wz+o$!+hiMD^Z>ICkqBhLq^t(9!~#yYUwehJ(2xFlLG1+eNl0xtR>YqPj6l=_gy{|xJb zIZwvI*+y!JdAyS!2nokF6&7Rv4INN7N6+4zbi^$V$1$mp2QG+7;$FGkAvD{GADu4F zb7a)yy_}S|=EVfy;|@WOy_HzhA9e9v&0>7u?dw>~V*&41Jq%M;B=auTe`9uub}T;D zA2JUwU}3w4!_>-g7%A@Otu(1G-&?#h++Mu_J|~^V;Q9%y&$bJAz34Y?@A(I=vCqK9 ztt@a#%q4E{yAIy7da_Y>6W}jJ4Ys*oQ9QHD32i*i!$$2^C|P6}xPGk8!ln#|+R58+ z)}mni9^04?o>2r(KTqOO$sXbi(Gs?-cvWy4RgQ-&0zCZW035g6j$7wnhS!t-fM?ey zu=bDqq4nw_?6jsi+V$#wo=< zmk-u@Y5_ZsMe?$@&f~b{eL*|-3k?6}z*g@$jyCqQdBWkf*fjAiSoDmBhRf3V;HWHM zqhCT%yKj(Csz1~c?*l!26M^fC9ma!?r=nV%As*QzgROEp1$_>^cG0gn zj1Qj2tN+y-l79|m#pWbnbDLUFN9;=$I~5L#4qb(X6%G7TXD8hKQ_bvmT!xjt<-{E- z=V1JyN1-yPrcsF-NX_`06273&4(c6@+o@g3mp5X6P;M zKKzu;1;>u@$akRoK-PiXk=s9+hH$H>64DJvo^wuw8yZm#SHG=rZ*;^EyOyW ztOG@BropD|iy^A*MW`>%X>E4z%^_wX9H{+{kNkNbo9KQ($b{B-)>iC2KBL!-!rS73t+VKWY|v2%IuIs2aS+pdoA(s?Dzn$ien%x%Ksp4eiuj&-s9+)t4F0kjAGRHa!QI;6 zJNw$qG3+JW+0l`I9J&kYp16UB|8&GEv6CS1unq2SeFExsc#3!PLZH;soiN9J7@IOe zg$WG`G5od@ik5rHXDXUP#-aNBlimrBj_%HnhPYy7*H5g<`JJ%QcO!Jp(|}FLBJ3pg zhrzQ0A2KfikGecy?;5m#hUZ`5+zBV}??ykds_#Nj{=Cn6=$oO%HaBd${XC4@_mw?< z>)*eZ<&6!yaSXZ3i)swJ_~U+WGi6!(}kbvnhaY^sNzg@>Z^!gvs`_F|(x>A<^oWgo|Htt4O@b8k&%Q-!U zu)A~k`Mj~4Kz+Kxp&8S zNIE)^U+8lT%Zz%(4&Lbn+ddrRK|{8{z^X&ost@y^Q21qDdwFq~xwelA#AUe&YwLEqyenp^%40+)2m|9*%cvN!(|`CQBV?;E1M`QJ~$ z=6`{zNcpK+ol2|Jsl5Dknouu;D$+o<`0Apx2F-9GQ-j2hwxpNxo4zgS2TA(Y zAl_p#8q|sO(tgu-CjC*8z5*bD^gT&0^EZ9lYexGIN%|H5>Bit8m-Hg5{~BLs(myQe zi;R0n`apUKzv;V?{t-#vEPbp=FZDNlPtrds>6@jG1L+<6O+S$Ik4gGw>ElLvH-FQQ zB>m%(zM>#~yh-ovZ~C3y7~?M|qvVG^mX!Yr`gW#ochWB;=}85fKJFwBr0;0@_9p$p zlAf7BJ;p8W4 znAf)gjr{6nG6On^|IHCbO5YX59~E2ZKcKT$xJnn~ALZrV^Undzyxa#2@Cps^Zzgo4 z4~4JOD~F3eFRfm03|kecRrwlJer*&sehQt+pbJuk8_DQT3Rl?Z7o-mG5?}uwxKQn6 zRENw##(J_^&R9`&-Wkh93bEz4p>jH}Bz7SAD&kJWU8xMY6L%x_CLZ9{+0o9Fnc~?p zH+MEAzmZ!sGbMjM+mjzzU&!qpjRn9)uW%42l|g*l=xsv66t*^che(@{$cB<@e)=i( z>Sn_YUfN()lrjB;vR=~Y(#I=Q zf1>Z@(QCjz^$H4U-_EY?autwF{w+N;N|jblkpC2qe9w~c;$yBSJwjxKluf^fD>?ro zTuI-vb@PAAmq_9K4}D|O7=4I#OKvp+RBA8TU3#eaP<&M3+TlXQ*PshA=C4WL%TF{0 z;i`N;u7lh~PP-2A`qRTxZhK@!KlnHIU_XB^O_(7>r563}Z~h#-ghxpsEI3rM!%u2V zq(Q=O2AbO^RPqfJ2FtZaxI}sds0>mwsPfIXT8^SLm^JgS@-6WG4||NBeKr0{UxP*` z)j>I1e$^At`5)=!8)KdVQY`;19b~KXQ$jA^D&I&iZJ1ApsH*aKN-MHJX)rG*D&OIf zl8@3iSf%z8S(filv?yMFVOrzUsJ=+5lDj6~*(Cn2zfJwbf9;Vxd~osHlz1Yt?!Y;x z;&mrNYA3Y3zP0*L#l5JRdkqImiy{Lp3#*K74z(SMTNG_vuW%tI94Z2FnZkvt8M&E5X^Z0CF>Xv% zxQMKyFoxgR+`W*{buha3Gk2E^>ST1cGj}f{+-v-cyJRT2|MFZ5;jZ`>{bK(?-?Bje z7dyozWB+Pr3E|#J4qv7A6-8fEEnoe=wKMvl0Cj#lBZ2Hm{FC1<8wU?^J15D#IuGd6 z%&YI89B=5pw@7Ml~{f5?hg6ODtYDljSMI z!%gx&LuCH}B+n%I0peWZuB4ww97Akf*7*EUq;E?cOzcK1Iwkq}-ozSWE%7trIARA1 zKbhE(IF(o=s2pAzaW9gm6Tc++1L7d!JmO-cZ)Ih)KZN88;xWVy#PvwO6LDE$PvW9>l0eqaB#t2Y1LCp7Z;6MIK9n=YM^9``>`m-I ztR!|L9!KG6iAAB1pC3m&k>tt5KZ#RK`ozbGClO~7PbPjz{G2$CSafdk^DN67?Qcxa zR}fDjxifJ*$=!)(69*DcBmGF?7~%xtDAM0f982F@2BYs3|UBPJYEMf=Z z!6y5N<4GP!+??dm#Is4BN}NEPPV7he4~W;3{H;l!v`M$;7LOQ;Ek>cx|Mth$U zI}-;IdlJ7RPNVX0fmloOA{2f!@oSPN6I+u!jd&n&I&pR4T;kE>KaaQ?$*rpy?Y%~F zTVgTElhenIcq_3t@g(veNj#D`fw(8;+lgzFJe{}(aW3%-($A&xy`4CZ9FSCype3Kpa2}3Zp%~#MZv9I z1+g>9oryaWyA!u24kXSZ|Ix&aNS;hQlz2OFU*b$+cjC9i{fMpV8SVRn*p|2^u`}@v zdcGU+Ad-6%4;x;7rCVoTmXyW(8sl*?MGl?z8 ze;)Bpl3O)3KEJ-{`NSVd?oRxPIFPs^=|>ZPCV2w!7vfanJmPfXufz|CC!6deo=NiP zBgXwVEy=CyjrM*cxq|pll6NBhPI7PJAH%iuMn{VabaRN;_k%W#G{ELiPxFzBc4U_RN{%mX~ac|Gl|C#=MsAn=Mh^HTQ)P= zTbx)ytRr?NEXDwO_W=TPAr zqS33wi6Mj77?zcVo>3m8Rs<@=FK-7bgT>eolm>$;RBKQeG-4MxO!(1@jW{VVq30Lm z@2}E{9ZH3-*x59m5m6cxAu6Tbps;mmDE8qL&6+wY)GC#q%1`n!AS}qBQgl(|Z^wX- z(of+l9vGlf_y%bMg=u=R@eD?H*})hWSx*xxj-?nMuM7#$=zf_Akd* z>|KZH)Z+0zQ3_vWNQkt>B9vr(m2W|a=HUb?!j&OmQuK{_K>;ceBeCxlU=Z_l`6KyP zDRm)H^i-LBeHFecok3DCvQ`sBTfQS1F<9hk=mL-NQi!8-rsOsH*M}%1foz~LSlK?vpgM0=)J`bdfUo4b_c#?tqzevqG>l@X#D5^Wo8>MC?nWA;n9 zA`^8=T~vM=7{gbqsn|)yD!)vKmQ<~f+F6Y{M5-jzvdVHlrCKE_M!t>4a5TX|Duvi( zSNu{$3hb5T`8n<@4wINwlKjl_4bvMmp$d_1a`O`+%C0g*r&9VwiFR8wLm`wdvJEDQ znJuzA6+Vq9>^f1=6`^v}{KG`ClI2o~HS;6cFT0BjQ!1nuMk*atnk1q4{71P+BQb8{WS1qEi$nTnD z3w>0E2$hs$qEd;zRx~c+AWxuN@XTT$*FIB8^;601q0~$nTL6VdCnp&-o}o(7X-f74 z{(F5E?qs~&YMClSerrQ@PCjRmUnr#TMBXUq@QrMcPmt6!fjE*Nk1IsCZB~PV=L20ivoZrGlyOQHk792@s_f zAkbjY>ZP7CQsjc!NJMfscL)*)&?J9m@`8bxXvDPAaO*$H^=h%>{ttPiA(X}sL26N7 zL_@C>Euz$8n^>y41-W77UeJO`HB<~!<=_kaX+lFql{e>q9n!4`eNuIMZld)79?ZA^X1meR}2m4(I)-hYh=E= zJhm(Fub0YE=J5@(ojXO z73D>hpKjuqq!`OeZHoSvkpqo|Me8K8N*)1-F?NKg4I=Zx)cP>3R-+TgVBzPE0UGB4}zX=VB6nRuIQ1#@+U&lR?+!z_79a32-Xj-I#VVu?)rBZn2a?!p^ z2_*{7Z|pQ^1 zJg!YdT8s`W7)HoLFsVB;Mnf7^7@u#n<+n!*yR<5K+-of0R1GA1O#^zVi8N17X~rl` zcYjGCp`UMtsV}2=$y0HYJ(8RB5&GmVPt#0~HFK9TP@eTlorrO*Lug6aqjEVa(v(&4`yz{w z$nJ)qP?b2qF1jKrx#&Go@gjC#t)# zqMH_>jT02e9|wvz0K|fh81x(S!&pH6xsH>+>?|5m;}BO2&!nkLkQm*LG5VF_Wh$eJ zh(Kv6Pt0E=CE@-rt*Lo=Dv(QaQK=`FT>jZN8|Q!0l8-{HHi@>FmK;qDvD`TOYQjYG zBQ+pm{-TlB#zay5rM)&a;{UexXkG|py)bpKTGTsf+Vz`0h$gbRG&~d0G`6q5Ogsyg zLjIv=OlZ^a`Jdqw$O{%jr1X`ZXOHJepHHQ{3ewCZGi{_Qq zXouNz%=L7ta7}Q2f%wniQKCwPMtpwN6RRy|eS%r_|4px;VKwRe8jfj}n?K6_&A-%A z{@V2a>OV|vdJpfH$>u-oHJhpY7N7`E8hA-_PLXZKb#8gBM2@u_?|;apf=kW0WUtf( zizZs0ulT9_m0=-bBqp3ik4T#tMtjVfaZ_p-!~ain9?1kLAko5!>8V%}DJZV8`+u_6 z&zX2mjp5J}Aqg=d;eN^OY0Sids-i@UUuRZs&Z`^>_XlHr%FlHcU{)xq4I5=v3f zI*WK4MA;~4o&-ySH(^(p7~+Nmg^E$D+&__f{t6+ns5IfGC1N=z^WCXqAr>QMF_kqg zCChrEZiY8&PSw+_?1|Rf*dfST0Ke!_t8X?9G|DL$rLVN6r4TziG${~a$o@$#)h4kT zT+m7XQ!efG6s&FjyZn~`%)=LTM9jEF3`C?wo{DgOeg1!1Q<9=;9*$V(4)Yg#8PZOI zR9V8revWCO_g6i!zoZt6TV^pbmy23$))z|F{Q8{yVT)M}GWSm{qG`w}dH=;uQ+MDi zc00}eN$VkEEG$-6Osn-K`EP6MQf)Td<17gOcRgwU(R?+<6rOp(2~%r)3}WrmI8!v* z6Q-8pAo@?yGaFZmOz!zBD&~dB7(a!nwKV3Zh>Mtgs%S?__|Na+RKD`6qUfl_FqL-e zq>3jRxhQ$n*tno2cggwg5lWrfSRM=9!+gbH*lZJ5*byejL)3rcnu0v#&u_hj&)?() z8v+Gut#bGUdLbGyBK?2ly$N_`Sy}J9WsnG{K|Pw|bU(ec1feli)eWHqPpYe`N!inP zstOEPnxv9cC3J?bGgPG-&djH_Il1Sk z-2eN3|L@vEcB;7ddG2#Lyz&;%|23~j(=jqm6rTg+$do&$fFL#fjm#TXt3AtCkUOYeEE}zga ze`D9v^HKQ>XBvZ{=GHr_!cYNY*d1{V(@TsZq;7~5>zQr+FNC)2 zlIt4|MLTlY zYbL0YKMa^ZUfvb`Q@~5!V)=vrBAk=wP#T_|J%e@Fh!DOy6%c>tF@!ulbJ|+3Q zmR|K5{=_xHxAh*6-*yS&`dIP9bX|C`tk;lx=sjG#_|TR0z7P>C{rxTxzG^&0c>s zo?nfR@IT%w(pBqeKCdsX^WsQ9k#1fn_qg6Gj`R`fVo~mKT@p7GfcX9o$UUxa6<5FS zirnM6DvtMw_*s+tL%MG0y8R8l?mFUYQ|`a5>m^-3C%uTjZMpxQt~RNq%q@Sxj zKhn?Do*(IFzvrj))9v5yvAVYF+M#RL`~ha^15d>s1oH=2&>VOg|2}B%Z~z&kYyKd0 z4#5R~Q|Hhjf5TDi1aUnYbhe!g?#F*!l!v=*O@n*Po&JTpZBf%Tf5_bFlf28KZEU`u zJ!{Xif3pl*z}dyiUn>;*Z#{N<|M5F+xwGE}$NHm5pmKKWl2z()9pZDE6%2kF2M^tF z<5Qp3{q(~(A31vLmXNdlvE6q1ho|~&?wkaAFW-j;|Khz^k(TrahtGsR+zjbpf9nit zR_lCf`h+NAjQZ}t4zl-zWz%-VUn=1WU2E>WHh z+~o4+&BvODPaL*Sz@NRxjf^I=FuMBL{Ioz8TNb4~xMK4g40do*B>Yjhd>^KgvcJ!xRq)-QeZZPC zPh-3gkyZC#t6zq$1N;ueL+_V2+ch9!$U?U_y!|Jk?h z(A9!x-?(*y`@f|tocLSPwdZ{|@_AkF_N$z~^&d(@8o@_hp^A#;5qDcHapdCb2aeZ z_AAtDBmGc{TFs_$V9qz}CO%SgQ)9gGjAvr-^`4Qbvz=q-pXj$|gCm%!**|n*tuCe#UdS&KaYyVn$zSi?^ zm(p{*@3o$P4^-Y4cunVDtfx=u8LxWH=ieLjz74$VzlZ#LqtbJ{@3o$PpIUie;5D6p z4;9igUiF&Kzt|sy?-=dpYI<&5tZ!dg-2AWjd%E6tzxwxDd*7S%z72e=y8gno_P*bJ zmGnGt&$X4FpK+D+e679jGp~}KueJBRzLK8J?o{dzzTnzQ&j%~%`C5P9r&ZGPwf??C zh4gH5M9x39i|M)XLQlud7yGsSKELjoL7?W>dQmyu*Qk6+I1Lxl^S_7p9Vw*ee-H0F zP)W}hl%5Baeg|G&PN&%Kwf494(z0Hy(wBhaU?n|Y>+gG}lAf>i_Z`GW9mRo|(m0O^ zHS|Kgb3+qFT}z&HAKL34Nf-P7W!RICeGzku?6C7z&1ZP6=Yy86abH|};*T%UtIct- z{~oXK#rv)4eYSLMU#idVJ-V-FAGyT;zg-&05BBTfzxnqYc%8q`nyx##N-bR$(qCVi ze|($Xuc6?@_gm5T*wM9XpZDwe(tNEHs($=6fd9-EV83|3o*(t^H=yf^uCA5;Yh&ME z%D=~(0Smt#{+qwwcD&F1{+>O$N-bUDzU1&F_J_)2%xvTNjy59C5?St8KXBUC5G41x zY~fM%3e91kcXwVqD!wRQ5T6wcUKYPVye593_>%ZX#5>{_iQCV5_+BjT75|X9B_0(oi^s%k;tS$U@sxO5 z+!F7K?-sY6^XE^CJH)f%F7dp$S3Dyg6<3p|t@ul8ieghID8&Lur)R*r0!Xm8QWN2n=3E;%Y zG`1Mz5AF;Bx2p5AH?d~fBFA<&#JuZaEOg|yrwuH#V+=6L{MEEE;u+f=)VBLV7`WaG z^QpPZBj#h+S&3X+6>sP(l-wO&+6HG6*iB^2c65o=OK~4oZDA1*yo{U6(ahjmo z^9t?_>~7+3PqP`GJR1r;t-pRV2^}hEVsp~PhW0p`-E`44ib~CF0{pW*sN_P zcaKHeS~H7XGO=Y|z9e1SgJ$~VwuQ#jP+>EZLYm{2h-qEtnTxZQI1~G7#YnDn=f-V*Ji;(76h#Y^Hp6R(Ir zB3>7xKH>AW#2*!Ji$5mb6{CKke%rLa&%4D9@gIqM#i&oI-zQ!dx5R%eUKD>^ydp;Z z$@@3Ne<#CK{&Vr781*~-Ulsp>ctd=j zcw78ZaW?DW`@FbA{MX_*@980Nr{upT?iT;LxGCNekBVO|UJ$=Ryd?glcvbvL@w)g` z;w|ydi7$(PQJl^B`@CA*F8-9bQ~VlnkN7vlP4R2R1LEHl&x?Ocye$50@tSx^yea;) zcw78B@viuOar=1>{{!Mq@$1FC;tlbr_zmJk@$ZP2#lIw86TeX$?Wbk&rsQuHZ;L-8 z?zrIL`x9}O_$}fd@wT`reyeyu{8{n5_$S0m;@=ami2qU?=Pj&=Hza?XcuV|~;$87i z#r^Xh{$CJxihowzD}KAUPy83+dGWi%OXAOo*TjD+-V|?&x5caCU9p-Q>4H75tkpDi z=K0u+2ClYX%UWDBmHk2Jjz&#YHaLfUNu#lV`>p-zo?+wKL9AfYlg!;tE*RIsvojMd zH6dcl=_w*I%&TR~$%~ag$M)$dVb`Wi5 zL<%AZA7pMw``jSXuw_=-UMxF1HjRzz(DKS#o#svEAK4vk6ZhzMoEe+d_f^A{+Gzi4 zA7Xvq#Ml|aRx_q^0zxnD4n}{5J_XxieA}*}f%h;$a#s`ummA=@9=86lra$h+!gu(P z^t~HV;^KJ)p%+n}nEU2nFBU>nmWJ7JH`sLT>H#@zj@yUCvGJ+nC{dMnBU&Et1t) z`jO-*KgZ4w;lJM>ebCUKu<+;Irt}<~L}GiHMzN9Hqs<@pD~HDhd`WMHh7>EM&`Hjd zQ!XDd5x0cb`+NAJKf?_=*}W=<`aYCQjE8Z@XXDg?RHW5zVOPnD=!w5e1F?+ z%*rKfZxm5M_nPvT?lt9a+6roFhz|}%$uebI;Ks=x;U3|c(0f?cPwxgF!rk}bP^N;r z@`+aiv^V&BM*cza86FvFW!!TYHiv3{w&&EPKXV_MoSHi~>ibMrqXf*oFRkPo8l4&& zQmQd`Y5qXtrRkQiw`|X$o0>^G(6LwUZcAw?% zJ+bC?0hTk=5~tHYoQoB^OD= zJ!HlEs$npVqC5o}?w;RMZD2?L@aOJ(eX5oZu8sCmw!k5Yg?qgHJ0e~Z!~Q_|iWv56 z@|yUpctZ?(G3DE0*mKD{V%THI*$e!6lj4RL_8H2%#WUhwG3*umL2l zhs@2|*)X|{!TyIm7r{tx(P*=5#>$(y+;_#bjTw=wxPj^jcJ;Om=I6%elD%$t?7W@S zWz7mcGAi7t%aGe(sk3H{?M;WhuJk}_SKAF^lh|B|85kS<&J9_Un!hNUs`aR!)|0n8 zW=6-@&|p#0n7Mn-kI~AEqaAPC&7xd~m#Cq0`!IJEu>JS2y>o1LVS3o$3!7|AaT`E# z?33+z-NRShe>t^{AZkUir#%Zy#(nP4s`Eo2JnE9Wb$X_F+|YR&TZgqc#jQOFz#+Nz zAMx*v^UldT?aoW$hUADp%EP|+4so~SKPv7OuZTy*?-nnLe?q(}evLTnk2r6b&)byz zf_Pi}!{Y449^Q9~8{*fBd&KvPn_{%)>Hnx0jb`$q7@w28Dqao4f8r2?t zG0t-(cdLAOpLkdDw~0IM_4j#D+$FwG+#|kM+$Vm4cwYQ|@sjxE;uY}&;&t(>#9QJ; z@wWI);$87iireq=@V-mjDSn|i&R@s*wf_E+<2+GvQ~WaVs2JzdQobNYsYQz5*dK@C=@b9BxFvprcu9;RocgQc zHSxOmZt<3QL3~;KcJZ$GN5t(f^YEghMgJS(mx#N>uM_u*Uo0LFTNzgTv8`Az2&p=- zUEVQh7NtAJGyS|gmf6;k#Hj<*==h?XMjyGVY;xN|F+aXfjUOHX!pH9~pJ6?;kKCGL z?DylWxgl#wP7b0ohDKskcq2n`Zr{iSs|YzhRp@G<{&V{Sdz{)!KF&5l$b1z&s))O+ z&7HTS7-*Bz&XU(K=guDVVaL?Gb4{KJajz*GJnTKXkL;f5>g80klbS|Fl(RJTL0x zGNT?R?V-|8P*B)!XR>k~c7kWI9AUrRG59bBU4o*%@U|W4`bd3YIs`pKgokylI<7COd z8Jv1%4&lFb*^9nlE3n*15{)_N!=KWD2;;Cvjo<(uJGP>b?6Yv6uAFcocNo=LCH=5J z+y?XVKlxrbXxWf^~ASZ70nY_Rik^yW=>{no-M(>U8IZoHmcZ+ku5F0#97c z+IjJ)Fo94q)l##qVNb|2ou6j{`w6BgBoA>%e5Z&qADlbon>=^B2V{lB2y& z`I;E@GkH^t_AdFd80~R#_A2*pN!%$$dxG+&ctJcMM*D>FmKg0F@`4!c74njJRJYzL}larQ+4XXI8L`hy%IZHTd9x3g3n>! z$Z=~L;92$YGHGWR#mg1~jCw_%fbW{e=iYP8%wxXqzDjsMtEbG8t5Vo_#zlHEs_XMZ@#s(P4jY=Eqn@5(^$`p`u>v=Y$Wl?@Co`O+Gd3XqZsQ(^j z*R}h-d_f{1Z;DZWkS~c*zma#vD4)q;Z$f!aZhyf2Lw!f?6r+46_lQxxk_W`7Z^$h% z>PPaD7~hb*CPw*4-VmcdOx_lwye998Q9hE}U+>{V{Y~x?qkbj#icz1E2gLV@=fz9n zB{A#^)DL^lYsD*{^nJ@wA5p$8{r8AB#qSkg60eAN#2*odJqPs%{mb6q?*scExkC(l z54ltPuDDZ{$_+`^6h#)IXGOiPyxJ#i(y7&)(?a zM|*_aE=GMw?i9a6+#^Q)OL?Cd?Im(c40{ZDQT!osx9l%yPf)%h`Kowb{L|t~;&+R8 z#i;Ljf7`N$AMGD<)dPhJ>&&3>|^9*F-kG=ruYNmZ87Yxl<$h)E^dF5 zhv$RhPVs`cSB&;8@9z_TSUf6zv3N<0_9OMz#Att#x5Q|2lXt|ZO35)l3+**>+nYUn z?-a*;DYR!OZ%B^z9JyQklj5cr_A$y^;x~zx#IVm%z9xpfjl3mB`<%QZM*EQ5cEH1D zWn=M|&#f<1qEN7QPjNy8+d+P&ET=J{LgvhZ@XO?ws{xY`sso-9<&rbD2R6+U(fIQH z#cSLT+8vyKbdLLR+W;yi_h10V%msQ7<+*vt^%HaAH@fUTS3mhzmX}6!l7AXxEpv^3 zepc!56zpi|7MTk702j-Ix&y&9N@ zHF0;nJHCoNq@;ep>}EC}X$mujtZR)f{TOOO{9@h=YRzKRuW2=Lntg5;iAieFene!p z2FIq+ex#ok@Z5M~{>wd%LJE%Y;xP0i_j6|t*qC@?4X-7(Neph%U?he6)F2Efg^qBz zr};q&NA<;$9u5F2+@7A_f;(oh%ti_eeVs>{^h~Gt;-P2r2PV&@ZA6nknkZghw_?XVzepwVA~)4LY1#rl-i=HXY>@io%3|@xj{9o=sRh z*Ca|M{=!TQ1}8&khNec+>0*_TO`9C1-Kj}SpnK9Ek{aZ8EahxiqpaON2NTXvy3LD~95&DCaX%fcBB6LSnBxpR1A{pV4?)m=}um4XkgoAM^Sa z^F7ENV$5G4cZx9|gWN5~d<=5081pB{17fTvAT$T41u`6J{QFU9&3 za!dM{??R6DEY_Ql7bM4g67sSb^Haz%o{9N4}e zG5(18E#z&Z|*-Vc7f&L;n@&l?@a`dOrCLu?E3hi)mx1NtrLXPowzI)*xOZRyy&A(rY zch%=MKG%;%nDr7cB?!w~t?h5KExiR9?IYM99&X;Z-sSO${x^A1yeW?L;b@vrz9RW& z#cN{ppWHvKAN*7ChUBn+P<~1LbK+g`&x_kvJv{5;PBH8`yuU|`{u#MX{EOn281@p% zm&EsqSH$;;*Tt}Jc=*Iff8|0(fh%}081+%J3AABn@>^#|g%_xSrh zAa001BVPUwes0ny#9@E>6LGin|4`f%|FJmM7yhbvRPqmt7sS6KUKYdN!}nbi!#+da z6fcRl#VBtmkMihK;$6udKPO%m!(KxF z*2J*)kvGI!;!9%KqbT1I!+t|pY&n)vs{n_}3z z7@lqMig-u-HgVX)eqEfs-^2SZafcZ8N&43%Ml*oiBZfVb+$V;8nA{Shej~?v!54@Z zC4ZrKMU48G`kUfy@wWJ7;$1Q9>D2F7^YFu-NA48EzDsV3KPes+zgs*nM*UCyCGn@l zYvK*@mN={YaFhsbGCn;d@2A?_+B$*N$3@efu{9aPPBS!!c8yt=FnxIv>zcyHAiAJf)*NQ%CmSNYe+zwS->1WfrqBUlxtlGqCZ^yN4*pEF> zg!C+|3>*VZUAxjgAua6nkT1v_nw=h}C&fuJ7JhS29p$|mvqmM6D0eSKQ+Yk39W7(`;Yq%#!)zRA zCKW7-1^34AsFch44Q!~B1O;q#?9usOer^vB{Gd+00bW@tM2o3w?{_EImxOrxV+m2wz4jlAeN@#d&F88Q2Z(*my zA{kgo@8Jd^dBF1d`ALK6Eczisb2GEp7bJc2aL2NMY90nf7}#HbmJfpHHibh#||#A2YFmdsDhgS;>`hh@cu&4N!v(D*lO9=^wr;1g0#+H2IIjz9W$8FLfPmkoD-4t^5+3b9Rw5PGIZx--elP@ zVS&Z3C}&SO)_x=f@_ntVdS+eE0|Uzetr{!uYN}xzRqC(-@8F#FoVu{kM?Xsvxs(&Lq30 ztsAnigx%5;an6>gaw}o(j*u2Ym%ICV=$vuzYrgMQ;W;QD<}l^rqD>OE02J+;g<_`U zjQYP6y`}Po^m^FYx-;{e8sd?dTFcSIHw$;+YZ+m*? z@;T2&D1i}Wd>t3!U)XmZVbJvfZx5mfCijTZA0ju!=|=rAHHL9k--?PZk)9?seit0; zZqW=Yc>((-{a^Y}Jl{F&9cLw9l^pg|>aUAoUnXygVgDs>i(x+|?}}kRCbxgsp9gz4 zxl;`LHMv{-5^>PYnA#c~lI0J9$wI`!#t*4Er*9O$_@tc|#0)GkHr4 zdowxuFR-_hFG~*lH#z&LzaQ-L zHs(2rHV%14lm6vjIuF_Ad=>oDWdG6~Hcimyh@~b9?@*uj>*Y;orn+-?t+)7}Pt z$gLPjn-AhiVW%D*xeM{^?IQk-iRl&)Yb9uWi{+NFtyzsq1nnC1$k5W$2ZIbtCnshw zsNfZBd=$PF>g)3uUbB4(D*-Y0q7$d>A<()_>*iw?fYmP^Ln!+q=u|D1_xZS7xjwR} zwskEWHCC~S@}%87SX%e=yCjbN;7}e>z9u=!8}gJPQUtvEd$~PrP`AEJjMtMbU z|AdF{HR4V&%45pA#VBvc1L8M{7sRg9MmVYXJKFzE9GgMmigU$ogh;U_L7K8e}iXyR+!m+tiM{AC~6{ z^n_qqh|;g%ZqLjcH<%IO8%9{JiB=WLH#1$>yjg4Rb0NFUdkyz!T}SIP??KI;cRNLgSh+L=_@C;@`@x*y4e^ z{n(TJeg;L`gjD)Vd9+}u52t5DjMzMjr&)aD-sYVi_*<6e_9J(ayV((UY0nK3VDGqCzK5$KNB15* z1=KKm+-GJ6&tU;+%t(rMX5m}Y!*EaiS$|Ba{jNO3PgJZIA`iv4vs<;Usj|yYxcgTs z>Z5#kq}|u}wCDf(#9d;ve<|+~qrM>biBUd~TjE!W7saSAC|?z$yd-am(S9Xwi(e() z6~9{CzLCmr>UWA!zLI;yuMjuID9Mx03E?yI({Y&|V z80}~BmKg0_@?|mV8*=uu9)8p}ohd~muc*Ah?k!=dt^w^oXS@+26uV|!BaKj$!+q(PQjFpin6R}Lit!-n&=*AcJf{J=8 z`KoqgxDSt^8baJf12%V`nPv5-$Pag4UvA5eToCS9Tg91~V>2_b+~+}v+BkRd`^=ql zzp%qoA-J%!`c8(7Uj$B%Pwp~qCL;nDK+)#ln?7NwFCK5PY&8UlUZ5T=e$rIWRNT>4 zuzQo(>S+eWtXS5>z(O}zX#ESC$0je{AWogWLa(VbU#Z}ZCQUw%34I>3Xxb`Tev(SP zlgyhlu!&l4a}0H{{c=6C(^-%)UpMvGOz!(jwdSU=_Ijj&B&7S?-O>!J zUK67!O5PH`QG8j9`4W_8zv$t^csRKs{wZ;{81tVf?-gS{0C_-+@mlh{cuc$`eusEX zjPYseZ;CMio&&~b$!)*n;eVAl_J@A8xFI=`v)?a%g}5nxY1}V< zlXyXl@qXUFB7VDgO^oqq$~VNX6>o_#{!IC{7~|dK*x&gz;$6uxo=$nkFZ=r~io3+f z#FY1nG5?1=AjbR*^1K-HEyzn^6oBM)F~-lyo8kw=+v5AhyJF1GqJG=2c=#~hPwo`| zn7Bub`6-l-iZNe{eBP3IeCGK-MlauVYT6$btqJ?qvaoVJX6R0Uf*-A ztX28w*NnitHl@-(*b0=&_~7KZId=bjZxatk zvAJdb&CGEVbl80h4@!1`hUJr3m5=dkOw}!xB-JP7eF@ktVBwbBVxu^%p~gKGMES!I zUfq9T)HY+_3#ON{L16R>Y_W^t1p2A)DCPcYyK`^UmfNM0qqwWKKQSDuoK-xDC5v6%zxg*H}M*euq*W0pP29?|vdUSFZUBln7tUdVl7 z)PLlb80}T^vKYycye@8ux5Q{4QGQvB_9D4$%b$--MeY!zy+v+_(cU8Wh|yjk$Nnm4 z?~$95qdnqsG1@oec`@p5@`@Pk4f2K<^)b1t)5C}MJ-I1H`<{GRjQX9NJ<;{giMQn6 z-QpcF>PqUj{f6tKJxlHs>+`3J*Nf3>9G*e=`HS+iH9dH40tQp=m#xWkm>S@daiD3F z;%vJvjE7;rcqDpMp|Pa}c)KMjpr@5%QKOH@z! zwmrLt66FuJXtATRtT09IlXL7WIwJhxDXQis-LgO{b;^z4^+KQ6a45&o@^>G*sS{yit%E+4FZW0Q4SR63+ zjwzApF`2cfiw-vRZ19X7%;s-mtT~jnWneT*Q63DLAq`vlxD%NzK65VX)!Ff2ph5YN zyyJKZg6<~%>LgC)54XQ)+@Lyr2l*!-%Q5Rd{6bbq+1BRId=1~|_xyXId?h!;s6WWv zVwC^nrWpM*@~9Z)EqPIl`i8tBMtwnE7o$H*-V&oeBJYS%|B%}*dH7J@kvqjGCdo}P z%5QQ@jQ%)zQH(byuZU6qk~hStU&*n)1^sLCCCTp=cW6Dx%f-8rPm9}s-@}XgpZ7P! zsQ<~`;stS2jQ%aI?FKC!tPg+TR9doJKP696d;&wX-hoWEaNL{0L;&09B;Q7OBSfuWz718`J#Hhp;aG+ogbn+M_J(I;tLZ~VP(yi*7~$JlfXy49Fw3uv zev->0u>9f|Mg}b^_(Nc4EVW|GG)uP8he-(o(;kLxc?Cr1Qo%T676LvdmFx7UdE$;| zxwFq8*S?%gFoo&O+P45zArg}9p*f9XJ(0(=n7PXbTf>f{6--L>9}l+~@Qh1yKm?qv zY{5W1-aj^r{X7sF3#vSh7&ZBXZ6H@Gt!eKm2zfj3?8q!`kC5f=Hg2KVR$whHpg}s9 zDt&~oRzJQ@NzVDm?jhY%e0zd8J3e?0g?X`lWkQJt1!Du{M7F^4YUK~Td_((-ye>w2 zi@YU9dy9NojP@mYM|@V?_DAj?+N+dziqYOA_lVK{Bae#F-XkxF(f%YaiP7F9uZz(h zC2xt*{v_{+(f%Yi{@BBV_9wYltY}CVYv*CN3Vaq{Po&|{3_Y(@oLX-z(u>>EtQ;t} z7h~|#Bs8E}!om(e@t`3)tqrX(&A5-A6K9c_-?^R8{g!zN?NA#&vutdk-~woEVLLvC zuGBQzKm7SKZ4*Q5uON5oMNnQukf=Avt|F!)avNOvfzjT{VZ4!*6P5~F=e?h&JX zO70V*eM%k`qkTk<{dUoQBriyg_7Hhl{6_Jb7~?6FZ;H`=BVQ7u{Yt(pMth08D@J>a z-2UhOK4>438)CFS$=zZkF>Yc!!E&!={n%}i!p zUAEH?VG08)*?AZeit{B@p3Dy3MI#JaSA0a2GwzPu$%YsEn`zx5nh~&x`j`smi^Wa$ zpj7dDiFEYjoy?xjl*J ziYUpe-eziNS@c=^qc92EZ>-7-L;6%emvRhC1XX%v*%QWwpJ2wJCs>K`gfQP&d1>}1 z+f&O*D`WJet(8r~SiGgV!;*rT0Q^pAmPf_CF!B=m^goO+^xyqK)r|Kt`&GFqZ5(OF z!ha3`#O96%3pZ?MEOPD5F;wcTVj-F7jyOva`0Wyy0aC&<@4In*5fi%CBS!m`+$To+ zlsqp+`;@#WMthdLDu(@%yeUTeo4hSXdzic{#{5ol``>!_Fh7;t5M#a}xkrrlJGoDc z_A$97MthySAcp;vye!sdP8ZG`Kob{Z3AQ#E2KB*t%KmRl-i_Z7vQ@1aJ(Q=zrvAPyXR&%n*4uO* zuLY=R)AY^#Uz570z`wXUI#{9x!bSVy5gT=T6V~8{8 zSj}YN9zlxkT)10zoYM=?J!HdQ@#8U*_mC6&#J17dSsWe`hq2(E@P}Q8X{=~B4bBa; zKgx2e>%ypDpB@nhdx|w#SgdgXGPze`niByV`KIa^wnQ*g@FKW)PfI@thQEkyi{7vY zR+{@}KEd2Y&NM8RO0(nMVu|pve{Tmw7G7`$UKiFem7*5q5!;Kg9tq_Sx%qdV-;kfl z17hSSa!ZW-M_v%4{2{N1QNEEk#3+Br+hXK*a`yNBJd`Ko4l&AGa<>@eE4eAg{Au!l z808l^*88CRB)23-`9)q7qkJN-iBTSsV|@_H2Xd?rLU~Hwls?L1@+C3KC-ROM-IPUgv@^>4N0jYU3iFiD7l{(ie9N+X zvxRT4>&A|!m;1z9;+KoJ#jgLNA48ARNNy*{Y-hE_?6;$ zG0F?dm&Iqru|5#_hw^pFk^jltV&r#n_KzvQliS58Z~Xp`yBy^Wxl?lFM{=zHL;fQ7 zNRIsEaxuye@`4!oj~wL#+Bf7S$x*(LBmbj3aec{A-jO%OD1XS?Vyu@T?}}00klX&r z-v{Llxgkb*N$wJ(d?fdZQQnaI#3*mbEiu|p(@wyo8BkITcK}&1JpUtN% zu0k>{rcm@4EDx{`SIE#=(Y@FS&h1?seq}G)o>z8f)@CqlvK5*StQf6n6k)S15o6Vx zl}Vh=#lp-rYUSti4M9vEL^9E zz{T033@w2<9KxdV3FVl*v{@9fb@Z$qs>Ay|?&D1n54P|lg)-LnnVAud6)d>q`6dOs zfaZmz0HkuTI4F)M*>p8nHnHfVf$20hrPbe@fiO7(cX7sc{wO>?V@O$AmKTJ&d+s(n zgEAHNhw|zW_zQOo2-s>9Mn!suYWRFx3JVm2gmDAxW7ML>DWBC=E>~fiy5jhIvHgen zC#a`}Qx{O_*B2G~gv6Ml5>dkIP?jS$_H9_!aJzE9qkKAJt`>|Z?mGvZD$3JA)3 z#2*t6h+&_ld{Mk6UKL}!o$@%Jc+w=2MWj#2*n~5@Y@c}QGb8tTVd%AZviQfvyJD=b;rq6KnZFM! zg~C6n<}Oy+kf-&Vs!WRwj2MH-YfrR~^3Ia2O+}4s9iB0@9w7I98wTyvF>6`P4wenC zlAEm)qNJZDs`#L3w0@Et)(ceHw(sOVnnT!f#rjUwsc`0w(N(jDS+gx)mr!W{gz>>z zL@{P#(HHL4)-2vqa<`kzT#rVL9V8rmxIOoq9%k2$jAJf})b{wp=1%TM$k9e9?U7O4 zzrg#?h*saEr#hUIxjf8pYAvdhp3(pU?0Wce^vCEX%OS zxRL(05kV^vXeX)cOX5$!{mDJ08oxieTat$r(YDD%cpAkhHZJX;WSnn_NPWc?VhwY< zVqnx}dwE$>v`U&?hEc0cxALT!!X_sRQ?V?;?xN_I>`87J%LR+nee!>j>(k}T9X_HM z$o;8&?4(~QH}d&P45ghw#G=CXNVH$rd!l46#DXiLk66fGSL~l4o$cws6#c8@)skOD zy%fiV!!K*)g`Ry;p3+GnG;@>OVK5Z|;u!YG_RFH>yKFvI_RSV=OAqt<6a5+Tsu)!j zx$9ZJ-#hv<#pth)J09--qrXD#79;JG`^4zKkVnPne~{D=jQ$Wg_VY&nhaCIiq5nhflRlCm zc|mM(Tl~?Ub7rD}Q%XIb!ti2+*U-(r8X9_{H5{U`FG82N>~Dt@bYU5xxf`IZ>{9r9%{(l5E~G4B75i5p_%FUq^c zNZ;h982wdpOS~pt6r;aP`KlQCfxIC`(k5?ET0vo7@mDh3kKPui3zd^h$extbUaUTA4 zai^GDTh(9i#7sFma`H~p+9rB9!W#V-)?01xJiDADX zM|}%>4LQ!gfIWeHS^Do6w||Yl-v`7EG3+_i?-GAf+$)Ctlkz?>>=)#g_#yFv_`Tv4 zF^cZeFEs)ywVu`c+!bpO%LJ@9Z$@)0mqGc=pUGqF)Y`7ryWk#JbCc{Z#5e`*5MG@X zyXz(UM76H72NdlWCXbuV9nVGIg8>d_>Zh@a!VRX+scP2v9k#RV^D}4p9NYQJ-?6lG z2W@U&c!0VXxB5u;g~4fSdf0tM`GrBQb}?tQgD~nbgas;Iv*OhEe1?X%b5gZy!9$zk zY}^;svA-rFyG9?czsH?wh3AJqSmKBpHxF0A-M?hT|JGe&3{LgA>El=RnJDྮJ zML(t?$bXyc!q&%KwlW42RKh)<4JZQuUn0E+W(zV-(Qv7iM{CHU(Nbl^S8*0g#Jv0L z;pDJ<-Dgv{3i8y+@%w!U4U-zj#yNp%>OyIIu1s=Fs=zXHPZv6IFTWqT>@21Mpap7M zzhjRHbT-0Lgb&Fm4Z91Pu4uaC^Kz?lo0l+zxztLz`MfB+w&mBDr(xN`TfMfsSxT1? z!7;6ed1SD!J{KfdNVkW#!sZ>_k|s0W_EatZF5sKo^X{QDlZT%BU_I1^l1GSnp=4?Mx-tCFuG>61^6Izsbr6`-+V6iQ^I|E`Sl5Il`MvCwZ))KQn#af{~wQtgHv)?u-?{vr|ZWg?VwbpIOeD!tRI| zA&yE2%N1=UQ5>g&{!Q8uNm1tED!Z#Nf~e?zesT)z^MLbu(=9jQ&OqB6xwlC_eUIdx z-q!YCQ4L{THyk@;+t>`Frw3iU_MGMkaz1s=KJD2}mU(D!9s-}>?);K;D6-Y&Q9!$U z3%Qd%Yk%2kTX(08$MF|?{2p-E#}~z6Dn)!yZK579$gq zcf|Ov)`ctnb47GV+Gx3{>GC)!UdbgAk()JcR^qzk>S(oScGB=jYzU_vHfJ zIP}GD;lD_aUvGc3zQNNE(ib_-3qkrOFG`M&MqU*oeUi7t$RB>c7_my;5yO5#ZtL*p zAwQBk#7NKNE-}(CxkrrjO>T-|zaWo_k>AJ*V%RgtOJd|N@~RloN8S{}UP9g$qkJH@ z{YMWk@+-MZjPimU``Mot_eu_X3*`f1lqckQap6<&&%p^SI-Q&1)M%eeuXMz9>@>$+ z^cJe`y}?2mcfy)~Ze-f$aB=c%WfOECk;>a=F{eG2#YH%{2Fm(ZR^EmvnEk55>)D2;?@{*@*He!&)83BY{VKqb7NL5 z+L9o|4SJxqS{5aNwNbg|DAuuAIT43&6&DT^%ZD_^Wd0V)4TXgt9EUYjQmSp5hH(*V?Hb*n7l4IJ|p>(82N|1 zD~@o*Rr@I-+Sn4YDu#;?Eh4=^jQPWq$Np)U4@_Q=9P@q2yJtN-nD0wol03dkT$%4C zv7zYD*jT=9&hs6bsiPzFSUW#7hT#hDU{&sm{z^2bnO||=)Q~lY*(LKkJb&-?3i&x7 z&-Hzcusyk*Ug%z0j~p}p(?U_StFf@rK5D+kFT!Nk^=yITN168fd9Qfwevglji(@|` zd_U^P`C6|QZ#>?=&uhee?SB8;#9NZDh~vC>d~f=9S@K^MXVXBsV%dd`O?^{gB=vUV6Ph?>EKW(*KA!_De!~XL$M~|7-E6__xIK z;vW+)iPyxvFY)JLK0E!3^T4s5z~5K;m>=)Ylm0u!E1!HG=YRcycwPE`CEgNaK0NQg zEJpq$$NA!y#n}@)ettak^*odZ)Q|a`Zxpvn|G$VE;&+KV-r(o{rh}CyrlR4pg7K7M}0^A zKHdKp;+FVlLSOvRkSjg>tT^^J`@A^X_n#HVerFGg+u!8j`HnTM`%aJVOX3bO*6;9ryTn-kL+%k{eGECyd;fKDQ}SOB$9`u&As&@{ zOS~w)U%V>*MRDwp_ABBI$zLbFBz}`P&R2iAct`SOah$LIC*tVuyh7aeB##fYXZU_` zUivG=9g=@c+%0}U9OtROUcBFV>NYN9V?lxWN3{du&RY>tWq zxx1SzXGh!ule^O{5Yt|Zb^$IuIXi|`!P?vuMuN1tT{Ml0a=Z)dY6u>M*7Zx>LG(9s ze_+1bqk(-EY=R^DN7h|B$6kzuF=jf3U1D(1yKsqh1ZA+c}{GO8TX-w%ek+?xhctS zP40^9U`~2Q2nrmpUJBRjD2CLqy0qAht8InE`0pEPbvxFWfgBVf4HG z9Q_?Dm$ZB<<#BDl=NlK;ilyfO3_D4H-<5NrbVKhFEmXh5i(y%?NU}-_e zG#%HfagQh^I_?`W>$3l!_%74spKaKw=I%po7QOxqP>vlfT@AmtV z7j4f5I)$Fxl469L{qg?6>FL3X3~%$+BPS0W>~G$DtRGo->^xFz{|Jnp()TTbPq&~l zG~JrzEqspMcjMmM;=Ymdt<$X=3->f{zV+xW2O`vk>r0-)e%My?Ag>{5(;oxZdpo09 zk+)0U+DG0Y`9ekhWpZ!mx>6%Izn7lu&wZry;?k)<)^y(xa!)hW);RCQwuwB6Q3mND zzVYQ?5xIx6(u=CpK&0Q67D2$}JF~ zD3|ib%kQ(J>rS_ZE^@m-`+7`|z9^S&{n$U<0;1<6{Yh*JUDY2S!4j5!SlRkbnq`m2 zeHNeJi2uF=|2_1uEbGN}0snmgzw2>*tRisdDf*5xPvdu9`P41`y~V9hJGVCcI`A34 zHb3jvjZMFH{i0v9U-D~1*REf7_WWVvC!Qtj59Ghp^3i)Tf6dJFo0y4u6yMRT+{n2c zUmhE>KlkLj>t>$ZxNZiyubR(7z~>>SNB;NcV_<#4$C=3(iaIZT4C2gw?Oo;gY5j)Y zQ}MI?JI<{?kh|ZOZHSwHr4UCQq)v=A* zqlWdC=}k7`ef{^Kr0hqNqwzh@%z5f8npRiPhrIEm##rMSjZPGMPqb2Y>TG9tr;_X{ z_wRe}74EZeKI57DJaq4U2;egt7!LB^UU>w#-`?l{fxo@5A1O-t()G@t^+G!WiR(8$!r}74O8WVma{5{N+j6=IFP8q^ z-3R{BuUr3A*6aFb=dS3!QFSh$mdx(f*+@@HY zbjGx2fz{;sT@hL}1d*JkhHP{3#-QC*P;6Wn9m4{5lWIjhdK=*`_-9jWR9a=(z~i3f?$JcVyDBd#@VxL4K)3Z}{QPho)2e&!#lmHr7V zN5hR4aE8I$!#{RYkj5nMAH|bnV5g{OEq;3^8x57N`G4S$UcbLi!GpnY@QpkSVoZse ziO0I4JqxE~cER}f82mKEur#Zy5+QHExCu4{UpAN5gk5npYOoUR^T?!{KVJ3CIt>)L3o_n?Y z+WJol-#+7@H8w$)A27Xl6DZ%^@pBv@F`u8@Mt4kVVc8sx!+~>IV&BWGFs>FjM*Ot zC-5TW=S?SfmQxmxe!2A{CCrVmZErr7@AKPGnYAo#?5BFs%}%FnF2!m8yZ^$Nm4ntF zG~)$Z%Kc$&srrk-T(q~xp+7X*k5S-rn9I^XJAc<)W^==Qvb#TT8jgrAo1aL7&WS!w zAJfingXgdq&#fs_K2;e0@s`;!9v6|F=)3jVXx(FPGn)||(U{K+fIhOazm@Y!~%D-rP)ggbyOyjD&GR+2dq()kLZFU&nylKpT=j$FjdLt3wkQavRrRs(D$1^!wJgR9_k|6P;UN*a;}FKR9ci-bgxXL zO4D^wTh5JSCyt#u@!bBC7N9FWsGxVnfEV=8Zkk2w4!saFs9{|?>YE9(;SAyv={WA< z^Gh#K@aM`epa?sD$MI9g58vi*a)l6<^h!^3k4o|{;>n?Z`{BO+qlZr&-tV*S(W^YW zC_j1X#IeJ-)4Tqgj~_kWf7_i$4&Sz)&*gAiIQF@}^u#MZ@5Hg&?>u$viVyr^?k_#C z@|~*TeD)p3|6e`N?yGyw;Ul;9A3b*4;pg@r>uX-Y=d#{jpDdh7=L-Im_4fL+H@;5t z+wSM(zWNof>-4S^m;32gyv^)=jvu}4SpTWxw;#Ln*{Ajk=N`R^M<##v(IyOf&%N!= z!$eu*t^3>r|$8I}z z@?`&sV<(TD>OXbot;g=z@8#ifz5W%8QVY&L_w5Z(z5iyuLhlG$1`gM>0nGpAiDS1M zJ8|OJ(f-3nkDl271uA-14R}RgJ;PzHHM(bHdg^)&$e}{9U{u4g=LIYGSYxF82>Oy` zM~|O8d^3`xzWeRRpLOE!spEI<`)T&ouY@4-18YD#e})5LR&$-fx-lqg0BTs_$m`oH zD;MgoD=MNrWlcNlX7dT)>G^)H6zxZSd2VF5zjfDaKW7x00^Kk>KO9`&S~=q*XpE$R z6tzFR2Zfj5njzaeNS0aNVU;nfVzktBC%OWH#)UDMc+k+a25Rc>Yu-UL=h(Qhr7N*x zrq&x^{OsJ6ohBC+)EGBMc%!@S&+PZGTer>P0z)tSRohdu^Q|~va>N=_sjqJfu;8UH z)`;DT=vUszfPMwDOG?-#1K$VR z0Bbt>CMdf{^s}IBhP+02IXs^aG*zYNX+xl@du;=|0%U>F~ zjX?n)HnyCWo7pm3>UG`&<%?_4*YQNwI6pRprMHR#2Ht{Y&v8wzyRjLsMa_J?({~W! z5X896TDG)kC;j;jtCoHTF%}BL2y6}c1}FvZQOu#)Xd!3}&)IiF;+nlMHGNm!>#2(m z_Z9`z?9|ZIxciOaNA>$Wm1Ws~e)jPrn*CvWx!=_2n!j#*eEzx_`(L9|eK|ZD&2DsR zC-8hMMk}j5@yU3pK^$9mQ{&sOoB4KneMNsO`iF7H&9HGCIda7MtA}9d!iL&r$U@HR z=ZG5nu``Fv8sj}z>e;71hmXc#*|eBl%Yy1Nq{ z$UXqvKg1n?)sa+55c-4T^2oiZgnwcX+saNCx{q0_$M+F>IKuLkjH&Ey`FNw; zDZTt{u5ZI=a_5NA_Fi{d<}bcO1Jj9x7h9{auUsLP$QEW)4J3*#5z{xWfd_hI4)=flMjzDI~7TwnM%_bv6qKxqnr-E7aX`x0ib?{%f{n3%F!Ga(@i|_V;A8XHB_Vq`DV9_zV4Px!YuYclVLz zMY)@s9%<^?vfLkCabK0YEh4k&P3w|C`p^?)w9+xvQW8u$z2ynFm%GRykpZtvysmN7)5a{oHHM=%%Up3)+mvss@!$45Pe1#8pAO0QyT9`) z_xD`o{yxbcu}}C~SMh)GD*mrr#s7_~_nGNN1V%_R4dV?gpgxzAVRYmzU@eQ6*0vfNiH^6ZiR{8hQnkNUcoHkDjE zlCMjC!w>mDo|( zr}b#}e?{(VN$$_@d5p_9N!BFKe!%0kUDpWz!dLqJ4Y_wE zx%=PzDwp@jy_w`5zK{>dJz_uJe@*wdD)M;$kS|o^or<6KulDCJNxq_MLp5T^*Y@1+ z;cw~w4av83jqtTU&i%h6_shv2Pk&32@5;UH2cvvY`pxvA8?u{M+=5i*9v36y)g*hCq zamt@IH2eD&b{u^ zcW-EP^BL%P&K^JPd328qVm3x<(S1L!?6!>a?lIrEe|Xf)L17-vumgqCDU8Li&sajm z>;|MQ-e%96h$KsYkY4f3lwcvp>Z9BVJTg1M@L)+8(kWJ3aZj4VwmB{=!RCnH%-A_> zjx>{be%ntg#apOnN9M3+6}%YI^;y$Xb1m>WU9CJwlf&VDgf=b9ExtdXvu)L7zQ7+} zI+3_3JD$6y@h^C60mvB@Kcn{hNJzLaq~s#9`ThJTWKCI(A>(zao@=SfbZ zs(il zC6GRdYrmeWQX6~|5+CH(DQx&<{ z;xVzx^Kwl%F|+HgG5a)?`_j_9eifJ%Im_%C|MK~?Cd99DAHrMjZc{(gSXaO8iL3qes%dIJy=ofSN6(I8^*RKD zS=h&jznb@DnyPV6X=)$;SwGj@$8TTbp2q_Ub)UWF-@g*Cr8HUNPfC;fgv*N_RGyf} z8L!QBR(Vb-E!I4TX|cwAh)sKM>&5ccYC7JdQ{zvx)vV39pFewa%Kq#vL+i`Wq47zr z6|A}c3i*Nle-ZhCdMrz8{Qn~IiQkV!w>TgNBY@Ee!w0@&s^Jtn0&r#rf|RcgZlEsw zE}NLCWL1;S-T$lSFV~B*d2jl1`PK6u^(L*Tu8EJD{6_sNYDpX?S{OZ=Xc*z7T4UrN5`ID@n=t2 zT;tCk9h(VcdcJ9}v2hBg`66jev~G&~9(~<+ z&OFDf=|-b*QzP89A)txrbpAl2vunO9%_ld(ZP*vqe>Y)quHPB%nActM&)n0~3(qlk z+OXJA$e(ZSsh3~T*F$-U@ZO2#9;hE0Pr&ktLkFMGU}M*25}lbI#I!YEYX)VC`Az&z zeUIUpsnht+7GE6Vx_|4ZT5qG1tB&Koxk=kc!0vQ^uqVlI|5@x!o#B|HqPpZWt?{v0 z%tQ(O=TD7chE0C|#0X~E71+G6Bcj3FvJY{%%Jj-s)j%6pZJMiyq*`e%U_LS@> z{<_UyB8A7g_h&Am?53Y4Jc1cQvm>XlaAS02ymjc{$;rXi%;=OQMgCx6K%el?!CS_# zjs-5kcc4*e3jUtw#;4AhMQG}-IrXDXX*|c~snq>^`REtEu>EQu_qm$h&QH1h|7v>w zBE718Il>Un4gO-UZEyGIcj=n_W&c9)8NC(xT17rzk@x&n`To_4e5)egs>lcax_p23 zj&k^RD)O$1eBpBW{#Hfa{x@a$T1DRY+p>JCB44Y>cPjFp|5Coc{hj6TZ&l>o75Tv5 zmGAGZ$agC8zKVR|@5}d(R^;vfP?pbE>tbbH!Jd`ihQvmU;97H_pemt|5TPYexQ%(J<@;cpUd)%%KfeXR+j(syyx?{zw5u3 z+j#Ggrn~?N*+8jWig<1N>GJz-Wc7L-6}_!5)IYbgqPOy}djFagy`_iO>&;j679LTr zw^Gq-J+fYJv!XZf<@I_y6}{%8>h-pl%IUwStzK`VqSy5m^?EB6y~d;K^?F`ces23? z>h&5Gz3j2|dRawpXCJ+`_m-c#{gw6pU4F2vxAj%^dYcu!jjyiP>v(rLowmNVUazO3 zH}G}!dY3*_4qwmL*XylU^t!&GUT?Xg*XXF%Tm8-Qb2omtUT?Fax3*BPce$ds@+0+n zqt$r1w_b0)qSw5yUT?9Y*YnbPz2%Bt>znHJwkmo9-(0WP_MUP&Xnsq*UQb1D;altV z<|}%w|E*qct)e&3sMp)6=q-I)y-E+udR>pN*UR2pes249 z^?J>U-p)RHD;2%1@2K~0v!b{5gnGT5ir!LZyvg@aoPQUtFY9fbxs~I z>iw;X-r5cIdb<_9l^g5z8t*TEkFBTH>-ARjHl9|m*Q)5Pb=T`HSM;`@Uaz-N(c8MI zUhi^6Z{xe`_1f3U@4NPldcB^C-pVuU^;#9ZrSGZNTdC+R{HJ=o&5B;Dr(SQTqBn53 zUa#W=<@asgT(8$t(d#)pEJmxBA&~x^En-*ITUUwck>&H(Jrlo>i~c_PO$N zclOb{T=8$ax8A?air&`odcCDeyli}Lz2167Z|&B4z3qzL%5C*}Z67Ru-;LYr^|~s0 zYj@P^^;Ps%?yT2asOT*<>-E+vdJF%#UT>$O*E&(J*ZHCH`}RD$UazO3*F06P*H_US zI9adPs_1n+r(SQlqSyGodcBQ`UVC4?-sOs3_S|~C_79iiWoI9~?uy>_^XmQUd`meW zZGC^e-tL>rdK;(f^)@SdYd=u0w_bVf$`97-EmriF`s?-jDtZe8^?C!9cxesR>n&FF z2F}#$tyT1zL-l%>DtcY5dcB>BUgPe1y|w3*zeoFYy(S=xxo_>n)uszwgHRee^2tyLO>ouUXMsnXlJdsDv*&SFg8H(d!zm z*W0M*4UE<6ZCCV~&#%{O`)E0yd+w^&>#XQ?jo0h-RrDGY^?HjHy`IT>y_JW`-);Mz zdc9Ufuj@tideJ`qVy~-}a5i3E_IIlyUwdU){$#D+3H#^TtIP7;%KclfEzAG;1!eo` z&g;tZ_K%gn-_je(@}7#k=Z$4~t0G@nF3aaD^7gls1}0s+j{x?4}82V-~O+sOYyt$P+8tyxqs`EWqC(MKJcls zyit+wRODAnA6=FE7oIZ6@Wy?g)B61M{SKAoeU z9arP~|AF6okE~>8uS%0dv`I>evMUvZh7vNf-XbG2WMuDTlT`L5gzN~}vNyl`oO54C z=Q#J<+vofH>-Rezy2tZ1p4aOd_jR9hzph)q{TA!t`t=jsN>?A0LuuROk#76WxU3uB zWIg`Dr*-i~dU(NkUED;^zVAt0e1o1obW9gl;tkI4)6+My*DZgs9-h%g7pL~?wqM9Y z7dO?z^Y!p8|LBg7NuIj;_ImndU378%@io|67uO#j%k*&l@iECqS6_epH`4PD;;6LM zk6)Reu6_OT78e)&={O?;AM zTt9xPUp4v}GOi!L;%^!}U&i(Ohvg3qUM%DK{Uhn828Rx4`0I~v8BH|&Ol4eud;_>I z(AT^E06a;?_4|)$Q;q#B8Q1SW056tt{r&@RqZ|!?{r=|k#`W7jL}>6>8UIuJ znjvb&k5pMcX`@CT=$Vey#f$auLS7el+N7%=rl+5whZpJTLz{K=o9O8W>*1Dqxak&M zeS1ATNe_3@!;AIsj(WJ$R$cqPGQLlaU%nnc5Z_`MF9^}q2e|1$O??OV*Tq46fxc0c zVI1gZ=;0v#K))bfS0CU&KX{lf4(bQ!L!%7iKtDE77YFqR^z)Mp<3Qh10S}hr18vvU z2k}n^@%zUxep1E@rWnSlTuuCA_3VTCv6S)Db-MZh?;+#RdR-jEPphwhYxOti>I3^p zvVGsahVcR!FIK=!^5pXMGpyf3#-Sj?c!rE;1slf8WZX%weS`4>@HYz6)dx7>pP_&Q z{+8i}^#T8U1sw4A9bi}=@GsWGLH`5%vm$l%0S@>(4Kj=a{sjs+;2%8Lus+~lrho(f zNkeq?LH`E)ePaycfPb+94*18$8rBE=p`nIxz&}+12mDRrboD|10sM`I8^!_u3D zeZW6o0SEkj=NZ-q{EPK)Fuwu(%k-{q00;b&rs~=UIN)!TY#0apGZb*Z-*TE^eZW6o z4+rxvz~6Veu0Fs4|6&Ck@Q+O~tPl7@GYsQ^f2slw_?zmrZ!o`b%9pR76LswaJXOY_ zNrv$v8BbNfO%7@7n@%>YA1vcp3V4=`JL%1D!2IEpjHfDG-z^Wz{`Ic!;QAIJ*PkL8w~RK78y(U3&)37j_}@{+%M|9PNiv?4plctDulr;?Rd4*1h%YyI!h)d#rNzXGoH zzt^ySlM{0M6!2hxUofnnEaScxb#YMtTK@YC<68a-xR(EZ!}?i(pB@gbZ(9F3y7~au z`q#t3^+&6JP*)$|T75kn%#XDC*}D1w*Xrxx9pwE72h^#QKc*Tcc}=dm0gr(9iq zfLorF>t6vMDdSFgy82*z1N`z8aKO(g->^QY-+TppAMk%jS09XzTK@{T*8gE$eZU{I zZ_@(9IB4GmdhNT%V)^@ZFuoM(>I1w?=5Kk$Fm8HE6Mv`6y13G~2+jxlXnr4zkoAl8 z>?h0T0q#`vclIH9{j=1Ensw=5`8dBsbBxHx1@bW}A7?z!;DmhaJ6ZD_C*TdX{SzXG zNK3*Dh>=ccl6N(Te@AC42kDQw^w+<$jk)^R%ECrU*OdNPTUe`CRFU3GEx+o{QC_7U z*p=k1&8@9%)i&gaDm$irH;YiFggDQ{I9gYq`N7{Zek}lzc3C(!nLmI>%n#&aUQG*7gpvyy{pw)at8oRdLGU(xJK@yxi5A zQi;9XRVECE-AZ0)O)aGkjCxNoLV%x3XUVFyzgk1HAFt9;wcwUgTeelT=T_E|OQ~x} z|J3UasY<4ibx~EZgJ!?KYS*xyWJ9i2$lu#W5|ZrMN#-rBTDMX;v9yA`-Rv|SQnjNJ zQ1>M(8#~+9(t#c1=jrS2?PhM(($Yb*`)kj^&)ZFPr1EXkQr(NKAZK@Vnatf?T?_?G za;gcKN>1ui%5v7_dGSzpgH>4${6t{3Z8t`vCrBc~!4BP`^?@%F9bUfV|=M zAjxZ*pE?dwqfyD5yLR)}982Xbe=L#w?YN7FQrx7$LHYpRigMQFC#_YBa+sr<3ZpMhhC$T0Jea8>tHp@y4*E$Bxe4k}5Fo~jiq>VeCewjAa3G;9s~ z1MYs+kJg{M)hP08r3tUL{H|I(6;IWX;byL*r>ehSdh(G$J)kCg)zpKEVW6M0Z@IvZ zhzp68`=tglXwBA6%e$Puia5|$?W-Y!`qr|(#JIe^bg0z_kU@Rv8VcH_O5fbq*-ftu z=F(y;<;$TKF=$J(RGdzE%Gm>D0`@?;l5H0M$1Qap)??8Rlc57^{yZ%R}-Z5uOKIz z)5xjoUBNH7K5NTwSPo1KwSH9>UIXQj&6V@p&CigWl}`JW%Im5iC(qP>`86yjn}b}P zz1=%^miw5hjaaJg)ub7yg`KoxWzkxm7;5EIu{J2DnHc_(liS>H_B1U{E2oaNG&uw( zK)bVPEzPf`elE>FTBYr3eKuq1&Rc#5J0PW9^o)lytrn+@dPZq%m)g6SYUJU6; zjS+|eJ@uqf>iWOVtLj3YOqM?{m+Loq)p=DL{4FlF>ZYJ$*PxtcBKb>BDvv=qP0P~C zsreZ6t8V&QIaU3t+UjroG!w~Ra;i8QlGF4gt(@Ag)CPaEXRGd-S~;~}Lvq%7aw@-u zILko>s~t0+;x?^sj{(94^=8iJ4uO;lGdX#m)1`;clGwS zks$SSMb%o$DXRL2^j(K^f2g`5$bQPZmztOM>l7<69{PLRYA-?M@BOSSZPhoGDjZxY z^l?>5RX7;Z^>I}XQ|n9JL)xmFx4sM*XVr4@5TP%l;;O<`%}d^b-l8uGhB1v_Szc-$ zO7dX1Rm*GcA*9(_xqDz$98}*r$oJLK*8}P>{(cWGU%)hS{>pN4fjejhtRh3C%YVhNj~ZLro(C@>1J&P${am1}2-T0ZeUN`s45E+tJy-Bjnqqb5AQ9 zOECOGzAj#F9-1qsPMflmzF|=5_GsPGMv`#o(c0Ep+L}viExS5*llZFi)VSunv%ilO z5K`&+yZZI??WUR~OK*UbmR#12o|Ro|X*9KvCKFzME_NzQ&VC)b_*i?&TQ_j*rn05_ zxOH?0i|`6hbRHNN9kFipD*WOh%?T}4g;HDc zljPzI%W1wuQD0FY$lXn!u%@B7yXg`J4cy;bQ(5KPs*Uu0jk~KV*5RSP3H^sehDw3b z;bkWc85&+-9XMYvSO5AprfwZgBcr63oU0r0TS=wU$Jr$j7S9N{e;( z50BHa+)}m->;fHqvjCUkrw^%J0$hrlL0md-?(6UGAZ`8S-QUJRDWux=Ue2CM?>CzO zcX#~_(&3|NPru6meO0^q9hKhmF0Z#I*Y9s4zi`6_04}ZPY8B+`=OMkrGsM(AKzd=b zmwV6Oto`!WQR+;8l2sKD*w^&aKWhMaRsZ<2bUFK)ap#XJz&;qC{-glpUH_Jkx3z)j z{r>xc*?`E{c*n%>c(a&{3_2MX#P?E4>bR%FVj?zD;JNb zc(thE@|2T{9j;zk{f~0G1((PB@UUO+l~BD)LOoQd|NPOOZXgux{n3stuixnWQD2wG zZ~CA_f3%~^!#|<_An8Rb+N+Ola1`5F`Fhc5&;O%6rFN?rZcto>_Vvr2ZrGIV8IId8 zJGx=}J^X*t*X8lMJ}A(i?CA3NW4Qk^KFanC^D5U4bcsn*C{2m}sHYp4|E{O&FHC-& zfuD@{kH7rcG|w2J9p zwwM2|_q#v!)ck+&_uuq%{i&zd|3mryyWVg9TB>hI{<3_Mzdz|kMysY(y6*mVJX7^Y zLw5d`@yC#z-=<~%(yk2YYlnru)|0#U-|B&G`bRx^y7WgmdAjsRIo*2Hc3%ZO>3V1= zT*}q|cXpJk|L^SlUi}LCO6^d48TzB1bUD!su<~E!{$?m}e>)$M_{x4_;s#p8NcXDJ zdlD?9walfL8^o#KKn3ov+`L|a}1srE0B-1 zcI2J^udSC3o;NhTt9jl}DW4YLO8K+^SIVaaxKchXz?Jf80j`u!3vi`;T7WC%(*j&6 zpBCUs`LrG7_$lSn#>%)-K5dqaE9KJyeWiR_ps$oq3-p!pX@R~{J}uB!%BKbTO8K-v zUn!p!=qu&ZmdWu^%BM9c*0kSXy?i6^JaG>hSIVbdB;!i?wD~fwlu!Fu#+CAEwfYMA zv|9ZQy3fOc{%LeiQ$D49+F%)1%BS5R~i=jx8nAm0V>SIVaa{FU-)0e_`@TEJf^pBC^} z%BKbVmGWr;f2Dj{z+Wk!7VuZfrv?0#@@WBorF>ezUn!p!@K?&G1^kurX#szweA)u} z`WCB@PitDDxjri8(?-a+QaL2Dr!A9lrF>e`M;iW0`Lw<=u9Q!k zEaOV~v_M}epBCsV<P74l`Z{uOYof4zKJU>|y-DPO)G4)SHS z{uT0Nwf+@wt$&4lSxeww0S^YaQa-JWE9KK_`77khYWXYRTK;e`r*ivK$fpgKaix4(z)vZk7VuNbr%eU@Pa&Un5%8~&FRS&hfNT9L<{$pVt1Frv8-jX#xJX`LtlYQD51<{(7VO-+$^KYrp^P z9}*w_+ruOB!zhxH0l8m4HvbYcBv=<@iNpMQY4Kh&Qtum92BuXd+P@881xZ~T7Q)1~*X_6)@BmmOVR z2E+fa`no&}>VpFPs~ue)2E+ZY`no*+tA4rupi4mYtDOOV<>Yl8{#jnvzUo)uzp?*k zd42mM|I+@SPlK+k z(S82JQa%RHpFmGFIH(t}1@ZDp7&7Gl5AiB{qq*;;-fFf5*L8n?F_F&$JoSbyZmEZt z-PFaw`_O^D{`=5D+?BS;eKhX_0s0vabnW}<`A>bQi=WifPkN+_Z_vYIOLcLR-n#y? zZt3Dldj2zR>*Dr$`l)wx@g{nB(p_DglHbz>%AZxNi*L~Pe@_=L(8E*j>*9~~@T3x5 z9D1kQJ~AHb;--3d>JweOqaL30R2Prc!(*T6;`VywPkpY7FVfRbdZCNw>*294b@3uS zJouF^-cirLZ<#LMLl1X)t&5lG*?0P(ix1PQf8X!AxRLx`T~PnQKXq~Hy>9)OzSqS~ z^l+mOy11nt4t>4WFaD&fA1uG$4)8Ddtcxe<;rU;5aiwtqoKH5>Ex!@c zUuV79Bt3qFPJv=A*7+hbBWO;qN-fo&a=yDmW>hURP)T zZg%p*0#e4RW@Q5ZZohIhrL0pMDaYKRrD~loDX&>d<(1O2T|A`K!ny={c=~sgM1QR@ zW@BkBWtB_IEqS`RJF6vCJ31m(_V$uFRT``60dcjQDp4EkwA5raYxKc+DI;4x@9*yJ zrcEFRYpSSnt}QfoJZfCUP_?5jg^mzNn}*bK>I89>L1_nMeCvp})X1sU3(y!=kdxLm zb5$>=;2>>P|J5tK=_Q&<%MwCrIa^D0WK?3dAn{an&{9gBmzZmIWrwT*4Tz`9&Yn44!vCExT=aBmb zc&QV(!Mvxly7~Q@`KXh&WBP=|M_ct785BD>Jkdg(%F)Blvb8z~H7GiKgj_b&M(!@! zGkr2O>tz~Ew$tgClq?Y@y<;(hm zzmc+@DjwxOsq*=yYWq(TX&XWDP z`}+rZ`ulfx_Y3lOm)5%JEc1zsk534X3yKeqiwqeeom0uVy8Cqt@^n*6goeir3yKVr z?uay>*cd4tJ~2pMc~m3s@7ck})2D-456DG?#76{4D{X+|a(06Pr2eitF0ZFPDG5tA zfkB~B@j+qX>K+5h{YE;~M|E0)HT@<=dca;Ss8R@z9v(g3;P%MBp*i>Ceg#kP_M)4t{70!DLe%4)W; z@-|=InhKip1@hMSri)Jhki!S51~S!t`Ejj(WK59iysC&`9F&)rHBFFOm}zA6u<*D6 zA)!)51*q#MGJ2q?xoJbGb!m=G2ZTfpk@B}0C^RNoN)&IP+D1kcQ)sN67Ie1bZ7SVsj##e}I{$>r`J-KT$a(7*xKQF6VO zlM9MU7y^|)j*l5KJUnPu4m&_3az8X1ivT|Efu5FQ;K7b0bwm^KNGiHeO2kB<)zYwA$`d_uGiqVZo&FCwvj zT%<}z^^wb`_B%KzHZEE&pK4ta(=MKF4(eKiARkZvZl|knYD*1Ggw<`Z#;-oLZ984kC7^%HT z#gcX*|M2iI4LfQ4aP{@_RrRoNsY%641f{m6())kwqkp~lTf0Ah{uKZ1|BpZ5f9p?Q z{{PBf-`?LI|6l$8U-kc%@3E9QnJS&PZap^7Jv_30_u0p0#vL9~H?`%}OwXG>N1xO` zJw~cerBD0d^mHt6u7An(1=|mKnY|s=)8uJ#{W}AA`=ST^;x1IpbQ^PYwb!Ag)wjhK zJlLD#XWDdc{ZFkoBHDTP-}2R$|G&oT?7IPI|Ewci+f9{GpOUMn_lUaq`uwhZ%I4#O zK={xTp(3nC)4F`^SKZl)FJ7@G?x*m(mmIlAh5L{SqZz>=u80cWy&S%oxl{DpT!ZIM zJ%g>*$0C)+=fe9djzO^#yQy==x%j>04g8h~_t1jl?K!dR5No>Jipgtj&#y?WKqNmq zjTXN3=0@(^AS_wA7T>?Xn%#ZZ3r_eP&TK#JN@l-m&6859Q}w%Iba6m zdd>kQOn zT^TuhOFC}(z6JH^?oP~xypG+CG=UH2brOeeT7W+~oJ!l93#3ie42Xm8^Jy;kk&q?v z+?ZOG(XfhfOocIfh%Ro);+rPViS2tQV-ZWY5mWXZqOU%wLoXQcPCRKn9m*Z%iN82M zk@#N1!#<}c@h-#jsk18~AuOv6TtS#h-mmUV*RSZ$?|QgFusEN|Tq##%Y{jdwjj*Dtycof~mSc9&Qw0%p^`<&lR3OO`piK6AqNr z5mwvBQN4ej$9|TbVdtdN*r`L+nBn`EVa<(dleKR=#URJ!__#Gam~A6(P*dkL5}%z+ z#Dhv-;;Dy?nOft_n9Q6)`fjzYV*0fsO_`3ibp6WH^Cn&ZqtK(=jg+HI_boGyxCjaaP$jma?Ok^n&8I&$h^sUPQ8UC zoO+1!!_ISczdIxE4sD0XbN8?scZM_l*~^gc@C;I<$Fo)Mt%H^vd`V_joXUNS3E~f3 z{R&mci^k&8)}uo3aeCp40r2ybQ?!T08fE}-fwY``j89p$5&tk}7q++ibb&@!60fFq zrQo^)+1csl@MzBuT=w?+#Iccq)D-Ut4B5Fi9J1D&Sl;0u!q~HdnB4acwSD~oV&=(K zf=%H*cwFEEG+*c{uARl>Jzs6)-<)cJnO3e0cP0;_J|iO7z57D&)s>9+hYzih_NCX* zGjH}18IPRVvVwzHgT78&pydcS?O+vp@d|`!@uMmeo4uBx#@!{;DuiHr_pG2gS1iIB zG(Lc|S(JqTczYGH$s>`JHF5O3Td&BMK{H9=;d|ua_?kqmLp;^H0ZA@e+l$C`CZPJ+ zn`wt`0mRg)$DyjsE##H>Lv-kJhB)|>guX>jV&7B@MstD&^NkMmz-n);Mn<{XGEc`= zAdMf5rr%yjq?XoQ3UwzRp`KygiTpb=nE6}g(c5koV7-zHk?e?kjNP*c|6YB(z>ez1 zZL4^J39H+KcFO&VZQ1gUsa~-)KIZfXe893i!LM`=T6pX<&abA#jmOf&-RZ4`0nAbe z>*Yq~H?icq%6-M#j-NnS{!|YfnENoCrtyJx10XONCzeRb-kw#}Ri*qu36$OyRV!N8;JhQ;Cp6Ysl+e zy0aIKWb-cV6KJOKNVHwMMMB)7$<*stN0`)rGO^85LG0^$8$KKt#Y8&0AYs<~;D=7T zNw`u3b8gB`_?p)+W;9cYrp7iy{;{pZoO<~J+xU1P+;pHh`|i9Iv?F~wHL%Jpa%5>D zo;n9-e|U=M?6Kpy$XYBDleCOKev8Ex6ucnOqr>@YeVvI`4f5Eup}oW)4=1Fc@iuPw zxczMFs0vixi(S~JGZY!qqX_oxG)tWQ@)K0=YG15cuRHvh;y^n8P>hg~{GGkAv?eyA zTW^u|vc(sl#YuMT0>rUP*!U3&;y}9_$xnjoIdX z;4ZW~jUK+(n`qmzHL~+<9-aR&nx5LSs^Cy34f>JQ1YeL*NPVlE1RbsI$2@*R^HY1? z;deU>CAQxzrV^@HLgsa|;T4OkAi|Bt_`F#skt>@5u(u<}kTsXtGZ|Bj$b(V)#X~o2 z>9j`1aFWo0^4wa;Ev%b^ADQaQ!vX%ncux_UnjA@PT@;7!UbCJbes`@ft>H4MzBnPJ zP+{$`;pv6 zorqmWF7Q{}q<*@*3y18P%Ty(1am8Owa}K9UsNmB(@clWj*|%*%m_`lGV|D2V)Une8 zkg~_a*}hTkROmf3_Vh+G^up#jVoLKBcyi;RFw(3oVg9k6*sIDvVg{a1G)vjfA9aXi zj2|3l8d<+*;_Nn(_3o5Gegj8PyH_+u;IKOMV$U$Bj)=o;w~oM8rIld^J1k}@CGI4g z-}J)%xwaZ!Pg$}DtViOew~|=o`XOXQa#gW8v<~*&ww8&wmqWi_kBPIbzTqKZNAUM1 zP4KUsc3^#H52vOq-9u)69gpU}2w~SOm;mpvolIp|+=I!@rC3t?u~@KQs&{?lnuN&N=%N#T!<|SLycO&`eWC%ambv(D@;A?14?T1)VT@PkdZkU+QwBUY>P9&h7 zC(zBKE|SMmws7(7rop`jM38JtCwRo?f%KX!5$uCr)rdXQjG%_4Q{Z|PO2t+S3#pJ* zIneYc*U0W=-I%KHuEL)$-Qwn5tAn*Vw2vwFd>3uV#OZ(k&nK710LQ=18;3m-DAPOc$##wHO)+bWS>1p|c6 zkGgQzcG7}hUz(leP@R2#pa+@nOYo1++KKUQi||b&_aV2uyOC`e3*v|IMIm)ZL-x%x zR@nR@i`-CrgLm+$MVobn+ zF@L{kzM&JA|KulcMrYIUZ75{(&dQ8eO@VAtvoW+U`UA9O=~E%8+ZJrhJL>Cd0(n1-tQ-N)3oSdq;@nCQ@-#X28tD`RwdOXUaBGB#d{6PAfd*hFe70dx@&h6I3VQV7m%Um$3LfhHkYqQ_ zCHu~OjSmeUO$@GjT9c|M0&8tgb$O_sp!?-ROq-9FoWKU@({?E5AxbyHd z{+7o9#>=`9zC7<5wR7=HNn10;n_Wuz5-8RuKxk>EqeN(B19T#%v>j$$ZW2a$8vpNaLYD;SG)Fwo8 zrwROwnitsI_Yus515vnNgV$)$c^~+$FAT4}*BV}ZaU$bXVIRA``ZnfJ&JU>Pg!T&KpSoQ|;h}4FmYnAJ^cASLVR$r2CTTXIS!PS`NS9@*48nwh7n)D~@dE_>l-1 zbX{ohb`l&M@r^uxZ5g`KF&uaK5XNsS2oz7WDn{Sr+$S>8)`ATqHykwBav*9PAnLBk}!|&i+FxpfyeB5gMVIlUKqWq z66Ke8URd7If(}0tgA5SwAl1iKA@4>N!4+=xB*g6b?^^mZ7xf{UxY`}jXLJD$sZ33Ye#>8n-@HQ_E6`UnVWhNHV++`)%K(K z!NX=SucD?<)o)xzoYq{!#70dK!eWEK_4x?x=)IEQ`i?@JDlZ{py;)&Mg=+k)Ml72% zDIITo$XE=W{T^>+_L8#dv6!4Vz5pc-yy86yFTwNJI%2&-JMPGX-Q4&(J44(Bc1Fzt;!{gA+J96Q#v9bK%Y4aHOle5Wn4c;JLou(0YZth2_6&=KvJ9v?c zCfT!rqr9M$ka^;`WKmp%Man!1oaQ;oQFrwrQUTO1q;RT<^PhO0( z`+9E@lZux@iPI9uZ6o_p4%I{9munJ`Nqa`}LQW&T3sINpXZHzvxUdmgeO3sc6d>T+ zuN6_3M()6-oEyeuv@=Cw``?EDnY$M0V>3;3?s^4J?ISW1=e;B*eRXDCPg{~*`_>nh ztjoto@9e|452+;l9I&6hD12g#p6=l6ZaJ~BJ9miLk9~OKu@U^wWdwiFv#*5*WuvBC%UA?)#Indm9#JsY1?o#gxnQ`ejAzzP$2E_Au8 z82hdQvE#i7YXVZ>CF+S-~{-d*`SJHI6@4@DfO|8Ai`Jmy% z>WM7`^h5)E@r&D3*w|s{f*u7}%%(&^oDY+E!6)DoOn)XJr3xI<+@FTt4#390=zv#u z+JNrvbp|!HI!_sgj^K7I@e*uiJs|B*yk!Hw?SPZM&ZA8}uO^ZY-w`X1ia~Btuee)g zy~x)$p9`nXwByI;JtWGUW?+M-(NO&dq5Ot`eEL*MPw1A%7v|~w*GQ$|kHx^*CDe{i zK}hDqll;L)2{=7+B{ZmIHaho2JH8}gD`Zi+9%Z6kseKI~xU171%e_I!0D3AL@zomjT7j9PoFKiAp2AvQnV zi*j3W4HAx(FxCURvUK;Oc!&6}a4%a|rk_P~{^Dp7nS5j?7d_vU+M2oo*))=*>eo0# zVpYwE^F9yhBk*bXXmAdOvb~tZ06%Q!)EDgSuVLJ#I`QyDn7{@ui(wNQ9Hy%TO%-k= zdLday5b^R4W1@}uHe$tF4oY6Pk;%{Y;ILIZ)TG@GCd+y_Jbd*|Xvo)^!is8X_|@-E z#dBktVO5{z2vt^`#n$XvNA!$#6^qKuu?qi0!0!hg7Vfr7fQ%>D3)dDLg*t}VGVi9u z!g2LJkgGqA;Vk>)&=sRcz|CGQ=WM$!pmWK)@ZH|oaG$j(oHqZ6@O8)yvD>6T;$@XC ze6_}9c;E2rc>1#D_>quZaP|owo^8^F^t`)3?E0)aeEMM#+K63`KbzpmH(e1HkfTv-LOUFgYV_Tj0$l@qvGZiA8Vf>L^{aWMOMLOjH02MdLV8CeU8ilv)Iy)0e~M%l!0@0wt*G{!JrK+Hb*Rh6etc%s zTYUAnak$0(zVOy-9mFbKjo3Bg68Le;0{OtoR@Ae?7jW;ro~*;w7TCw}HK`AduB6H8 z+x&o~LHO9X1Z+^HTU6Zz{h5mSPoQl(L-86n-Qg_%R{SAHjGKmb$L`i}BJX$FC6ZD zXK^qQpEoxVCcOpPy)YW9&4i-q?$_W=3kR?pz7FC(t&T#{p{vyC?F2L9@gl1Kk88q? zdN+ln+)YH+c{w6~-i3?ZwTn7%tANb5hJ=&P189dE!}(@YO0ZJ#4LNLhFjsG`GqN*z z4z;cRc&4UfDb}R%MW$=bOmX7c1Jw4@%b78oj*Hoc_XySe@1jepr7)j*Wgugmdf?qA z%AnPSrJQ3~QzGs#!XIXx$U4vrZ03RrP(-D}$nJ%;X|(%vI`M5PI)E)grkvoU z@1efHS1Rqn9)8;j*Kha*KH>cW?vtKJzs@Vb!+H_IdDx!IYj2JDvM=Cy#}07c_d7tB z_Kk#NO+WEd>NMmwo^H-q6nK#>r}yXXeEN(H%-Bo(9Mear++Y|}*ZLmOHm@euU>k{i z4|5PMKK_co#>Y@L)0gut>0?+_a|}KlZ3!QCuE4i)?!sh6R6+K~EQd_y)P*Vrw`CoC zZ$lnO)*;=z!r|AoZ_@C>Qnt*i9kG9IL)PnZEOFk_nfq}6Jl}16DfM__BX+ahN`B|A zD^RVXFzDf1d+NpfDAD(s8y~d=!8cn?gZ{B|WNH>aSSmx`B;`7o_blGfIqTK=u;>ot*P@5BN5$hYfQ0fcK z*6KC{Z{RqFE1bWFcs^%0exb!x`d+|4$jr)j(Xvj>a2KD8eBa^q;J~3DuvEW#qC-q5 z8(wV~w%@E0(X^Huv3G3%9bsc0LjT?`kFU4oX8qO=x z2OGoS_`>e&%y;HouMtbwy34~MySwJl&ZXOh$R&*#x9mR1W}nI8q3U(G&ljCJk2$Yt zpSwHAQQ23-?(;m@W>dZ~;nn)FRVSJYudgJd^D=4fL82*Q^4^Ev65#@O_HZJu7uDjr zb1#Igji#Veew2{GGp_Q1eWzo$qlSrN+AL)Knzq0W_lqJU4xWJzug!rvIG5m+-c5mO z7Y?PY1K&~fW`DuzWE$C^!WC?52NZ9W`JS4^Rp;iv;K;C9(@<0ind%o$p_NA@(Z<;Wnb|4PL>04}%#!LO@YNAR=uS2zs#Mk)e^gSdFF-tmvQu)PbeD6Bw#yTPNp&qGXUE5BuNtr#;TXojeWg9J+=#xzqyreCLyRx9ApqVDWX>k z!s#4A)HAA2k6Ri?Rcus~Zu9&Tl?v181+~I!+mj zY{*Ix;%-bwYzBYi53k3Fy2O2i?rp@_6LZ9KZ=z}MxOc+GRr?6Xq7i6=lC5}B$1bdi zX%%)u-*fQz)27VO54|w#XaF;>O(wl~fIG9-XbraGQFpZ3y82LHoITm}#5o${OPRv? zy>UD%TqLiaK?V$sq&udVqOtM+Q23@*f_3|sRL@II#aqpaaQkDO*!0)l(6)A=B)s`N zdF}ElX8MQ&Tno!pnC+Kde8V@5=~iz#Kv$k@z$_o;@J~9`qdp<&I2CpQZv3DRf8}Bi zvUBh|Ve*MkGS<&j$ei#6KjZd|&uevziM{HA9;~(>8|9Tp&-ArN-ns?QQKKg{GI0a!py!R3&gO&*i8MBEQM%9G9Bb>>iIiulTW^+ih(`Cr2 z)LztT#)+O>w&`=`t043D^(AV$GeS$>xy+#?=$RT%?|Ib&a-j#gW^%P!B*+8Y+LjUEM& z$dqoZQ-u@4#r6*PmxaabSaV0A^Z7pX?h~Da`D^lNx2>beomaMD6BdnOKM(0hy>AqU z2c9j%ssvVH^Q(lSmzJKTy4_fT_Fh^G9a>==`l?bO(=ap{$-FWTxmU#(YM0%KJKkj$ z`O2<6G}`YFb9wMGlo+~KbQrS?-Zo_;Jg@(DveNn+kOfo7n7pQ;qmAzp&r>XfcTZ5< z+{BC;v%V|YyFnz`YFbn1;qp9YcI~fX?vi36)^-wf{nmQw$(kH~@tqX%+tT~O6Tcuj zvP~ypVNxb-65AK6!KbsUH(V0$6_Ie8#Mg}JmrlZ&xp{o8h!QGMT*r^3=+e%HuP9-le4+m(cYU#wF=TUpiw?CqAL`dmePF>1z2B4E*7y4srv8d~+1`zJMu;n#U#=nXeiSenCkkMO{1I(>#N zZpgyNto7iJpBTm4txKRDG2>X9jqe1zDx*lJ$j5lC*)_?akGWI@I~T(0(0a(!H5j^f zkD#x9ZNVJ!_=X0*jS%Yj*5W<#Mx)t5T@kl7h+x})C70?^hgfiGD%rSB06b&V6y^ur z7MXk3i0QVy1PR!k94&$7)jx^Z^zKB=OR^)MZJy4yDP6**j4*{vnoT1+Ke0e> z)Y!%O`_-i~tJ={CiTCkNeW!?P!&_1JXVt(fMb*F$e9WS{-7$tUemX!?i$+tIzF)(R znDwSlvhDF2MV+Y^zW(&776DXA*Ov75&8?Zr+lOIg^_RorT-)%?I`0>@B($MCcHSnA zhwY|KKhHroeau4-?3@IBdwGix&%F@fAM?ra6MWfI37eQZ!@|&2y&7RXBTVS1(~E@D zThhqMD?dR&GiE~3KXxEByVT){jE?NxNdwWwcD_)>@IzGk`5sWxwIHPN*jy5NmO>m( z9m7ojB=YlZ-g7sC&Dg607V?whI?>BkmU8t{U$7I0pM%e z6i`!=4^Ry+oD@G1lj+Z+2cQW}SE5I&z|i-{rtI7PkKktw&S3suR>1CGXK{S4G4$TG zKaw)&qgdj+7H+`bXDkcb!rQK<6RXcn#f)zSVb?4!V3TK=v!wA1N;p=Lh%+8S|0KyE&MB>hHxC zRA_~znD3zbjtrrfrOfBIE^jRE8MvK0b#El$aAyu|(T9e+USGx!v@GNrxHb`QckPO< z?Q%^RadbD0nU#=57t;Bgd6($p_B}DnCoPFZaS`OU2j9udYqyD$yAHzA?Hu6owbRL~ zjrWVMw)pdz<40+4 zXgz+S!D4*R8G#+s%#$~_N#z}-=P$eujmL8rY=xc{&4Sz)#?oHawXj{)M&b3G8w!_- z>SJ#|&&07x9|eBL5@tfDEmR(#NjGc#fJ_Ttz;)l|h0Skt3S}oXq7MwYONNguVR{7H z@b$wYxf>m}ktaJH7b;lJ#8zNV!hqrXh-+viT(B5~cF$Qx9;~*S_3v_u8y9~cy&l&e z`54ob54&Ek~!;rm&_B(6GH>E%T_ z$=m~bdALMacK0m%B&QX&I=?T~ViqS<>$Mmq*U#a4x;GV8JP)9vt9a2iJ0H+}#(8pl z?*_up%$H<@&st*4O%XbGv8H%&Mqln>vr5#8TAh$dSL?#VXPgmlJQ>Wpe|!Ov*C!LR z+^!L)zE;D>y*b3UFiA#xymsa@d)J2sC9Z^HE_`6CO{~oCI=U5MHeQBqbfQon3z6OQ zI12l|dm!U-*$=CGrw}gl_2Lu1o`=3&-@~8lzlJzD`4Dx(#hYk#vZ_$McqQFt*bee& zawF{f_{pU4Y9qpX@(Chq4TJC4$BB;|+F&qIP5NDA49RZyfr;BqNt~_8@>)Ajg1gq(_s6$kl*Ff>Tm^ zEO=iX>Uq;%)X(>xc!hPJal-2$=aW{4OM4#9$8_F;v|dz?2~7KfW^>K?X??zlM`GFuE{-kv z=@zqKxcU#Tr-ygL-`>7Yrfr|auWYh|uimCAOI~C6 zW&6#|qS z8yd0KUQH6~kN655`LGtc>3M?A{_KlYn`e(O4OcQ&;|HQ=>|0=a9L?zXv~PTVScJ*=WQE}9dW-QbZYknpJ)rR`0wHnSWYQcrMYmS2&$#X=qr>Jou%{aR zz_{7tiTwj-b8R~EkuuQL%reKxGbPf$VJ zp>8oynQIev#u!^>ZJrzcBz^@n#d(;pWa%;D+(Z}lwe>f8%l4kk4BM;Nz~UNIL@OM= z)xio5rr$9Qtj^%QzHY|49ce^-T7L<$8dgjNyf{v$jBm=>OqwXv8P}fs)b(m91|&on}B`*M8F`#@w%qoH)KSdKnBygpW&T#4O`xejl*x191Wbio&y zyFnIV1Zp3@51Hyu(Qf(XNS;|sWMAk9acjN9NaC3w+HLL_VoX|F>U!Nr(ANQHxaFfh z@|`BUX1$gtA=Y2N&|Ri1X9tcF;W3Zw_zN9NiM=_msY_D>;050Gu%o7run}xFUd{Om zelxHiJJC7<&&{qPm~~7i>K9m3zP8t)pMKfg&2Cqy)TLk078Sd(fh8BIqc=xhhC3}1>ct;72A;Xq*)I5 zxSrdY9WI}V*8R>2N!O0RKaSmE$2aIghmG*#V@CGjo82tK)_cdW->%$ZQtF6QoBNlT z_|+}NH*IXO6UYv-pW$jICODm`v`z z9`_^r@}+y{3zhB_@h7=lVfL{DzYcP@P z`Gb77Ih{%iA4Ap{HV8Tsv`e7U+QXg=&f|?j<6);plc_N?hcjjYdE^*-A9Cf}LqzK* zKS(z(L~LIf78ACWlFN!-V(i|n=#p#I5vOjh!iNf`SnT*Z^ex^&s9n7+eJSo4{5*nX zGTeF2&N?4C_P9L~-`^jfzpW}eKiY(-yy8Aljabasj0hlJI`l@W;uJLbb}>0Gdkvhl zdlu|8D363o$MY^+F4n)Sgm9l|hnr@96=#}md=~dilyi(2zap>;8)I1L_{Fu#7 z>WuS!^wk~*EVfT=hS|{tzsn3qru-~suMVAtPIF8{-yce1VpeTID(zm!)Y(SCj~XQM z3HLYgRHZonylqR|weSG+qkDaRf$1frc}O7oc1R`c_WpEnE!s~sd!2`TTDp?@vi%_3 z+WQllczh1GZR0bf#)^N$!S#>u9gd~r)Bd?k)C!ryS4Pa3P3D9!G3PMXA^);aeWx`S z%j3|_R)s|1vU%{M6?s(8<+1$omzP-E-pPz__03fN?n1tGz;5Wuvl{gAn_I9CD?V~9 zLnrdBM-jxZk{amO0&}8q=}Bzg!n0z@pnhbfE+0^=tU4c+J{BL{)(9SLJcw_#TcoUJ zU*ek#H72(<{)ugQ6N1@vo=3StsbupGy$LVkwRq{(dR9b^U_-|4fubI~qdl6K!zbFs z((|lqq5~`|2{~n+(lezdgtO5&@$AciR9Ep74$rB|Zze0^H;!G04zE2d-rWO}Z?5bY z_f34ti`Z@Cr^{rNY-23$>z+&;Y?;Q_e1t>uX7NJoltn1J<~@Jw(Kr76|HIyUKt-)Z zZNn#-Op?iD5(_FS3W^0gC?a-{E=UtBSm;fvFf>KQhP`9O-h08`yJD|cz>W&`hKl{) zhXJoQulcSY|NYj#{`K9gHDu=G$w_kdexAK|Cd|kvsmvU|DXOC4 z2t`r5Eu41rdd=e3`;eV`tQeH-uIZBfOjGf(6~DIcewAYdcQ%H6&U4D+%%zo+c$=G{ z;t6dUL+0Ms_}a}@CYrWUzdzJYx#`VF!7A()aVXG`a*pBE)t?SgHSKwrYJcq$^ZNZo z(y3XvuwmOsVfxm6{OTF#g`@L}6=UzN5l-&t zLEMcUM>wo*#T~Kt;Zi!Ey1%HT{%jc`cz+LMn^f*k4Y0@)0_} zZ3~1((ZLF@8$OzanW_BS!CRH7Lq%#&O?@J}n=8E|WEr_JbPV^_Ua4}6a3ZX!baBS0 zrDVH#l)|I8A(=mP0vCS8lU-vvM17;+vS#0+eu}R7G@3`WP&>N56nxtuh1PZ}oe$5E z>g8A~y|qEi%TL3F;Ztn*s=FU3U%%SPR4%ScTxuK3Kkv9-rKxC6#nkPGa_YQdCzup- z6Akpm<||fFcW7tz@SXS6_n8-(h8EGngeDD1^R+g@s3AS6F6+{Ty{)6^-mO+B*VHvqndSFVwmPg8Ki`a1 zot|M%pIJ1UTsNYF@O+)6kUpp>r*F7I*}QiY+x&B`Dmgt&-F)Rts#2D~YwxD0NA%vw zo}Ac;tlXa=c2AtEOx)+sWv*?_m^{wYj2N^?BW@hWjyP$^g*aa#mwYp1a<&fRo)@Jm z*s;gSdi&D&z-(4?q__{W%JVB{W_Xpg9`lZGK5I7d^6gnZq38+C+tA8$yS=EChYOi6 z%j=O3w!an}S~aH|8&^^;yX>a0kF^swcbK4lZn;(yOk@ck58Wj9y)+>Vm%0i|e7~w6 zPv529alH;djl96Uvw6)=?T|?ozpczqW8VnRX4lYsFR-Jy%C+exZ}Wt2m1h#x#RnC` z`D;XF@`8BMejqb$v1R%YIek#RJ%B@5A`ErUu;E`x}+# zm$XrhpSP2XSvXVWCCpRrzdKvA<6a71c%q5M@MJaBjleJbe9xVlkmNVa%ma_qhjW|q z-zqNTY;22&$u)K};*Fl@VX!H8^+OKZ$9DvkJ!L%SHtV5cT-72z&tQPK>RW-Rf5t|| z*_w-Aa%p;!tKTfQi~X{MQMYe*dXdYFIJ(@^xfKZKYT zT3LDYMmoQ9`y=wpd_y|e@q_9kUky1IgcGwqbQOJ!km_CcWG3(1dOEDaJ9KK)8_hJP zr6RIz8}-PZeVKtfPKuUiJ2B@jTkyxHv{WD3C$Rmlv{u*c(~inLRhfBnDgQoV2CUnrMD+-56u}CY1DYp5}66&a?(l$?4@m-ht z!v9n`3Tc53!jP%0=*5%!@QqK@VLokZPCfF{@E0Z-Fav{MP?^h)FmCO%>d@nnnogf? ziW44HCh|Wsit0ya@JTDiEA6+o7JJy$*JwH$k-2N9QRY9=8HL#o%~2ymb$2^G^w4y- zu%~hl)zuaKnGwo4s7ENJCiTuS`5Sv_9%{QWnIAe+M>~H~Zr(bJtadk^t?U)ZZZqu4 zFUo00+UE3AkL`L{?B4H(Y8CyJX)x)O!rFpBS*dyC+iCadf!8jnt-GjHS=o7X)6cmI zJxSyFiPIN~ zuRh&j?VKy~j$e(*5lech49C*E@yj*HuKF0wm4+wDu9qt*2i|lLYrI=1RxKPz$6s43 zHr+Imofp}W9sP-*y=R@&`1snW-yWp+frD>w7sl+=%+;hbtBdr}$Z@%12kkK~B0Zb! z+&G&m9#|w4?7BkFUU7h{axqe6GFFc{p4*Lm^w~*0eEtqpqg_7xd`+RM>B}8V-D~4C zd;8gumYdfKMZ6R3Uxigf`cBu3h`+;7Te}l6&u*!U>uggb=Q^Pk%l(;F^^BAg&C^tU zZ_nmBE-z*Ve?{zk_~nYO)+XHh4kC4Jq^C-AJ4_R;HAAD~`3wzgO`$%hfgJtlJXr=x`W7sdBXIH|l=UCcRnxAh1xGZKyJ$&rm1pgEWILeG+80FKxGvFiF^J1hH~13 zR{Xr9c4&Ibaom`&J;K{<<4ON-)s<RV5<6*a4J0E%kxL9u-2AttxaXDZb@pItC% zun;vnmpm5*&vP^yLm6K=#*c3QKos&G(w9cX3th&AqS?mFsXbTi6oESr33aY7R4p3p zz?)_zF;{XM@gIi7(A%mVC$!r?BFjh%+LHRAdVT36QMZpFisv3EKA1!i)xUJoj6Cm$ zhPy4IE}ggGYTpd!UxZ)gAHCZ_20wqo*Zs0t*?DX;vOl-=olLYw6#LZ#83 z}Yxe5Na$-0Y1D>drp^s#G|$Ywh>kwFhdPBD(-9^NpbHhAlP( z(gz(;IWM$fI;$EhP;3TQP}P$>GAo*y=KGK~TOP<|U9qFL?Y+S~o6(T`vC>Mhb7P$H zYU@w5$!88N+F_`^QoE|6%ez8VwHJNWC!AiXxJ3);fd1axc6ip{`kTkhvBt}k;mPY& zBYK=ue@Uu^UToxq?@P|J0p=^n)d#wWr@o%1cMo_-4r()+J^s}|d0L^bj_h$>bM@p~ zMbJr8>d>vhipn+4YfKK0B(L|;5Z~=HMThNM6zgIOn0&jps7(`6tXO|16PbKWU1gVs zHb3@4=#%xCPE8qwXpKLA=s+7KJLMS4ozaK)*i%E{@Qx5xPMO7=urg8R#v;YAk;|2J zJ5cs!ugX@}7IPKJ47OHJ3&LdMZ7%+r5x4hSn5M>qQ|dsp3QaEzv0YvHDK5R_ItIQryyb8gjACQVqH8FIGqlqR-9MLoHXl z6jz>8C?2|7ayf7O*mD!(sL#6_kUYO?K5$G_o=xf;-GX7GcY2 zn>xwdYkQM_+MllSzuupnR6T)g@}O9lAgDR(ErNRD)(+f)%@#W9Q$tOm_Nt25aukiKJCo|v zy}H0nPvz9ZPx0&Rdb15XRuIiIPw=yPd{(zzJzwzXIEmYxK2y1^Lx6H&^Bn$u>PF$l z^;(cd`=A!b!g*WEvt(Q4eX;-dGn~&#Gs;FhqT0GjtC-c#hP?v+!`GwdOI1&Y7s|M4 z_Egr12V&OXLV_A}Q0R8+JX#-1A@}7!$ST#1*w9Z;$hhyvSfeFFh%-H|F=u<_Fyr2) zvT-8@DXQz+Dw;WTAudh2Kvy+9qI#PZL~I)QN}=iJiG1c|Adf?*Y5h62;^hW!1l9T^ z;mNG&eAc~o%!~ZGstgqRtsEr<1(KP<#PtHtU!whb#&m23nS9olr$2%>)NANe- z3kMeIsavPaW^c_fAolEbLET2hQd@Jrs4mp~sy?N^k9yZuU$rJBQQ2IzO-$_bMzD6T z%f)+iWdQ`PQz} zSdTTIsi+oLRW}l~!~}!SY-->X^{yaR)o{o}_HpJ3;_K6o!qYFwjJIV!_WcfCxh*G~ zd_JtU@MuT@^wADVp;rr)rLyr zG?qU)adG2@YA&sLMK-vkC)^)2P@KSzR;F|wN$yYAV>VQZq@Ni%atp>j;n=?3DpOlO zjdlM^3X|hosDvM^;^~cWdP%@Xh4EAy^gQy6VpnJ_VN0?Ly=Ko#MbM7^^ruam={C32 zjBQ6V^^M&f)L-3(v$1($!bImdRmT{l=|3TqiQmuhC{ouDgCx) zF1Jj4Hq3|LOFFBoINT7@sgIiRJ*q4AKI%r_cq=k9U$&v24PB=6yFW>J#JY{be##u; z%!)|C-+n21bKQBu>N`^I@2OH8uk=K0Y;lyhJRwvZm#nWmxxWehwRIS~q=FL{>2Vak zi@nGip6sFWH4YTNCihj}HX86@mxnN1ZaDjN=0oZ= zO$ymzq`xNg`~p?)?B(43&WqG7&DIN-XPzJ~Y~C$uT6icMrI=FpdR3$6paE2Jd>Yrq zC!#U)oQ!a{^Tg^1vT(zo;d@z0L{AX^Xe;Z=!v}|sCY&03wEnS$l&6vx+K8hQb z6~?ZuKAC+ou|RP(y*Dz6@4SR`wGB=vE*Q0B*L=OAI@WPCf2PJIzSgkIDyyjp1Zl#u;fZxL*_I}1k4lTh z6CRnG#j`JKxDj@!>8V6btErJx>OOO&W&CEH)jodyoRaR ztRPY~rrT_$xp8;Vp=|+o(xe)b%=9Gv;2X58EhE`)2D|v&_+`R|8idl^ZyZ0l=W4~k zsL#soD~-epV|)a&W>u7Cr^AHo!+Xf#m0i>wTMFv>8*`Y5-nGPg+fr3&b{mB{noKcm zy^+ekl9l4)$29R;&+V#FZJ-8E7))%v+63+G(oWUZzJa>YmUyl%#gJQhOSE>qwIXXt zh^E^#YvsfP1L$*=tMJ`2^a)~NWwck#vS;>orMs9pkVb5KwW40G^6kO^epsf4X!V>E z&)tZl8rD@Sw;5g~r;m>m4F^Y%7y2?pE2^5J&fXpBl-vMv!?X;+#j=^k(e0IL!Rrtv zw&7fss2HK1Wz&mz_5BnbTKtaFpVj~!Q`nQKp4Am*gKw+W#NS{u))x@%LO%)i&MU;n zEjBABeTk+wZZuI{+2X}S#588s2XsLVHb-+#LoykX@KPiUsHAXc8!pz14pI4D4JRww z3=|DU^P0n-MPjzO1#>hln%?Zk6BoN0iXTM>)@n>&VtGgs|0KtQzEgFerux{*Z2S5> z`HIf)zgk6g#24&4VUGV2X8sc|_-ThkW#yh4w%$H_)!-u@Or!fxsPp5lXl{)pDE73+FJjq1=$L7n|fOmPS5>5vrl zv07GQaPtr3m#%e{2fFyEJKw3Tv0YMw8nCR1IOTpcb+azd&2?L%dR4fVwb)x-ozm@< z@O4W=O@7}3w&A=i#p2vx&TfkO(@^x*tqFVF&iCmsO+ogAmNY9;58LG}wi+-r-@%rP1!p|*HKvGjh zoqhL6<1tpk=tZ;B$7)Fk`|r@B`n# zBbey?67F-nc*V48QH5ID&s245Xeu&@jVIkgR-!HFfifjITI}R-nP1rFqB6Z_I$zD# zjhMM6hQ4%p7=JJA8QW~$3~KJ-E~>@O^~ehWq!?OIM=|-sX*y}hBeD$zPa~Xqt8Ni+ zj+-^D6(8HMHgn!3k9hEMrTTWx9b%G;H?fXQXZlzqs=4o>Xms1!#N-5(c;$1DCht`^ zaczB+X6LxEf@;KSq1Wxc3a4RFY{K$$>akPDkY{e6Q#j8Y$`Y%hh;wVF3rnNDRkMo? zH4$4*vz-&}@^N!5)rY=CQMF&J7K+9lr#=n+PQ81sWHUGJB3EclR5#eZq>IZ{_K9U% za{h;Py!o^QvAy$T#(wn?dP@2wer?7Q#^0ff=u`Kiuq&v8>g~$K8vQ{7_~VUfqUhy# zE}^HWcs(eB*>JisTGX>0{cTqTO6Yx4k=Oe<(M-QH|0e$lp|`Fn-)X)N6~AL6*>lct z6nbd_ZM8F=G52cAJ#Af|=(=;SV&R@{l(1jRUs?WzY&tzenDV*_HF4oK^^^%_3YR5a zkzYoF#^7KVb$S&)G30wCRjmtJeuJqq6TWpHx9jpL6qo#r8GZMvdS}=7ss@%H*^IBd zHBTnLptW09i&+OYalvO=61(cB2%Ude@ZT?YSG>q=!xp86pacFV1d4n@zSwm@8S2zS z2)~`A@u-%r4hv{bRps4P_7^9iZ_6wdsoOo&5kLB}L!6HB%gs}j5gp%<%8I7qQ%?(a z^^CJrBio~V?1Ks{*-fM;c$`yMc#Y!*pV>!M8hD9A8*{nk_P#WFG>gkxv4t4j(wKF7 z0QYR(-sf)23a3AXThlGY?tISy7nqCFMYtDUg+1XtK(V#sT=CAOY<7y-N3rn!J(Anp zOy%5etcGrz&kZklPevVTP3ARTMXa44ttjZ-T-2+sP)y#woUmo@DK{RB*LeDVp%Z%- zsqb_!Q~J2or1iXaD_okjrHm68qNev1G_c=GG-{3t4W3|&%%ktn(f!6y?rS~BE=LEE z=H>?#$9Hw1let@*-bf$DY+QS^PtjA@U|xf6d2OJ2!qa8KkvVUOd3W!rzqGE(7u<-V z9_7^6d^4^h(pMMoojn*Loh>|9T7uRE<=LDv&Uo%kk9 z?Lw=ord*=*Ha{iS%{Zb+_r1hxKE{*Y&*zg?fqj_=t`zg2im7T)ph!JgyIqsK*HYn7 zr!w8RrW29B|FIa^uM!uYzK7_s{-g53+AoTyPjd*f1Nq9pCtm14oQYu8`605N(@HqC zMX8zdZMa5#{4=fEyHW5=zQxy^>yI)$eo&)bhM?gKRVx3k0~9U~;z|3auL#?1u}HN9 z{@uOLXW?$w$HLKFuhny!+bPsTSF+kcpGm`rX~fZUAH?Ju$(rh?9x;!ahOx^ubu0@$?$#_V8mKkKvnz3^;!G2b*MRY-pNj9T2_g34%(Mm4HW68|vkfo5Zs4!oIP zEhctIHF4`(EXj#4GuRC^9uijV+Y7PQ>Ga$06j^-lj&gp3>TF2LDWS5%7j^Po zb8%(cK=MefL_R3`E#Y^jvSL&I522>t6a}%fn$Z8wLe1IxRmHrlZ;IBdZz^BUIl)p# z`YQF~f>qgFBgL$ZotbWm`pO|4a@8?Ot*Lz-T9Rff1m;WlMe3?@39~l+q~;pjM|_@f zg|Gf2l^9chIvPIsmFW2XE}A_uNC@gOhTdRtSM%U(XL59sztA;n27f4|ohp4;9#t{) zig>%hdCib!!HkW`67}`-(=`R@wV9;(Pr1Qvtrg*ILnsG+HNAII0N1@y8^(R}V#Uov zcItK&>rjK%1t?fwFJV?xH}#l%6Uk?D7m2AaL*f4e-YOfmAE@l;Va*QcUQ28~upY|X zZp=QPcm*wpIHtOKeJMAyN*-T4uOn&Rrw#it`6lh5UWY`r2fy`}3FW%C9yio)v~p0G zf_@VbuQ-|S#)my};Fam4NE38U(YE?-MXF;viuO?vu7`e5`n#_x=FM^81}*9$TudIr zh51xaDVrRkek@ync61LR8a7)(>}NbQ>kN{(PppGFyt9G~X}?2VB~F0nV_PtFr=L)5 zx62?N_gbl^8v-Op#b&2^^D-!t6q@NK-qf`zJgVPE)y6NkA;XEfr9 zt(MARI~t1#yT>zcY`v8eyZ2)o49ZmLqg3^5{T4!guA?w<{RRckA6G^-9EYlfZeSLF zjUyg~TPa(t+QM(OYYorMzND(QupokqM>7={y0b_3%%|=)y{dFK_aqF&QA+if3}%I$ z6%}tYi`x9@A(atTQ*q<{VNO5ZNZqgRFitayM|xxXa`EpPC~w}qL~3`QB#90I?3M$k zNqbvL$bavR_ISOb+KWeM->oMEYr>CT*0P4!rpQb2$*46~&wjmn8oh>!@9fA=npT$@ z65mc)KRto1b$XcSvU!8XLSe!0TGETSnQtkc7&V#LmOr1~5WR#S8h%OH@&0q=vTGB> zr<=BuU;B+^B9r{cjnypp>vh9boo*Sa2gKTwWO5D8maM1rabL-gm_1Ds5K)iZx@M4u zoMuBb?ebVv`OSDi*`x*hpZ!?=ru8>*YT^#%r>gHYCT@+CyT4YV;--(`CK*I=jdsjI zKI!f#`^q};c#0*r`O$UW*jyw=71IpW4W7omESt=C&@R;3EN z5(RKxmkHXW%RHpLlBrZ$93m{vv_%1}dN57$wHn7h*VTn{&3PY>VT6ytLvdK+?!>`s zy%gtPY!L>J4^^LBpQl-7ovjdeu3}v}4=pv}?n;OJnV*;)g6bdn%_MdR(LI?pKL4t~iD~S8WWLa#KWyM{XAH zcBX|$r4MC2;5Oy#*N?M!uw2dV%OyUqy3SS~`jHJT$n4y zSBQY%>dI+HLsg+2T4>hA&rlfGGo$>EUq<;&ZIyN28c_7GTy9+93%2$B2byWM{fXTJ zm$P>B^2AFO+8|fQKxM3Hf3kYEfkKIjxvjIC($8L)a4%b}636a)MhvwZA@q*P6nyV4 zrl)Hty2wq#xwrg8=bc|g^*p*uIl8!(rq{(7)^B;d(EEFoX2a$wR7cmEqDi}ZMB*e< z#ax3iTy}IK(QL0q(cjyW*l;LanR;@X@X5S}MsI2%+Q6FAePVo3O=Ew}_;2r3Jr2%8 zHU=WGB=k9VebNk+Qlpk4VD$rH)QfZUmmQqQU7JI=7pT}g)f6HyfS^OyKc>!vtH`S7 zHVH$fnR715r^te+6cvNqlvLf>%D(FsX-1B>AzzC7sr@5GbwKT&YUEhJUmr7F`TD3G zT{Cd2m@(=jGkY?@RT_LmNjI#mx)(f<(2opf+U>F93)IKhQ9Dw}z?LHSBdr1R;o?c+ zQl%}TVfJA*`?f1nHEoKxpz%biU(|GA-uDyK%&7fJMVoxeIqL*ZO*^Ev7T90$&y&tB9k(suJJAN?Agdk6PXpmsv(bkSGfll9njcE zm)K1bpd6I$hUl-y+I z!(1o~AcBpp`SF(K>dq#W(1W%Ix%OU<70FI%+}3MPg_xET1UastFNV!1&5mv%ipvm`+n65 z?VTg2^L<{ampbrdlXM%=ap)4xx4Aies=-ikOVfmdpR=(dj@MNRoJAc`znnyZ#PPPe)N2nvRXkM zu(RVMhqgu^DlSy5tTK~`n(>Z^u3=6UcT8bE4;x62^{=2DJtYf;aG8SU&UAM4N>}RU znr}qoA@$Mf?5+qeIl!+7Ybw>{|7~v;@X_z*9C^(OKwT{j*ZETXETI4V2Xjb}-YeBzR*y)XI)a|FZ-?UATtlJ#nl)_p z+!K7mm5Z3{QG2M$UwHLAYbP>!=P|;{?U<_Lx*|=7g*Eucv)-$!#v6;8`Ll^JnbWxL zPYC7B`u8VIhI5D)%$R>&1CkMC$jkTTdWofl}z2A@7>Q>p`E^3l$ z_>h+Sr&v8p-#J+QdS;!veIr~)cwGygao#V>Ail>Ty;T$6+^Upt+OYkBhnKo^ylT3v z!;S_q2ZdbwaHeO&x3x0&W!NZ+E1vu?^;M?=`e;sz?2y{m*}|uH(mY>&9JMxXed}%m z8qcb6d7w`fC$00Mi~TA6<c{52j=b;gE$5ma zf0yU*XvO>_ZlzJ!_hE-O>^z+6k-^n%Sh%k8_j}RvKA-KnCCVtf&cd86COri51B07EgG#W8t1Uhx<6dE#Q2>Sf_GwR*DH*#=r zK(AlFMjJM4Kv%C`MN5}1MVmHlLi6X(N6VKlM{)4O(uWQmLOXZvMBl!BLo;T~Kn)r+ zKo%AjsB`De=;Oza=1gbDpjh4($dnf^9v&WO*|KHG%E}5&nKA`UpFSNe zSg-(DT3Vv_@86?+`}Uz7J9ePl++0+rP90RCLIngr4vgNtdxtJxzKqVDJBN6lN0lpA zM$ex=N4~zkX!h*c$kx^tRjXDF9Xoamty;AT4IMfZb?n#?1qB76e*OBP>eZ{G`1p9_ z=Lg?64AEK0$6jV@9fU>i*QJXexP*hYDnlxz=%E`$=uCA_V&6+hRGBOhN z=+Ofe6&0bUPoJXT;9xXp&>*yN<3_}?EZVbY4@yo>M)m90N6nizM+OE4XywY4Xxp}J z=){Q=sIagQ-M)PrX|-BpXlRI>ot@GC{rk~`2@}xx@#9f!Y%J>3sT111eLD&X2|?Aa6T-n|>8r>CRChYzD#wQ8Y-3m2mM_wS?P;$k#s z&Ky*+Vnq}l9*%C_yon}Ho{TawGEin_CaPV#HX1W#40`h92|9oNJo5JTMkXdE=ZEcO_&Yg>zHEV`MQAC?JZ$@5T zUTE*$y{Kx{s=x{K0EWsHn!LbmzrrCiV91Yvn|1~IorNI}fNnM5#_)5X$R1p;1Gr~5 zxcmv=_Lsnv{ekkI!7YNo&CkHFZ3Fk24eovbL3xl zVHgg>Fw_Eb({P&BAUhFoY2F|kui=#E!cc^R$)18_%m-TQgUL36Tm`~q-vzT5z$NU( z!~-{shoKJv`g{TE&jNb60Ch%#i#!CkY6lco0gdc{VryXtL~zHKK!XY(1(o29VOa}LE11_iqsbRxO*NqG8gSu*5HhZUe9r^f z846+OI7nw(2tlC`e!fH4Nd$>o08(iK(zFUFbRT5&BFNo)aQQF@VQ)dkYeMKS2YSXr zC{Th#E(5xb2WiLw*+>Bzrh|O0hVW(zG(Q0{>H*Yt2CCHt`mcl#(GV#70jS#=Wb!hE zglLeYdO(?~5bj2RO!|VP<^t6oLl{Yb@U|3W{1t?erVv`PKt>Eeq8EWw_JdFw1K}qP z;|dd?4(2f<(Uq`S1sNFM)9Q5vaQv z!q7DckDVc8r-Ix?LCARlvZ@C%dJn?n3XtfIAi;GZRBZ)WDF#^>2aaFa;O1fUZ`6J6nP&4uYFl!SF2u6EB2ahQn#S z16R8abo&CQkqRcy2lKRrVHp9Jl?n7{0dD;R+j|C;BrmDZEFL?rhqh@ z2KVR;GA9Dt&#L3doufNXR^p z-#n10Lm(aBLCTXsw$A~@d_eMxK*|h3er|<OokE0vR6*lF5Knp9DEJ1Bu-NQe6qc zMFj|1y+IZl0+rK1HlKq8_=2qZfpmC42pI;_wFW|4b)eRE2%lXcY-%99Gy|D?1R-J& z$iX6z{}~{!ry!)w2f26!a=RF)dkh?nD z?Es-=B!rFb5FX(Uy}v(5W;F=2O+czCkjkMz?L81~lRze}f&4cBX}k|%G#n&C4?<@k zgja6}FLfYX@E|oqN)mjWDBvUkC%-t+z=;Y@7I9*P6Hc7C;$#gcD>!k-Ni$Bya3YG6 zADkTGqz)%7I7!EeGfv)dVv3VNob2G_7AK-Okv4*egA+@ftl{JlCuKNU#YqfKmT>}$ z3lf}w;lv3i#W;z>2`MfntRQmXWF05UhamdkA_gaVI5Ecs1x^TYqKcDmoS@_68Yjd! z$->DlP6lyeg%ft1RO6%-7c;m(!O0#@Msb3QlXP78;6xTDrMSSr$sA6!a8ZPlK%9W# zBo!xJIC;j2I!<13ae<2(oD|{&4i_-E0Kv%@E?{sXj*~f@jN&8{C!@Fs!Nm$rz;RNH zi!7Xo;(`Sy$GFJBNgpm4aN&g$MVwgUq6;VAxG2KK8!kw2;f0fQoKWM06&DJ)Fv7_= zPM&e`fRjU97~p~c7Xmo3#0e@c!f?TYlUG~-;RF>Yj5wji#U4&_aiWR~ES$jOVh<;? zIANzCYrsh|F5GZ|hLdz$*x@1qC;zyB!pS!-RB$1QizuAf;$j3R z7)Ew#GBHe<8L{8`%etE*4O8k2tz7-wy*`K_6_k=@SQV${HG(K`6sr<7G{GZM%_tRW zmPblb)Nq1=W(XC%8xtOc=PpZ#42B8q z!nI}ddzH*b34dT)cn}^HjEfHr#6wqd>G9ft$iMAaIv~H!`&P0)20{lV_+L7R@{fF&7dZ3bW4P zBbObgWK&;2lpd-S8?KxE4WXbEn5r#25L{3jhW9HOR9KfCAI?7}E?gT{>Yl$I?^iP* zUBB@-H2iNZ5EA~k7ML!v6&M!$J1!+w8{-=f^uQMk?S12d17qTX`odIdVKG7ReM_MD z10G>*WPGzIf3PdwKQKHtELb;j9kiSMVSgpiU-~nX^wTWJU+dp2K70^9pAs-0Oqd}q zJU-Yr2?jA3MmaDdSc^@GxBu=!esdi2YFX;}g<+~Dr5YqxQ8b+yBQUzP)WxO!1YPoG+e5nlOW*{=3g z=3eO+*yOG8ocbmAd`k3iU;=n{SWq0kbS;QMOq@{K zb-V=3Sa9IdL;d|c;zNAFTktk_Yg=2Gixj!zKd@NaIQ#Z=@^W}y6JCzPt>2<-;a4$c% z!)G0)bh{g5pucX1&(iI_C4Kyb$DjW?j;oumou{Xpr>+;6N88oQ&ePS}rL47t6E zZmzzbcJ|)gb)$}uJ!tBo7>tiSg7Ik>*=)))e3``1P|{x9e2Wb5l9Jq_gU>E`8T1Lxes$<4(Y zUzhI6om_iZyTBf0J`2Wjak41^{JsAY|MuTLXGkTS*jo>|=bD1w)3(s4?H3e`W1laiO(A%)Q{ULq7$ey)8754| zz@NvH?g!iO;eIYSpavP~;;KWwn@#D2Iu@EjwP8A>jS6%<*_@2_^ zOZ(BKOE|y#`+4cwjXZnV+u+ke!O4LzJ1vY|lz(z~R6>+dDIg#rBm`#^(*5IfS8Oye zAvhrzdXOF$W`pM!&|QzxKm*Pk3N>*`PzB_g9wvKaXE} z_`sM1VCm1R_|0|rM}h_5x^z2~X4A6$VRT@LNlHegOh11a@#vW7;ADu^SRH;^{eND6 z*(RON{<6QsW8}uwKM`h<_78}}V~dx+#!1H`Fq1FNJ9S%szg>3@I@n+Fyd=K=-g#w? z^Xt%sN0(%C*iFiYR9E?wo{023@j3biz@P$MF+{rkmvj6TRu;E@O)umJQMTXspM92{ zx9)hrNbEO};ZaaZmMqfq!u|`ijfT17f4e;{Sc`MVpAh`U2quj;`qj~GoFEeE7HR*u z?t=NS!QX%rprpUuu2ZXcEVRh!IR4yK`4nSDK{X$HHwbWVjl_*0tq)VZRQDgLjSI}e*-wVI(a!+yR`V3xs?p? z-}Lbh@VdOX^pyUF*PXymjVe8}5|xM3Gt-@3seei~nzkt0{4>9nLrD3kyZ*AH{MFH4 zxbAXYm0bVdh$7b+AWQSUKZTd#<&XVKp8mf)zrW}2^3cEM_2tC4ZFX&r| z-^gt*xz&;o=NlBL6TpAM#s32?C_FyUKQ0L8kiL<@iNTR2NB`^3#kS6A_^PIst@B&y zK9{Z!+32=koZq^n-KwMRbDEWIy|{F3+C}#{HqoI3XIk3d>(chkw_BF9OV?#*5-T~* z)Y9XZ;Z1Ezk5{@bJD;+(#14`1rFJMut8q{%O_3x0Q%Y{sl(g$^66v;-W+aMZI2B0hnq{fJxVr}v}2>;TOKiiF_FGduEdw!1x2W2yMJtKNjBgc`!lgDX~*}Y zaY9jgZZWVczLSJIF4-OqiGRs0X~;++;foH0z^B#SNBhMu;7(7OSHXRhviM_Ea;3U- zxM^utToQWfM@A+XnV2TSI=PXNN!|MKbs_Tny+3VuS=w*y;_hk`l@PBr3JAvewC;{) z5TyRW(MAdJIHC9OcCvx{v_^21kVuv!aYkjMVH6!48l$TYbR+5Kth1x3i*9XH`q{7a z^TpD&yQ^+{1-DXs>Ds+?9b39ibJuN$-{>vzFLw{!I<|EE(=P%8@hHUwN5_%ue&MC0eT1$Z*Q5A_my$Ykl&;+hKI0c& zO4`$P?SAkXzwlDhK2F!32A}Z@FD31hbnQAt`>UOmX|EvDo=-nJ)S}jjMSW}%M}D{T z_%?5C^z5QDS6dv4j8k^l_af|hPa!1aeWT-}^)C!=l<7Ufso$3H4MmgB@3`jWzwP?T zewT8``PJ&{H2L9#-R=)=Q{MpqD#GrOA970bePuvhau_H zywUbuPg;y0w(G!}{H_gBM{eAC_G8!hE)ORTiyUIpJSjN+*v@(#b6VszoMqm2CUH0V z{lxiAI(?f^Wyylu-JLtTCVt&=Ja70&FNcmh_T;M<`eo{kOWB>h#eDe1*P+i-$CGz& z71o`%*Lz2rP4UIW?Wgvt(rA$1L+3RoJno!n813!r=G*OTb!Y!IFAt=-te;y{YenAP z!ON?qH-58aP{X#nH+6WmApS?!g@zSZiEk%g`x=)YoSER|>ltNyr}e`@i*6{gw`c75 zlJ}&z^~QlCj$T~-ZcdNJH`t?t4XCs88+AXgh<6>c>G7aP)YOK4{>fWgywCg6RPp)w z<%EWVR`nl}v$@`OV>>U$q~fuUTQ2BR!@k-WX7}Yc!-FDi1{v*7teW=4xZSqdr`sp# zMcCFhskN%p(H!fGz2mh%it;$EX7$tlv!BmM`Q*K8hPuV9HTsPT*M83VqO1|JwO!SD z)n@u#*c`g^MR;4b(ES^gyT)RB+uku_ zy4hFe<(TThJK{FA=ryi#|2rXXGUs(|X`L6bzV!CUkJFditueYZ!g+FqZ}-0T$+IzA z_ei_g?E(A1{^p)TV^v9!{rm^@tag7dZ#1}?eiK8_paI#P;>pAtLG1XO^ye0DB3@pu z(cp6a`33&B! zu8#NWR)gFrO|@1VnjKp^-e+=Ll?uwwbMzZruJUNW%%`bNGu!G{>oxPknI?BmdAh{B z?st6ql%>q`r6U_=D$)i0rb!F)+n={+Zr^`u%hWphr`bsD8*0wJuCA^5(5P9nVwpxc z3-@}CHtO*%z+l#fWw(s`1&{Q-Q19F7&Q-(bUGX-saLk>fJQ%oSS1LNvvCqTj9w8=9 zj}4tuE7n`IamAu>K3^g%U%uE$7wzc#Lmly=&B`ZTT#8N%?H`c1ee^@SBOXyvt?#?F z(er&9#WgXlY18i9*6K4~-KNYZr?6c;>Sk7Mzw&^Z)Se9;&$^P0E*acPn-Fl~nE8>g zI!klKQ)S~`ww`N7o1bc3)NRV4l~Zr+{E>e6_LNC;o^G45#%FU*!)f$I1IO4piMMO+ z+I0QF`PfGOhA#^Gc%(0BZ@l#A)WvSIvgYvv(Une*JH2DsdcVur~ zq080Ar=N_hpR2C2!#pgbMu!JQ1N0jno!g+#p8XZ(4IF#@@t9SWI>gl=*gF5&|Nle# z*RwhsRr^!M<7-;2x=*u%m0tQeb`F^WzsX2-h`wGp%(CUIx6PlQ>XF+wr}DBbXRAMZ zeb8`x$F=V76LXL6oRG7GHp$O?`?AXHRrlJYiI@AI)w^-u@!-&?DQDMuSvSdIt~ww0 z>Gfl$T`lpz*s~Tx2dy!FS9tQkuu}!S7aFLinpv&hK7yZP-y*hu&WG>X==0Y{6e()O zU8?f5^P1l=vco?;Eu7CEigWj;bntQLF-xGP>_Jv;N zg=cx4a`nggq;GCGyPDaJhErd3AFz2NVQSsNGVhVlec=W=<45uSHhVfI)=oHe$G(AI z)~&0D8^oqw-uC&Z#q?3+fBye}vHsn?@?y^Iv{QZqqj#qj_At!8o6#fjfxGF#wNH|I zI6Uk%(;=Gtx)T0-zKP|_oaSiW*z1u7juUKDR?`=ac~)dUwRPCi3$>3%y!#yAtzhW> z3OQSr41LkBy5qV}wMN^s#|_>E9qw0u@!Z1Mb`}HHY3~VUcbgU4b}p{mIBI3`(yi}1 zG@;ww?(;&?DlDaN%%P>joELn)J$ht|^z1Xv5vETggTBU_pL}gxV|CAGm6=qP-{vHe>U!_YZyM2d--uQg3<0j1P(RUpRane{hwd z7F}5|X-CWK_Iu2B$6q{l;KszeE!XTwO|pFW=zFD@>C3deD<1fd|Nq6m|LgLf%DU1A zDNENSwNdGNyfX4Ctv|hW>z|wY=|21U>eie6O1Jy#)>8v?Ybb;h!{OPG|M`5G?wOMK zzPh!qKa`b$0r2<)JT>DBcaY6|!;+v<^^b?UM)<2LqY(IFA~>j>5j<$ttW#7%q&B?d z_I}9?1pI{+{-Q4wKfh*Fr=w9>$%w2XO3x#*^!!RM;I&rw**!_O-ke;zJw>-(JV>`L z_xZz@oVqLcIbtPmaJ}gcF9NQNMSwFw}VJ&D*!tqpDWe$#FUZE5hL%J8KHl@YWZ`b~Qs zXv4>q;&B@uPiZ?m)&AT5Ntt%|hmzmoDQG|RoBoqkebQhPqTq#>! z%HT{SxHK7@r35!h2B$l#fBq}AM{$NviGAqOUCYMhKYRS%U;aObU%9Im|l*d^mvQhw}{ z!AbdXNCqe6$1xe4lponLIH^6(%HYb&k6nLg4>??U?Qv1&I;8fvDua{S5~+cqoG_uRXH=&>nKQ^4gm|y*8kKgm--?m5LAM!&ES6+VT%lMU)9|kfwDL;&4a8iEMlfg;(VIqT* z@}sE?uDtvx{zH4n;mT_dQ<>|K+QVE1C$)#A3{Gl~4l+2YJ*;GKQhV6S;L2+c_7CIv zfA;vjUj6I#nEhw>cUc)+dHLZe<5yCCxX9q7{BW1SN%`R=gOl>3mkdtIkG?Xv^77-} zAI9_l?D2bk{M+`>m+^b){dPHAdHLZd<5yCC1j*o}{0Ni5N%;{egOlg!}#%^J$}!Rf7>1=f5;CxTzUDCEaO*Fex%Car2I&e!AbcsN(Lw8$53=Q$l=P%kEt?#CFMtk3{J|AIWjmYKjzEer2JScgOl=O zxeTtn{Lufy`0<}Te$S78+a8X8$PYPOdHJzg#;>IOSTBQ<@?*0MPRfsMGB_zecFEwR z{MaXhD=$A@|6%<2&mO<$$G>fl)ieLBK9|Flmmh~@{7TA?V=_1?KeAg>+r#7!`5}iZFF!WR z_?46&+hlN3e(aLLN%^r)1}EjmAsL*MAID^H<>iOfAM)crd;Fds|F%8cH|g$6;omR7 zi|(jDen_9clEamkAK5Z~CFRFi8Jv_K7iDl#eq5EoN%?U@1}EjmEg76{H2?W;vgH2N z)IYR`9Im|fxF>TRQhPj??U z?NKaq9a4LImBC5vfu{Zb`wFQ&C>fm89;^&bY7brpS6+KOFRcgh@5taqPOq#=e+NT~ zliEWLw@dOn7!_o$LuwB_8JyG}`Z74FJq%=UQhON5;H37bCxg?C=0E?H@}sEK9%aAh zBxeuDQhP{oQhUhZr1mh8xelp4n#$m$_Ar&fN$p`SgOl3BQU)irM+X_)KU+eFklG{c zmM)&--vz>poITuSbWLiHKm9!!E1Bz%+QU``C$)#83{Gkf7a5$?9_}(YsXe@8aJtd_ z=f6^Wr2U~i{_S|)OXfPH_UJ2vliI^i1}C*gkPJ?0k1!dW)E<#CxPP{U4k5M2oIkY3 zza7tGWv)YN53LMNYL8?YoYWqvGB~L{(qwQ_dyJC7mDe7{r~d5uD>-S{{TAuob}6vCr)fCLGrrI1W&ie`$O<_do)7ubbEX_1aH0eIM2`?VR-Ac z$DJW^==S(%2%c__W(b~ck57f*>Grrg1W&ieXG8GTYmY64_6WmUuRU5Ja_IK>LI|F2 zk9$J!bbEXy1W&g|I|NU+$2UXp)@zTQhV}@GtS^;OX}GVF;dX zkNZOKbbI_X1kcnS^sVmVw#%kV+oXVk=_pzkJ~q8$$F|GpY{*M4*$H|$FVcDipLdIM zD(n9o3!IDDk$jxP7!w%t`J%w;+*tLO{B@>>{dKLE$6b2fd6&P&`RW{4^_LV_oiD5Y zIxpvZhPwZP-s4#>la%sd{1l~p7(dBZ2l;6TKKN-141QXIA7;;};D_-OdkxnI zern$h>ZkhJAU{>X2R{vg!B0ow^3we;DMaUJLS57ku#35*YkMev|RT z_^|~)jGwBMhkkT^n!gp~rz!a0rz0@BH`Ot^`R))j;r7HT;BoBe ziSZMa^26fiME$2eWPVQ6ejPSk&@L+0m%{pTIS)lXgMg~gwy#2<{uS`xp! z@tVZLu=vy(GQY9<+U@T|`RxqZ-pSt?Ex$FPKdkm*jmRH9D*ZRc{kp#l3LEv`+q?ZY ze~a4vs;v7VTKeLpeCd>HMt|B7|AIbi4}4~D{_{?@C*~7TfziJw1xEj#eAn9cFG_v7 z{NN|@ZY~dg;$Pn%;3xK;AU|=z2R~JT!B1Q8!`gdQ_;tU(K}<#dnd?J)2aNZss$b)L z#E0s?Fs#ed-(GV$`dYX*;$moS$F^zu$Y{kWk+@BesXa6eDbUt8ow`$(pD1=>gZ4}$u$1&03O0z-fO z+G}0v^Yfy9_xJDek}n*2_OHD!X#d!M2mQDD{viJ?!3Y1AW$UnYAjrmYV@)0kK0)zj$z~Ddn0j3wme?;&H=Rd!k%Yl2#`sp#APwM>< z_`vh|Q&-IJZn~NG@jxz}KhV?D!{GY${2iBm{Dqa*(_yc;=ofs}1cuzmN4-tSNBe^Q zVPETmY%k2q8v?`L$VYtXNIv3E^-a7Ui2fwjV0!3(q5{JoYJbG}?suR_$g04)yy5Lp z``(yx3!34(-l4ujPM;N{Phoq*12?_LumSqCKE(V$pOOEMVNag|L!YhJvAob{O`qUay`jJ=idb$vqK)`aD)N&VxJ zxBlVD+BYfnk4xU-A5T`^sMJ3$d1HSvS$Qp~e_ZlL{&cePw#F>)p#B`ci}i!}To)Me zx%v){kBHAjfy3f+@>5JtkH4^YN9ZG7*FVYlh|e)8kN6xHI4nL7>d(WLw?1Zh2leM+ z%iA8ayzODPU+M4R&vAjn{JAdm!+%FT-e}x8PIJQ-*NkMcz_8qrB+s(YSl))zKQ4KjpO~zDt5W}{d4-{Co-j7K%>3T+U5x-#WcD zIy*>ps*bJMJXK16{(5^nHi0*58r>!@ueR!>{z`P4=gQ?LT%m z!+0K36&TM?T7Sj)Ve4~P-@tkto|j;~&X)36pKA*22`WFl=O+`EwjZf3E){`xE@R^;w4D&yl}j82%g=82%hht^ zQa}2i_TMu;{5Ae1hIRYHzhhD!{u~$B71H+){Mr5|rZ*{h+hdluK4E#2Qvay!YubKI z_eWe3GH!q$qyHZExZw*ju0i|qxv={a_3G*U;9=`$*nFyZRY=d#<~fdQ1I0%w=#P(z z&RniQahJoPw;40IJ0j1dy)NJ#Kl$eiM^d>L0az2Wk)L z@b*yuR?y$8(mvqtO@ZO>);Aa*{*L(}^xcqrw5R4b86W4HfH(aQs3C@_uVnuZ_M)5#w=f4>KmK={%y?m8Q&|5T=AE@iHoZqee!Pz_7TK zN~`z4rGr&;dp%P?|Iz+wFrG#PhCPx3qkY`ppC>dYEbq9VC&VT!@5XzcP|Btfs~;$! zJ#_vj*dD4sV;JqhmVC5_`}^~R>V)MT_w$5?*c0Q&aogA4aL*G|dszKI0qr4TUE}T} zguar;gYBU%FxtcY{eAuVgykLg`})yMleO=--`8(WSl)5JuOB~Uvi2SK`}*w(%RBb> z^*0aMz5}jzjr;v(>(t50JMQ`*ZSvleO=-{kbz?dB^R~)zc?y-*NkMy$Z;L;Q^Rb^TDX_jT0{zjT{yc1X`<=%*Yx?7%i9@t``zH{ z)z!$5ml)nP1e5S_UHD5 zC}>w%el`a)S3{$H4oz?ykVWk*{#oa zC}%G|w3l3?p7P1;+VhCwjhf@_eR`=UYXQM~!9tf7QZp&tq3-JC`e|d?r=OsCra4 zqS6LFzf=n1JPy#|<2Sl=_4A#9rwxm&tFE-H{d@QB^~>YMq-KgY^3IFit ze)85fn!JYn6YSd>P+t4O4QAf~z&*hChd9e0-f0ws&f48sU_qNe~YXjQ1 zE%^7>_-tP^m_HWVtibkV*R6i#-75kK3?+1 zW5Pei+xXtCH-47#qxRote)U}!uiX2%2UIdRFb*SB9%&lSKRg0F;`PApr%POd&`*6j zsGsO|hGGArz!>kpx?+POfO8oammMcwR$PzW4vnbU>M`on&h+A zy8jM)J-$oX?AN5~H};$KVv7Esj><#{pnkZLm#$5W;7=XVKiXUEscawkQ%hj@Q*kHf z!=E|=!=E}&=X|u!W{hF9cjUvLikESIm_IcnAN~~E#rW{2_~i`4pTfT1Fl>98ehJ>iemZieBH zF@fQaO@ZN$)*i-(KgI-xKSuU)KKv2+@W+_cALfrWDGz__JcH?Z{wV$lf3$?2Za2tV zov^%(G0WSTu)Ov@w%4fbYZ`Bc9Y=IO3xiGh`)tU$hiG3oXVNszh4G`O8^Z<&Z0OqylXL0*S zd}<1e_|$kd=OaEPpUW`fQ*xGJ#HX6Th%X%}k9cU^#Q2C;HGvV&>H_OpzTs`Xzh?}( z=y$BAKDVl5gFK+K3J)2EchmY$f0@}i(dWI2pSMAeIvbumhV=CEVQ_l6Tq!J_!2TpU zzPCI(mrEUXrW5KY-|SK`M~*Bh+;PSA4Qed6yN!$OD7jc|{9(4W?KVpV> zrg2NJCkzhn58VKgR-r@TV4UtI^o$H#1N@_UGusFLVIO7~{t?MB480`t48uR-MTX%Y zky{wX`6fvzkMVp_VE9KvVE9KW62(+0wN!TNfPXYgY)|+{yv#8CBf88m{G)Z0Vb4ES7>0ioZ)F(qqbB7MKk5R* zKZ-{fAO2AlSXYFxe~f56(|W*U;>XT6@VE!|f?i+`#I1dXcz52M80vU0lU;Dim8pC| zHYy2R$UEi50)0`wkN>(~H}JM7O8rnXJ*wEXb&j!XNs+rxUl z<0km}9T&#tMN$^>^?s<7U0AFnoP4^Fagj^GHO_~nk>^T!9XJ8l(I+MPKKEFrT3gg>t&#i*zd4E!2fCj!~d%92>M@BVEA80V9)>F zsrjG4@W1xE{&)G`tjx2ZZ}``S^S{IC^0sN^MFF>3W86fzM$`VE9||eVh+}tG}ON#Jh&T@VC|nI3N8}SiBo{d^%s^7}^!=4!#k0 zwuIp6{&BG(UNi(xuh%rbgYSO#F~`Gly0lWPkkhGP$8&V%Q28Hc2K`UcQn>}jgFhxe z%Kia6H3Wt~Mn1;*ut!5+_+#|roDcn4pI{jN7!er$*tv`I`}w1(eN6k`&P&anOWkLP z*UumH{4x7SC0E`?gW!3DCAWV>V$d^!{!srk+Xw#85!myGzvg`SgZ&wX;SZ6|G7NvH ze~w}JLqlNrL-cPsAN~*%Sl1u?^@RCr1^J77A;_OC@SyyiD{%*U(fLQb10Li79?Ai4 z*#2)k{ueo5PwG_n99oQorZMI@SLvfcBT%>JT#?EW2<|QN!mrdOiK%VaKCm=>@eg)o(sgE{i9- zF6;uU{f?1(y00e|{4e>h><{q2hQRQ@Z z^={b1qo-HY2Of6&qvsnrC%@M7OKNfD*>ag~sv~iKpc5fp8SbtP9J}n&?W&C;1^#UP zi2V`mEh(_q-tOak=s*5n45Pi-KMDGC@n;O9y;TK9dy8(m*6q*H-eLml>NWK@Q@fk` zx#@h$bRK8A55&~ZG5&)+biKiUP1|Ad!`vP`e-MJ84|>N8@vuJ9kDktVKX};fYq{)9 z<)~71FVhpgQmRrY5!`3oc37?Js`lpo@LCh#)kCX!$H~m4(uZ~Vpr6`iZVzaG9f8sQ zVyAIF>=Az;!)Sl8(-}tmik`(V+Fwjyw7@;pp1p^*Pd)qKuDCFeN*^gsW%Kg| zfhi(XR+hUdE_|d5tGGcsr{}U2e)L;jE*7VX%X1*XFg@^*g!ybflc3eiL^k8r&?n9u zyX+FRxbH28S(1=&pB5j^(2j8aL%K{KJv{XD!1L_(aBlyIH*tXxZ)%U=eAq8~9>eh8 zrof0d#Yb^I;zLzn#GBZoIUn&RE-?7Q-L$=%_NS)(z5Nlh`5pK)y${=8(}lb`p39x% zD<1mz&*9SCj)4D2g4bi2jyFu>tEpaq*ZB|bU*K0r#~pFvK0`cHK27}$e3;(RzG{zS ze@AwNd|7qt&EQ<_^y zz-io#kw{78oufi9n7(?vgLx8HW6ktqeo{;x>jMe^p?}U*F03 zkUwnw2>jSjX8eu9k0tt;G(W?Bo@zSYYJb8k{)WX<_z~ho*gg{-?_Q}F?Gk>g<8=)2 z?lZ)*?qYfS)!TjzKmY58H>!9Rrf;-M=o@YX z<)livl?1JMq-fED{`$nLRB54*SNm(!7SC)d$BXAwE}hEf3l%$+%N5e8ies0YTb8pW zCu37Zh0=<Tu@rm+(syi| zCVr0)w;6kvD}Y^DDLO74#V2iKCq^$=wna%7+o>a|Y%VpIb7t&q%t#lH#BqRWZ@FOk zLIP5G+f}R!3+H@WN+>nkOY}OSJ?Gd9WQB@TvI`}fDo*9N>`uFqU2@6V>dW0pt2zLf)J0j!=E2kqiDE6Kjs@Tz<>3lkp77lSw>0?&(euMS%2!;`gh9f0 zOZLEH6$oCB{K9f2L2GUcl|{nokzYJYK1}k2(J!ZRm0snJIHhv7z;3PE-^)Y))XZ@I zgmxcsg8fxhV8khVf%DOSMg_)x&(_;_xbt`Pmu<;MJB}RY^4Q;56&U?#LtxC$i;Ikp zb%3hC*q?0Q%=r%%Jx2w8h``|Ip#ryszJT8CntOO23B4c#awGo41P}TO!;6IAK@XtU z`m|YmMm?tYw$O#0^m3@bV~DrWJ!S+kzslgme5g7gu zFL6Hnp(rr?!FtVZ*WUg70r9jZfXdGS`QA8W9-&VpTXF@w8Us`r$9FS2Ntz z1phLfFHg#^Zrji61F#eLhn^8HZ#Trd!w~OIL%h2U@$NCiyJKH(dEtkU_g}YyBJsFpJN2p=PBU68# zRNQjUmEz!}UX}IUgf)w2R3s#xC0`SaXAOZ7&!Vpl#suHXA|H3qd$l3nZA)hBWi>;*w;SS}ce7c& zru*u?V0ix3S6*nQ=PwxILGPyblm5V(()+1N`Gcw5fH!IXd5pZb*RS8d{pn`y>kdP_ zwzMyd$Dj|~5qD1dH)~|0`1hp!)zoj`NB!zQgBFwCj0kVW~2kSxg*OKX{>tAbK)KJ2AXBRegtjQr(%wV=jW4UiovR zoStmm@oj$Z3wCaNpP!FFjHbZwi<9FO)(qkb#&M=`bJF9BllD6?`=MQ!-Y0GENzH%m zm3b1{iLNiSo0I-{V*WU3|3be||I^@j!Mc;-u<=+&@-bfMe1!2aUa&sOFveqz|HE+D zc&sh;V>}l97~^9+*7!KX7;iNN#(1mVHn`7hW=xJ z%`o&|6&T~;rohmDTVUwF`B^Rx{kH`6^#3=U5B;}3$1wC?`&)*g|3-^p=)WZ}^pAY# zzw>#<*Yyv5MMNLaSFMk}Is@vfem~I{#;~w%n&bbh_`5nS2e`D-4L%~h6s=;QH|@jPfr z^fz(C_>nZkD;nZe4e@G*cy&X(h9O?l5U*v3*EYoK7~)x`?cEU1HpDv_&wIC{pO<*v zf8JIK%-a;yYu<+WN9T(?Kf!z|_THU=^I)3)$oZI0Szl%t&lhZg@q8gBFy>oHfid4| z3GB_czQXh{-->^gVa&Ih0%N|_78vs_p!jaZ-2A?vd`A$?-~6LCe42N=I$e_B60y?j4-Qsepi4A<99 z_mfOYkCW2hq~tZVhv~kKe*QUVerEBovow`Gyd(wtk8_;#G2i;Mf_jZ}B;8VX_hbfn zXBp!k>)YIaVEhmh7|#!^dpRHDiH5*v&(-g7KE@L@fia%2zt8y?PsBP5V|4oXr`Wfek={xq{oDY2`1rF19QSwdo-4uN2 zyDIQ{^<9_p{q&7~2YS}+f&NKP4}(qPR#$@|dJ{!t!x=&}7` zGraSvW_YI0r@txu^|SN6hIk#pLwtjrxI^Bb8qz!cRc8D6P4}@hq+Tzc2xG7h_yfPD zcT;~n={G@*Lf`+}{Khmco%ENJ{-QKs8edNORd0Ve*?$G~qCi9<6ux9>s_}njejToG^lU*-~YDx#H9P{Nj+~feILm5`IzbY=W4}n`Oop-F1N%uq7x(`AmDCqU za?V03z2cVxO=kZSzJH%2er>(82eSM2Q!TQDiMLb{XqhQ|C+$qA7n+iJocxw z1jhc9=tDRk`+?#DV?Pk`(cjmFU-SzR;TL|}5*YiX;%75`?B8iVh+*gjcj(7@DCe8% zCn@-&(oa$7hv^6T&`(Y9p`Yr*SRUxdI+x)=^@Dcr(ShRRj{am+`}<7mzr^tT$7>An zCM}Pq=1_1_`Uz!7%P{3nD;5g&kB92m>eca3rP2vRiTP4tDU+(CP=QMCwZAhRk|D_` z?ydW_9>MJk?J;&9!`Oe=ek8+apB>3ZyJ|l=*glhwVHoi%@>qtk-!u9+hR+aAVge(6 z)gI6J9;5Q(4Tk5_)eXPL+c3mSZZn&&HbdrbkQ?!)C3w)EE+_DY{axW<>t#@R;Sb}I zmqr&;nd}06g=vbKUXedqOqGYXL+4nUz9+ZfsDr-LZ||J1r4)VZ4x=i{Eap<#JidxY z@J*K`E}2#z5=EMl5&d)H3GB~kU-9!9M*FH=z_8c8B;WIoCvraeznH+f9#NkqJeO|QBM;}J{lvDjzak#g1xEX^FX4Q&m$tx&H}($B zM|)`rjP}wISl0{cPmZ|$_@%wuBkHe?xc){+{RZ(-^%!1!1i!7P2JKbb$uR8I5*YnO zLtxmibs6KsKE)Y^5zlG@Bc3${#{4;UIpbq~2z<<+lai0`DHX3^e0*P|BQU!U6H6IY{(`cdE-dFVw))C3eaP4Sz%YHFg2#4OT!4Wc;Za+nk0F-rd}_(D=a%Q^ z>2to`_iY*9CbY+0LH}A(XP!Pto1I??3{6zE-uSJ$kNpvLj_+p}?XmbwhGF-H_G&$g^U+>`@3mLSM|-uN&G=}qErHQq z?dNhn+G~B5VYJtVz-X`0H0Pte#sx-utqP3x+7KA+wJor#bl*Rw?e!)ZcR~L?67Em5 zL(}$k(@V_WN9q{j>HLJjru><CUUbrjX+oLFbid$h z5+_wz#7RG$5(PZ^xVak&ReG^pRtHlTmn%*}eWaU$p!%+Oc4>LZR6W5H>r3u8ja8)_suQWK8_(R0&@9X)Qx4;`}Ulem>qHeDe;%JdQS^kG|l zsM1b>RmD$lylby|#3vOM$*e)-+ zy&LsxDP@-weXgF;Evt~vt=RFacOQDfHd{Q!E-x30g;K@I*hfk8_O*LwaL^aF?oADRXw6lJ};qmu=s6F~mNyZR-xZP_mWDpn_B`S2*g3zlaZ% zoOFSHGMz)7K9wqzI14mz=rS+k0#{wi287f#0ikvIaI0nmxSXtF!L3l)mHFWM6|5e@ z(Lx56jNFXWa-|>(QcEdX5Etjbwk*YHk5ZyN5^H0I#Th~vP z3MGepo_K)A97U59A9bhYXcDgHY`GwF;ox+-Uf3O9TDS1{3FE(_z~1xCGUsEwhkShB zv38X6F}`c9FpTkCqU$oP#yu8ulD1=wan$i_-`KL z{BiSdI=;MppV|8V9fF5(zpgKgL-q79cvAId^W{n^pLW1kx{$9p$0}2*XH`9($vDNy zbZ2z@o4XTt93ep)Yr#%tddH4!mnD1{Zq-ial1p~3N~LvTmv(ohcrTZ?3tU_z zYI_we5y<^bsqo*n_&4Tv^%t{0Vt&^a_*5z16c~1nyoB-5erp0_{?-r}^S8FZXb-iQ zae2(&fRFiGL-Nr+YA+4b4~Ac6zCJ}#&mu(s&x<3`c36AoyYw&L_hFH=x5k+o7U?Y zyw4AA-&3mhv<{~#W^p9#izE20jr?hSoJL&KQF|*!%m~`I^_%RU@TaQ4XrImB;(WBv zj=*Sd$=7o}+FMg#w5Qe^I3Mk)Be1Rx@MDjepZFV@zc7AcW9FyPho9t_`H8%#w|-3e zIkl%kc5Gl;ZmBe1U*;_=!v57abA9M0J{s#EyZ=%1=`0)S8?=TGiuL+F)re5cKufKUG!)PCMfzdu1@8*2;H%)=j z-*f~0xkrX_|c4eI&n> zQ7hx1kE9BGpf}N}9J+G>C47~ymdIa9> zhIn_&x_Uo)sHfk3Qu;Gpw}zhKXSzJl-$vJSczaEiSC-P*;vy{+&#F}!C!eM#Zt552 zVoGMoDXkPM)}ej7rnZS9RC>lqyXh(k?YaJ8ZZDpn{4v95&vk*}hnB$5bMa3YAMM%x zQ->v5_p#38s3EDp{FznwJ820Z74EtLj zMM4D%e{KNBgv!tPj|yDlqKR5EybqKEe2~PfTF6&$__ScjT_1zLTG17~@S#V2n4T z0_%FXdhfM?Bvbv~@hY=@9RcEN0BT=iae0m&sW4J_yHWN~*ldqNxtvQV&^@?Uc7i5~ zrR)(tV7Gjj=@AMQP^~IeEHCHe^j&xVqe`a`8%zhQo<097XwRg;o_z#{{Tc$pUafC) zd5q7kZ!wJVc~oGupSZx_1NTYs(-Ho`2kyh-r*`gj?l{U+KaGbnKKQ_WV*CjI-~;zb z@l$*F#?p^{-e~z5w0*^1xUu+YzIe3!R3FXsjoa5FHx@s2;UDb^_hGfKLH(!w6OP~D z1NVvXbJ}R_rRyj9-C+Nf6d3(iRbc1^_fhGmA3xUjMr$v<|LVt2{TD}TuR-~#{?f+c zC;7OI#gFxb(ek6m=f3`P{>I{`_{7oj6Z?B^zv#b;pAW{Ly1` zKauUDMmM82wj6VDuBXkE*}u$B+HR(b`LohyD1e z?ij7T2IVKRb7S#SpV?UaL@ysLKYD!b=ReIWHWoj2Y_$BuwDEI4{Y3xYXxsas{M3K2 zvG{5I&&J}Xe&%TXr}&R7FXmtMe_$B>S4&{@UmbzbZ{a?y{%cTvYQjJGz0`M z{nV};t-S{2$KJEC_-X9jSp0OJF^8Sp!_t2fAE3(u=vsAVL$yOuO6+v2IZ%7&Bo%VdSGMm z)4Xo9{OIwypZ{3bZ!CVQ2S>}#pzYoMPmWJ$=eQ56y${My^v4^EpVm1W%U;b>#>-Em z9qhl_0;B)3{$;%O>c>yy8>8h%?=SlC6TM-y_8OF*=8YSRpZK#k7C*I{M$3=hfA#a9 z)^j!%Kk?^{mLI*p=%=4%WMlEuI(4-C=>c6tF z^wUXfEPkS?(ek6mpML&RoZDFZG}EKyNB8H5!}Xzk#RNwCN(zj2h5M-5S3iCl^BYS) z*5bzECzc&8KYIJ>XRqqb8;hUT;nDJ=w=a8%>qGmB3yk(v6d3Ia_ffU4e*84^8%sZt z;>O}9e#>b2(c4!)d(}!Ci=TFRwEXDpE4s|}p?xIn;+Bf44J;4jCRuRuD)GUDI|(Jv-$Y~A&0+DNv}lG zv3=?dNV?4mM8&65`4#>ahpLMSDUyUy+-ZS6UfC2_eMl`KX9?1QEKVsgmsQnM{SJK} zjjHj!=%G?Ai{Ntca8|whsfbevFWpV17dZpz;FeyC4}5RUJ&mXbA(h^X5cr|*vC+Am zxokQc{D7M;KTr?h_vBZ-g4!!XrT3~|6s)vKYUlU=N&cYz2&tILmRvmwBI#=t8Z+p} zQhGgRgsAkhilDNa)VJr*E<1kXmDlXwZC}0jIqH4c)#!QhGcupAlx3;+*jLf*fq3ZJ zX*+&!|Fd@8u-C1?g?Am?b?x38_8vUcM=wQwqgN?#4ZZlV*4B$3v8P^q2y5uUhqbmI z{D|tD2h!JGe(T@K#Q6>8tDTko)PRG!RV}0szMr()paj1kSA=tU z@*FjxUd&3pJ@Nch2~QoLY^(w~H#OipqL)5&{I$Az6nstOfH$v!7bK_jBJ_HStWmYp zIl}7v*FYN!%F&aKR;wFFjdiE!@7Whr9k-t__ght+w6}1bF+DBcM~3rz$`;Vk8hAcx zUb_wxAV5>ef74}KFPXM=E%c=ms8i9AII9V|s=5%oRpfxzS20p=Pdq4Wbl zt;Bb~=Rl6vUw)2n8r~{$px09_zgC6Mo_Kz$9H))Nm;Nmb-%r^UU+^`te2jAaTE34A z=l2xDM+N|Dh0mUNeyTXv z)-)LI-Q%8v8w`ddr~w^+wSIg}X1^2xx*A@9oS$A#nS)dVbbI0lsVjVS&abJK=q%qo zguhBl26VKFy?Qn2SIZ;(X?PmBt{gq3)~WjV?TN2bx2$7)OtP_}ZtCq$26TdTck9&@ zpotWU7bNGazo+0DRlnRl@ipp%KbSjNH}!U>zI618QSaJX>hh=I>EyindrIxo66)=V z=c6j)UmE5G$MC*%AGR7#s7ASGUl7}u9>Dg-AA9!Q6f7a*1C<^qA^j#z>ok1spH+GQ zU;5A8L2PPA?mTes?jW|;pU^ZeSOW2z(gXBG59%`s+x#U0>An(_j`6x)M0HQT@i&w7 z6?OAvTuNoP`>PYZt1{aI42mB4TcbYv2hx3&uwK*$0)qsSX^M7 zA5{|=?_b2wZgRTK1zjF9pGkVr^;M~;4R~a_-@A$iWueX}g??`#HAN~9q z`#mQ{Kl=8df9mH`Bqbku!QGU9>$ijS_4kLPk`KDLo6_&+&#e=rU;LdQ|N8q0b;$?c zxEu5Tjv#$~|7cP2K^J#Z`jL8&zP|q{Ci$R?yD9y)Mql6m5qT%q54yOU(r-w4_`m-A zyM2Q6tM3ZxM}Pj;kbLls`vv6-%25jX>Q4XVa?AD>N;yWqj$KIUGiUOrCn+y|L3&;B zO?_9zd$4iU!Ru~})2GnNM4RrmO^jSG_p9XoOt~N0yLZowFuIVbpy0qj_;S7Bs-94p}Vs(C@q6*OGHs`Vx#R}Fzyn?$99oS}H zw||dRPx>Kz!aT75&<*zP8xN{8Ow}KcGrVHf-rZC2lW^C9iE?n<^g;rt@dnynOlM-XZnHy=$P_jB8T< z#k^~EhMI4zPIbq-fn**Z2a;5E-e14?0E5-;;`WRFxL>?(2)&u|DxT^2y%u zZynU+4E;4EANw8Rk`H~hKh5|UZzu0&7~}1t zz+w7q^{LkFfm-xm5|@)t*3f2~jb?Ge{+eR1vh6PNr^#h+rI`kN!Jzul+)=s%3s|KdVF%>U{m zuD{u*{>Ya`D}Pkzhsj?ZasBl^^>;>Gf8?IE+h0=hN7eqSed=$Gxc*L``eXk%TK`K5 z{V@M)jHv!$?-T#RgZO)f&95ij=P`}9F#H%=c)(hRz6PP-R>=B<^;fKS>&a1vmfcn?z10ELrd&K|a{~px8TCQJ9|55mf z=08bEx1;R;I(_J0(Kpe5^XWnT_oEN}EBe1qSIpw_Nx4_$uCeWb{pdrUVbR|r{$D$l zpMxX*+)m10OaC=Z|4qPu&GD!40oK1xANp7HP4wT|&iXT@5B)3pzeZZEKPqUy&Urx? ziZ`VXd4@$l2L1nc(Eraob#47eMbF?L_oSr9-n-L{vpRj~U(q+we{*k8UpoDL!hidx zLH^Gg68}1V@UQ5b@L#`bZT_RefAoKX{6Bq2{Ok0=zoKu#e{0v;{O=V0tH*=<$A-ke zP9OX$`X>C>cdyNVT==(63&x)}^x@w${^<0uvkLA}-)t1a@+Fsy2jU8YlD7qMD*3TN&R6Qg>h#yalPAL;?7u>g>j_v zC-n#aLVIkdxE$_!`x;RHymilKf^LFm0%k=1g}x%+4BDe1`hz_z$%j4Kk`H?nzrp1p zXGdVu=i$i-)j#a{c$j~*_OqR#{C<96Ka=rK&>v_EsLvUwa@f0}>AR!Z*Zx+}o{{e` z+|QoF*5`o!@6fy2({y=Nw;omiZ;m_8;-!J4>udq+6m(bM@r3ATwuss6&U`Bd&rAr)^4X%$-(&4 z@Z0$T!>Z3$e~lk9Ov5DiuPHG6v-Ts-hy5BqX83`EZ{NqTfZom2f8TT9c~zxb=obXQ z5B7c6e|nRP2fl!ZJMf}k;_)lWBOiC*0q%DPU)g+dxiY0Zf=h(Ar*frGa+VgBDzo#n zzb@f|UHiCcg`$(EjFOXDLjB$JOjaHJusfB@W%CR6b@9Ci4jsBCv1k85`nY;3v*qy@ zlpjxf19OFRDz{iDSDwNYyz)Zus_YRbZx>UQ#Vg#6qRfj^Nu(=u5QEwYS+*{S?#vw% zeB>_|rG=NuZjPItE2J_B;)`|zR!aO~a_A*$#a+9=ziQvu?!xe|mgK`8ZGmCO;wfAn z{uSNKF#Ibfu(0XfO#Q*s4?V(teiTXzTb23fbL(4=X7jFf)kabie*nJUCk|TI(SJ91 zwU(Vq*8~B&YQJnDKZ}YI%av@d>sPRc{Rq|{^dEiae%Bt*f8@NNzLSCveb)p&T{x=$ z-qmh-#JASVxjgJ`{VwNw0>}@rS)R=<6>|>l^sS^S*+RZNo5?OXbD{I&~IB{ zPrtvowtl06FKl?X{&E~G`lSH>(Z_Oq;3p>agP*FvuuJQ8j1PHh0>e(N+c+QbsQLL0bd;q5)0EiO8x@+{vIw8{MFe73yU z?b_THf%Z^*d{AG}$1#ldUle#$?LR8@hw00@o%u0s|1q&wSo@DXVY2dCQvbN*jhsJZ zc?WC{tuf2np0K=isejb=HE#dejFY0akM>@BV$dIo7ch+W-Vk_H?S0(+z5S%g$~*4< zzAI~8T+ZP7))e`-o{YNB!RP8_cVV>WP zIzB?);*%#UZ|hISE3b9YkmVh)J;eTOyzUh>1n_mS<4kNN$$mbW4Gk4xUxC6l#pP3j+)ypcxC-fg$`#zWi&y=z|j9C!U+uUE&rT=1~Y2mWvey_g|hCxky;-o{IqzkcxzwOU(^2k=Vkm=lkwNE z##P4Si;Sa={iOZYU@*z0c% zZVDhiD8V^!$E?{Ob?d}^@DXHxNr{424z zlu9R-GU~C3A58QJP=Wkj6CF_;{IwPBRbcpc@*2&b1V(&} zU(5MuztuPMd`GvZ=|0ZZ19)8l{ONSC4)BlDxf>ecHBgKv0S z@AZ-O(mR})PZa0qUpigh{frjv4_0-D$2Gz&&vFs+Gkpp8}4SvK5DRuPdx_Vu=p7&C)Kf^kEuc zdE=`PI*d%DZduNz?d%c0)4GleFBSz}ww#>WElXRcDX*L>1n4TtP}Us_vx}e-4E|vL%j10@wOP^L9hMp!`Ab#*TaYX zyx^vr6Ye@K`XyaIXis{27(8rwkBNQzwU65M{61Dcym|;8`t3=}YwCYt`q$G<>6xy- zToPgrU4O&&(=Qm#TTJI)cNo&s_1OF@g zzkl9&55v{p<$Lk>_>OeoN8j2TzZrtx4#C&cLBDu=Z~A&V@S|_;jjyKz-+D`Ld_5ib zwGezgU0h-DXd)#mv*gKS;_&ezm+;;zQNt%}UH+yDgQ?vBV_!9n= zmp-SqZ=K#6_1?l<{d!~1Y8BJ@?AC1FofD}VI`3usb8Q6Q!EpWed#7VO==Z;h`ho|& zBuvwf6zG`hgX4sH+a`TjDaB8BIZx9!H^;Kte;DKk_1GWmoxYG>3apzC$PX1~6S@2- zVp?PM(zUg$Zo2zgwHHjhbheA7NUAxhfL5(3a(spTw)#(ekAH&G8v+-<%<08X4u;9*KfakBXkAN0sD%zR|6>hyE0@D6IKKk>jhZ zkA~bWxksT#fs_9*7=GkSjBkOC=szO**X>ag{FWg<_B}%X^~`@;V5B4d>gkO)_Qvmo z(UG{R(`mh-Hyy+~;Iq0ZVkJ_gY^occO#Oh1bpu}KA6ahnN2mwsy4*-dKceHKztGds zFX-ur|9X13-09SkLuVlPWLL4rSbncK>md5&-hNe=bltC_UtxSxziJ3R^lN{W%Of57 z)zhJ0JstYh)1fafy)AM{U@ra(!^57h40}F0?0L<^o)=ftlj82E+Xa1r)s3req85O~ zUQOArWq*h57X3Egk=_zmPj7s;H-6{edZ)*}*E_xTe}m~A;X~&K={i41*ZDzu7(Y6l zWQX}k{s-ShJyu)N0Z;1Q`C*VR@Dcry@co~BkN-gK9zMr=>lBImoA}0@nqv zb}Hi)Pvd(`?#A&?jd#^xr<^_FANPW9tc%`sJ)f(i&YV$y_VXFW^P0HiZ;}D%*-M*!PMbKWNh#k_(@L}exzHn3s1SQ z+iujylGO^kd>}B9UUbrjxuSGwrC2G<5{9}ImT$a6AAe(9mCpEGy>VNerIr0fz z(&VxVlZN>v_n;E>-9m!1`6H=ZHe>7Q(KAkaz(wb5KIKvJ;41ncPl8iUr8GaRME1j{ zXz*qYet-s_rr<}Nc7|wl)9HRflfRE5h%RKpr=Wkf_P}qdJIvpjX!m!)p=iK$+_;1g+cc5W?@6?d| zh#;OW`K>sA4;baolOJbm`Ko!Uvhl}py=dPkXUmU>l-s@Sn6-P`inV(?ty@f6mikcn zZucYx{*!s6yWva;{y=!m%d>|rF$T)He z)vWqLsDewrK335XJJb1RvvfA!{1U!o>efe3xM})2msq3&vmB0WDrq{~jR!8CN>N{W zPtDUpmmgc?QTghN^*!?4u#uqc=V~>Ld=zp8(&;0aNC#i>XI&kri1<=TbA`-`%bdU} z>dj>f6o01Y6awxlG2y5~yDnfmpDy><`3$2zl<0_zjP|5<%>6;SowIaclpBH%`Qvsxo%fbU=juyzV^_S*Iaj{N@7@9fdAwiP%17S zD(T_=-0M8JL@K{BO*Fdwjyhn{Pt-0j-*LH1H5SsN#h_eBZ-t~cZwcbJOAHswz0>2B z-s!RB-s$#{V0uSj`)KcU>sasfdPsV0C5Yd+mEpGBp&z6-U(g#r`K!It<1Y-R7hlA1 zL++rD^xBJi<43E#)9sf8(_=4XxF&aReE%{|ufJUI<=&L^*st|YkH4aKdhFMGr`xyn zPH+B3Fx`F?!*RJo4>f^nuNHjCXx136{U+a!6sKqvwP0m4+}WdiW-2vTrbFQX(@<=2 zX)3FRT<%{vTlUUFQ~gdhmvQMFPURL9f;uxu-BW2gZjtVl6w{)PYKoo{(5k4)rS#Hr zy0Tny)NgfoBXuR2srgc2Y05cP%w^Nq;j2EmJmnin9CnDC!%J2{=5l$byr_1SlnO=n zV8n{BI=3*DFHBJ_`SjEhabL=h<#6ls7yj z-YWF{>m!bO*pj6UA|;15tk5PEghLI?-n(+~Y3;dCTIp(z ztmGmnJ^0t9D^y-Rd2$QUKc&#Y@m&A4lbIVIAn?46F1)QbC+)Bl9 zD_u&{xtEmgANLV?b&{%!pj?Cwsti<^bEec$mU&uKaw$5+sa$H#RksV%HlQgQ*_D-Q z-0{DnPsbIiOf`m3rc+ME-b~{I_bcb5^YRY2e7-U@Unni56kp`lS$=9pG+b@d#v^iQ z=#=GUX6d+_(v)zuBpOr07MCdfvphdfLlajuq$3&|i3hQs%ES{5U1*A;@R#!$HVXZA z+z*dWxsU3UiB!J&BV+qNgKnuAl_~^=l>!pv+w@kxmD@f=r-V|Oa@txoV^YmRTCd(x3`tIjP2W4SD8$I~>m-%4uA9as__Y7R?^p8CTuoFU>N zJ*D3DQ~Sv*+COGF3k6bgg&H%g#+YQMsUkI6#h9{nDxZRSsV!$LA*1}wZ3V^B{FJj) zosMwKQDT%rqeMP2v-t{`2QPyXw|57hE` zhIZQNvR)y2>CV2v4`$;i518M?=;HIv)GiGEfe(HGgI~bs2!DWiWZk95JNvsZ@8s{o z57x@_46~ar@?w2vGs=tnn^8Yt&;zW~6MLL?(fOMa{#r4ubSxHfJ}V)zgLL zMH>%aHXeJhOnf|;&C@N<>g~d;-Y(4Q?ZT|yF8mPJoL%^#8vHN~J~s$s9S{6%()71U z)88gdf3lq9)xSy8-=?7cPL<{h{8Kjv>pOLGu)b3_qdw0c(VpOMXitFA9so;wIQ_{l zdCcG5xanoGFiG;d@JpvyAI&Y68wW+bmYCU!zvc;Udhvss+`G-_UcPlN=igYF-?_I` zDyY7f#TB#u!Jc<2 z=|$T)mUfD&=dkCND|Vi?728KsWt$!x`}ol1YrYzEiF=#+l!{~1$aXoGvGX+iEZK98 z?X7t(SIRU#u?zD=oyIn~?5*z5X!p$Qjb(LYCyjb(r&21jl+Dj>O{Yo=1=#v_?;54S8>a9Da{sp&o%X$d;tu$RXMeL!h zk;-K3qcnZ73#7k!I=&QR7uz-Vj7=jR8oFid06whjAcd(v#HDl=d@!6)h z;qcq~qN)b|Rrh<%xu{a3Vpc@h99z9(ws7 zQd#AfB+JxJtGrCjdx6}&NJh0Tr;Rjfj^-NNX5V@m;i|vPQ<)F=)GY!dUIfZYQDFm| zWeXe{_FqSj7AXuZs{wjg{Av9@w|m^%f55P^ zr}C=tr_yPsT((p84U1|9WnZH{`CuQSNknSFv0a1P8G43Av7=D3-8E{P9!9$>9@Hy5 zrLaciA*KQz&8KVQF$^>Ura_anMLimqMEEHxGtrLNk4jS6A3Xt0>2X&bfr zql+~ACRq{*(v_OBsivit{=F{)r~;}(A$hh^{Fvc-4oE#iw!1G*EYN2ZO67*smz4T$ zp#J8fFuCZ-Ax*_AxfP#;#IyR_^2^NklNq#hy3Z!MD&FYn-=TCh^wZOSEa|&)$_G~L zrDYXPR_wU~MVg~d2I+uv)atfUJh10!Z=jPIo!U6Oy49)9;M*cM+RIkrTU27*Kpqia zp_jw*G_;_uut@QrMjFz`xw~i8*n+%-X1LPJEmsP()I$4e-5jsOLm^top>8p=^~^JO z(;|&pM6s!HxL-_3szJrf3{^r?ZYMEMvvhW4hn65+F1B2lq+t#%*N{W4RI*FX)_5wPP4C5Y{7lu~btmVvNx$q4farT%2Wd#=PW{~8N;v>Mi9+94 zR8-2;rCpOf?AV7^%G9R!9?MoPrY@2C$}U9$$VX_hDCMuDwRx|0yR3#_smhsIH6YF9 z)P#~gFPG!NN-?EoCpLj@KYNtij5^1{@&eB;X~dpB?DoRxl z<}=(uhUz-IPD<+tM}5qyHnMeeW^$EAcFONzJI#rm)Up%}K|<$X_XmeEwdh5kj7U7e}l?Jse>utZ*45FoF0 z59d=aQ79c)&bfEO0X^X1j`gq5{P(fG`t^GaS--l`jR{54pX&jEhNRY3rlzK-T~W+c zvkIrYOiNS?6gwE1=SuD>8YjmC4cJd?t4)+hSM6u8{tk#9q*ZW(QPV$%LN%@Z%n+{n zi(SR|YHsBIh4@YTnE1(nJvj8J$9e0EY?t0GlLmk^@+MtS5Xkr%sT!7yu8q<%n5^p2 z+-D!_1^xD0sgc^GAQOIR9Lioz_&S~6COQ{V`fi>(W4%&MIe91}6Hu8(AzzuF0@-SM z@1^;^ny0yiRScuw>Mu<1oxfte>+3MOeSqh>%p65qChO5fd%-;}?d){%KS8%z(>?u}T#t&W z>hBDJAIG4j=U>kAPt`ThmJD}!L}}5TaVS=5;-@ys%f0h=tVd~IG!1jRN)f`c>Qe8+ z1z-1rb2nR-dc-qiZw?*jw1ppiUb5Es#$`Pu9&|p>@`uLVFL3^PI|w?1#o@Ji3IwyM zOp2Z<&`Q3OUtUrhpS_jR=GAQP=ZT)T(fthht#19~>o>o_81Ep(=3GS|-^gXf^pz+8m!Y(8zXknrKi7w z(w?cR2x$lHAG4pINxiSqRZ{Gril{#wzC-ws$GaAru*b@Uw+O;?!u+LuAJ;#wII`tB z)+^%3!0XLJX4L0MDsI!MPRsNeR~k<8y}QE5YP3Et{4Wapf9bB~y%^HkZaMWRk+#>+ z<{|rH_o*fA;#rmBQdo?$KGa-G{k=qB^jl$mQ~WQs+dx5s=!f|M;>Jc_56NB6`og$s zM9)ioZXxkSjhx9X?v?sse`Pn-UkuqTL;K;ygTeNL^+966{adTQI#5tU9)55_D=>5{ z745(jMTYrB{INW4Z;M}|p1{1(_ss96L(CuMn~uO3=LO379u=Z~;Ngz-zXAGDm&Jbl za(5lU9j+~9-G|ddwxZ9A)ZBnBwY$w7d~Cge^>ni+^isO3{;10rKll>HEFJ%;g!{{M zwJ+(tzoUH#+szv!m+6rTEz0nM3eWrk>nRxN(0qx;vVC`6z+S7y{ZjAfG|A7gj@`)m zOOg)MAD%0%<^Qw+F-0ptwB0~8W_pNVQ!}F{Othbr9tdvq$j5TdKa1raar_I7Kle)g z=)d*&gY&R(FFu?3W$su1J32qX3N{^VNKH;(!>$WoM}?)2(OvE7-~nx6eqNnRks$D> zlRB)P{&`8sCp=F`KR;=ASG&se$X9KMFVXW}wTq=ddzJhTfu){ z_h|LJmF%Q^6mj0wA^ijYD!!QganODl^gsvqn$V-^aG?}W(Y}fO`HBl1rrmX2J}@r8 z-M)?a7>YiMs`n`6)nf9!&ttt~|HqxgsOocR^B=7s*WHUy59QK49h)5m!@z0%&hD_c7(WOFhyGD<6f!v2~zJ_zru1tE?d#1M;G0P7B;<$)3zeoT&EtKlvh<*c70Eg*6Y1p>fI&v zf*S5L4CJA%O^*xs)hk;O)9E}U!Fs@2*rNo7pX>HNU-IFfqNJ|h2|r=|TT7lJ`JQrk z4-r*S#0`DC8If|bj=Ge(nK~r3?@H|#7EzIxrPc6|Je1&dck1WL_WB@FO;t%Q>e|)2b=}`e6CX}fDY*Deu{Or_{x>)^}a!uZ9@GY>o#Hb z!MJhtV~Y8#L!03-o;*FxdOA-8u?0pP9I|VN&M)>!y_jDNygmp+g!pS*#tT?KMgMb_ zl*1kU(9eE${P-#VbNu)@bUl);^XYO?L+Eex@#M!dgS7{%&g~)0uWiX+?>JCzC!OSc*8TMM!0={DOEb`l)S)x)jZoL zE&ljb>QL45Sv~!Sl&;o`I`3fnKz`gKl1}l4j@jS%Ya3TCu-xd+u&x_eFZ8W5HU%H^ z=)Vyd@(0SvI^z&y7#WQope5)740K*g$)R^^F57yU`@E4x3&>JNJ$sSm!h0l13aC?J zTXplTSM}acDY(7ps2JuiznGn`*rlvm;R?K`qe$rG4-+4c2$o;A!a!2Uh z=51TIZQr`hRTS;RCk0)e4ch%KGN4)?(9<&%kd>{kQyT+mUBi9H+#RRU2IwQ%!gAT& zL`Zwj=&k57jmCz#CA@1=GW51-5kT!x^xExDM2E}=!QEO;AKE^w}(g*2J^zzT7`qbPl z%p}vWgV#OcApqs?W{PNy|gx3p`?R!cn|G952QUim90FZ zQ1Ydvidi~IW{O^nro)hERH*jWFHYsQO-<9dLD5!4uFLPrWN52ynV`eYl`8@rqVZ(T zv3$Ke7U*b8JU?+caD(kuX1iRK?JdvF=5LB$bfJ0%6QKN*0A&|%=S9O@o$3yV^q~lc zcy$IA&1z;z6ZD0zvd`boDzm@8glwn&R9~gWb;FAXsd9ds8m8^ox&s4pTDrqP?GC9Q z^Q*JSk1kY<$e*wM_iitvW7O@i!07cA))V-=llW8ZT2H@=(k|$c{*g7(mA-X4AEPw2 z_t7VR@AyYJ>aSOM)&70u%WKU?dX*pUczJCc4i&mT^S@y-bvkcd~FmW|f)=at{Qp3ZX^zC$ssKP3Z@| zBsnOR2M5Z(bkO2fu>8wTu>8x{QQj#IT*y~|PLsOD2M+v`%BxZQy8o!W_lRRXL^ivp zTCLZ6ElZu6rA}GLu}*{Xpw1Nk+!d$dl%_$8TYT!4cdFC6%dfNfc=fL{d{{W;ZL^AH z>-a?pylB|{<+lvG|o`*{}%@+prJkh^`E0<7=qrJ`0Ldl z>OWEasjD z2Lo5B&tLL^Fe+hhI_{lV zJ2P{D-c-%(UM?Nc()ZI?Rh{PCBkK?yJeH-W`dmyjyiR)$W*_R+;NPbYRub4}jEm0~ zwR>6h^~*&^+~!uL)YKa^<}!gLD#?0^#i*8o371;yN;hl z*Td*~G+j@i>ms_g)Ah@A?WXH$x(?CxJi5|!9j2>H*9+)+8C|cU>-BWKjjngo^**{j zMAt{?x{IzWUvSs)19Ux?u6epjbiIhKSJL$+y52?C2k829y8e=`zoYAGbbXhuAJKKn zuikb19J(Gw*AwZQrt4{RJ(I3y(KSa`o~~QzdIeptqw99M-bvRV(Dfm@K1$bL(DgaG zzC>4>uJ6$G|LFQ}x=wxJUB{pOn*P_Fuf6NI|GFilj2}n+HleL>UP@QJ2hIB^?OLMq zVY)^)ZKtI!-}=(&uL#cDv916|-ze(~f28q=^#wisE@E7*FX`!6U+9&t`glEk(Dj90 z<)1)w{rX#LeW_P@wZ3pY9ZsZzWNBt*cd>k9DeFs6hkYKP;qKDoXKxGoFZ_a3=l=Qi-*bIT@N_!xBRw5{)GJ;2k)94el4|_^u;zMYFFJ$x zQ?K&MpYWaw?#WlO{=lDp_vvrd^PF+m_x-|OS{PfeeRVppubvM3_DWaw)zjB&-(GYE zv2U;P%DyN3xQ~`COS5z^1Rd%>tA4A)@#$ei?A7ciH;Ek{Oaq|v=(mic&RFj}hu6uT zddjBt5jYe3FbvM53R!Y3yN@uQ_ZpTD&)JnN)U)u>`FOA&u1WpybM(W$_BYYzJKJ8{ zJI?CqXjghV+EuS~)vok(v@4(dYsSl73T0+e@53!?z`)F zjjnV5>#pNDx<=_H$(_tsK68gu-&zkn? zMQ0Fu^(wFICGqHir+}fs?pU{a;5z4bXN=Al+~XebSlDX*Ci}yj$oE!SXi)O|^gqV_ zx*N-8e=F#xh+{B=kH0njRhQ2pgDRW&%e&+0oI{&PS8X3%rJn^UuhUJ^0;|&7ZuPdz zJRQhap=FQC9DO>N5(0_pyOZwW?sVw*Lhqa#=E{K#*`2K?)3BY6&s~-3r>|$yJ5b9` zNl&F$?z0)%G^nSOX4QH5tCEX{vw9j6PAuoM^noY(z>uCVq{0zOsiXAa!-_+%?$TKe z&k~MiX6Qj>f)DczrnzUl?aD0_+%Jpm&(MAqncvW7fO@8rbETHbhghb#`$;U?RGc%bh0S$F}zDyUACH_nT_*e&6EzeY5X3k;&4> zkjOalRo81%<-@d;=c#&Th7`X#k+trv0Fmsd%~U8bckHU7ndy zAA?dMf&FlG{u1e1ecpC0oN_8x5mT=wpiX9|Q)x>H_YElWzOE~Df8XLu_eZCL&JjAE zUYTE=``-<133Wz*FIee#foR8~8DYC#d&8B76f)O{Am~r?s0T15$oUb~39IxG7xgu- z04g2HS?QHdd+Q6dN7s$s63)wkf+}34OF3W2Qj${%`T!(Pm~czNCcvy|i##_4X}oXLHXGCnbU9vT2Dl zeT$#_d93<^ zpD!g%U7$Jw*q8MG6Zb6uRaII4`#yjRqT(aPM|vzXeBlKy4-xgMV34LLSZ0(L0fj`k z37DqU)vTI`J`ETQqP@v)L1g2zfy*m+3upN)i-pUu6@PW9eLAgxr#?hNQ908m6(PV) z&$I!KsT;X{9@=Q#yw}&rJnd7Nvf@}%doJj-%-5cwWB$_|ZeSi1?R0Utw7sP0L)mhw zbZ!|w+(_SR#C>o15^Ss^zn#=25#tw9h}F-F(9P4&Tb=3xdwnmf!0rpB3(=fv@hyX{ zS+JE6eZ{jQ2mgSEp$eUlnYjonbaff_fUQ_ox2%h}cqNI?Gy7HU*b4FCsY*FsYFSwaYtd1LcMNndLB^TZlP`>(oL@ zio4424t_b`=V#NVG}3V%e}+lS9)R0`%+sFONji7>w2b6r%F#)jJ*%LLY`)Ly<)z!5 z^P1f@z7^Z$jGXK|j5KPyCd{jwV z?UYouV)-2^8vSWwb?rtS1xS7-O1#dAZ`b^Qm`7| zJTiA@tE;g|G(RbVN;0#WZ}EqnNo~$1&1|-vbxK1S6r&y4v^(c%x3y!SYoVze@xU?t^>p%7$=<(l2 z@ITzSUer7vM#uC$Oxi-p92j-^{@VXh%lSmJPqiCeuG)bvSM9(`PVGRKt9B6P|8eKP ztR-J#rdDsO`IN?;^80{4U-8o&rKWv;IiaL!K{4L`nrJ$W(aFP z|JT<~rwSbQSm*jX)%kb*{0gprU9Q?i(kHLBC4Ty9TNdbC(0tHhP%UU3XgbofG^&UE zNzlun*FgD5e-B*G_ZehgfqnojK%VHozS`CoREp!F;8ozGz*mB&g3kqA3@QiJfHs4+ zA???oJoHF{W8@4W|@4(Y~a9vK{gQxr8Dg2I(++FqD0zG~U`3}g*W*zr;ke?5E*Z1}5 zBd>T@A48_)wZ@1M_)2f7k!8NSkL+FajK%ei|6SyhARK9_Uv7+Q44Y_pNj*muf^O%% z&_VitzW$-pWhXX2+4;I_1o&{^tA1Ve=ZXiO`q}&SV)|N9##7R+0BoT^_ZL6t=PMU& zAP6i9Vf|y5-#00}k?ky@2*Lu8+5?i}Vdq=-uapTv*K-kM<80)#4o1&k1R3qsU?nF# zc!s7&-r~wBL7L1nC(|%}K=V|*F1jQipAw^a@8TuqbO265Q0)Mhj~Nut9~u>+-$zT# z3Bx-2qO+N<@~hvo6>qpRQs$@6TqCE-r`na`-mS8IsrPWy`yA@MgeVh52rm|tjR$3e z3P8L~sGtwu(zl-U9<#Yowx`qh{1bg&O6{xu^R>4{n2k$H&fpuh@r<-jmZIEqWDsl( zYd^;w-&vhczJ{G|`@Zqd=wn4K?Es0VM>QUCKP&xI``1yup2c-SEZknp^^>P~YAc#1yJ_i0R(s$JWShkyEg8v7E5?ZX>-i^bvq=TrTXuJ=-8%mnHAW}7PVBot)q8WapFQ@ZZQs_anbTD{<9@%qIPCmZ?finALg}-C9kQ`; z3T7a&1yw~A_G_V^TPs(wU2!{Qc?{!tcFy!E^Ja#ht9}c^zH|8b3!h>%FPL0DZ#bVf zd+ND4(+Z8e?3`JJdDHW9=9;*)w{Ru4WXAs7)%59Gnw2-rz>ZlpwPR_j=xo}bdog}n zlZryDcWQ?{d9!k|jj0#P#aeZ82C}_A4{(0<&MNO>dp@nd;bRPh_-Lm2siJx9RfZJI zGvU|8j`pb9nc@K+$6#_{c`eNeW4m^$7`5M84%LH{W3+{7+_Ku)RM=>hIkL3yrGaAH za%N+VRCV=CeB7BQQ6Z<#(o9{|X`rUsy}Aw+|GCF${}y}O9FDzh-9ZCDOF^}uD?!(R zZUt=yZ3X4I_O{&)Is__m?`=zp+S@h_G#gY5dJOa;Xdmc3klVAj?Qh`!2C07RRPV#w z9NO0vHNPVJ7gb*Bx={6&&*^qstE%%!l~|(%QsT z_&x}}REfvrj!2e~>`nFRcw1cZ{-(>-x=UTI=7V&(nh#R#>tyef^`FT4Q}wTS>xWWK zWkn&ZJW4B8VAX=LXq9mVHpKo94+K~JTGo>q2mTTJ>Cy9`F8>JfJPY{?cvEtEonKcgymjIbaG?Ij-jM=5bt&Lv%aZP=8dm)p(kxZProjMs^+EnlTs0VDCv& zE3Qx0Lt{4zKe>G9H#(HdA=aBK)r!}_$yRkeu(-XyZT*`2Tbt`8C`QS70c?Pa!VH{j z|E}=#{=4Of#8c_&x>VfD*C&mWPUgEmUAwEAvdYEuNrMtJn1$-&SP8W2C&qdse{4D1 zeXu+Kx3ay=;DW8ibw};c&cDE4r2kg;ukd@5-T6T-A2mNB4oZD`IXCo^_15^2Ob@n5 zZkNBYzsw(E`$8wk?~j-HgC9%14V=G$+Y!xyQBd_-|AovKVqVYr^?r-yv1#lXBNv~U zw_NPByc{1mD^h!v%02pcQ$DP7q^WnLVbxtZ?Yo7a-s>7pD^iX96NUQ~S-)x=`WhZ!&xC!J`@`ZpD-|>h zr;ERM5%z60Yt+y_VQcQHxV#!G&FB$F+EJsP4>mL294b77j{RVlnA_S(Ozm{;yn@1oQ>RRuQ8;(Xv>ZIc@qNk! z#~)h7SG&qA#KrWXIdh#G3X?XyEvv$24VYl8!h;71u-Fc@(OH6TYn4}H%CD{pRf9_s zrBYQ^i|@}Y4HtzeDPDvDd08pd8cWMcG4rz=8%|PR3IG+OEX6CZ6gpffwri|fv>Xd~ zv5|H~kZyiteldSeylf@b)7DhO39~~sF0Zb`HzXFJ31IyLv>9^IDpo(C;e^H7#b!a! z58A7!rO6N8EXHE&npG(EW#-4k@F-M_2P15MQBk)nEUmJ-I!GDR%2+C~$_gwRG!n`Z zmn0fBtCm$(R4qk&tPYOEuN`PUs-#E@8fR5$Wtn$#PtGV@t8WIohV_9Q?;}Wa~h+| zb)LIV_7`e?q=4hfAH5I8e$nW1E2`DJ@dnOMbK(^CV*F3z)so^W^UA`H_PBtHjY6}F zHfCZ0aivkfZPNTb!zitzr)#=IWG`)Y!uaI^7mAK9JIx}q>y{Qoz9#Kg`y+l0Y?_zk z{u3|JpeLa2w%Yt$l<;$YHLfe*IJ$Q;=>B{Uf9N+4IE_-&?djM(`!3d_#&tCq4;VPF zxO7EvRS8*8foqYTCNV!!whF7t(2b>dye7^37 z+D}}r97hi(8>eXD^VRQ334Fe8xA~ndRK4d7>7N>J{2Tdc?A|qhZ8^1+49>6Y8jl7( z2Km)|w4S~n4T8!*mwylW2n+dlkdr<=e+=3W)u}G;XCn_mPV^`=^n6ZwsGG)(7W>?{Pf5~kw&SsJSsi|Z)Jv0wFh$GD%rtrZUH4|^>+d$`?(`gV zc{y&$xOLMdfGb_ze{nU+Z(-Ex2>duB4zXTUUt3XMR3ErO!th1-gQr_8-dE$N`2Ui2 z(Ap;o29J+bJ5v2(Bac6g6xmOslPb$J3h0A&rDe4kRG_oM=Lf6hqW&@TB>*{58R$G> znz$IN)C2NMee`X%Mb#LOwwsk0Q_l9#?<5o!E~FV!ya~CaqH3WzS-h}4H>cs=rKcEX zxF|6(QCVc*6Uewx8W3GfzDK?#{Z{?i0FL8v)C@zlcnv-SWhyp2l`F#i`~CAC3^bHNTs?RJJiv zaESF&8=!C@i25aYd&fYJ?g{2-6t{nV^p|~>Y#|A6%W_iB?-Mz$=0iH20=;_vAm=Ac z3cB5<0Wi0L^QnGm5ek;>AC}Jz=9dD^9*w_pjVblz7&tG-V3r$pGwVw>QIDsG@3<(1 zl5%R7Wq4K99LSlA$kl^Je6uVEniHg;`(au`9|D3eQ>#~Im9DBXrc|w(gl0nnv{G(1 zw&NPZBd@D^=B?2(E@D{DukL)jOdxfL`W}8-2;3?1i z*y@U6yx~m`gy`@}D{AnX4xULmx(U?rX2zSvc;#F_>OQ(2hS2Y_cH_wU59IT;DnEVP z*m#0;|GBcf>X|qFRq8X?9#u}kT$!&ikMr~MK4)v6S88Uw7}=08!j^+NGfMAi)AyJc znh$#kBgYu#0kt-6?p?;GP4CF^Phudh*LLlfm(w#6*89^qlkPEQN@5qq@qd(h)OEyq z@L_fOR4G1#ITky3(<7RViU6NKmhJFzIdv)T*|L0^nX7uy%c+&i$+BPQ7;MqxZ3P}z zq+4TnBoAeW*q&5YthZBz>*sV;k0Gu%Ki~iK>pwBE2>;t}P3D&f@PxVuZ}(kM7WO@a z^8KsRbX@y# z2Bza^CZn>ST+V;Y>zM!O_yIhpdNDkiz4$zH(!+dLa9;Ry z$MHV&auOeTLHp7-lC|u=^2W`UJyoXBF?Z9^sbTDh4;P?QQ!}FGSMcN=VEX}iovV5E zS)x#6i<$VB$Q<9&D=>1*84V+0y7>a~d2+Jl0!;j3_*AzXKf|k@a`2y}KGi>*#c{gU zD4b}%Bm6nJy5qG5v6A)BwM=0uh@K0NXOf!jqAznMrO{I!)@WTWX zEmAc?_Pj6sJX4+~==VmNhtcKpAR{|<`NfbGfaI#c_HTG&+=7qwOv%qP)bLX7Ghob` zH?s!W#Y)DdzK#N6Qdo=uG2KOsxwFnOI0eKVWSN-?#{KL z^VLKZcHjU18ery649?>QmloU!hbJsN_Euv`stU8< zJfCXN1P={^Xi#K+MAm#ZGHU2GT)Z!DR=b$_p=@vJcWqUl2_H!LaK?WWoaR5Q|x$6Lj`Cfx2b-Fd6@*k*PXq!qBN&`-13k=y(5

    zwa9Lu{iijYh4qvzvRtVwDICwf5;Ta-oZm2WV}1ts)XuFwMMqim{B`a5yMCt5D*u(7 z|Kz`~OIpzGKaqZol2MEIk1*3%Tec9lpoQr7>dF%7=SNxtWfT-nDa=`T-jsqF#>9!n z+@!j;S6J0hj21o0StE+&na`l~{C5FGX<1wzewnGFjZo-46;lcY z7{iuXC(6eIa~BkOW+BbplCnA2xdU6ck+yaj>7X-oy{0UUA2{{rs_pOzMb*CUKt1nK z+o#Y|vUaYXFI9Rhr&C*{pw90mqe9J3&@&bVJ+97I`jq}2GP~%wWfto>|fLcLqpk80LwVeS<1f_${ z0nG&!fhs^Xpb%&y=swWXpkIUj2>KZG573vO??91XK_4gqn0qq670eTzsN6>qq4?rJ-{tEg#=%1i3Kwp8r0euH*1G$Fm zZHoeR1N8*;0VRTRL1myLprfGZp?li~f<}X~K<9xj1YHVR4cZ905A+mhH>er(3Fu3Z z%Ybf>0ZIZ*1r>lwL3N<(KzD<-gI)x^4*CFe81y};+c2yT2AvH`1x*9Z0WAbA1FZ%P z8;P<7T>{#lu(xgJD69b8-X!D&RfFhw1?Wc5R?rV1_vF28@gO=L3Z4Qw7xdfU-nMT+$(MCLuD$`fKzH7V zasUx0x+d&c$&_5>f0FYw+T;yC?^KSj`;q#TU8jOYd4J4#Hyp>tjmJqlRolYz-x{X( zL}m0G@`gBna@cv{`ofQ&KZ!iy`RVw@A8}5&j+3!#*N?zBUfqP_|Cr;GvH3)Lcb|k$ z;dOl?eLp2#wUOiL_#Nzxy$*fZ38?f0=~m~Tb?u4u>gNT4Qv+H7x|A_jfv@3X%71m( z@q8Sw3yV{F4hWBc=DOgMSeLJcuI4W@*g%+mW|6-ul(kP^i8l_*ajII!GY5k?n%@ck ziIk_H@FQtSbr4GsX=vm5A9j4qyYV)gW)Qe-Y%9f}@`Vql=FB8-C=6Pz-AoMD~Rl8F>U$aB4 zA5iJRe@i=BIbZATGOpL7T1TzR)%(Y0{f@&NT1^oxNGZW8&1J>39T|OkJTW=Nyf7=v z@E)Bxy(8wg%KGE!Hgin}Ju~QXnt!vB)4Y}x*n2`15E=_(9`dOjOH1}j7*r6HDZ)sPhUrA7U!*p>@1LK2l{z5KT7E*)xK7E z+xv%|U&{713g=Qt2GKLCE+?O?nPkQ@QrNs4gh@|fEEQ8 z8#1%}?Fc`p1uXDpKt|8hx*ZE3OR$hrJ<+psu&!zq%~7u&d!-lAF6R$H$C3oOxstgG zle6Y5GG;>Qmp#mnhOL*!U9PlD$4|ofG?$>ueUP7X3VJi~YXJ69UW~aG^Q9@wY)v%G zcYHhEf3C(n?TRuZ$)Hzi;zwh8_5T*%f7V8Ffi%bt%bp zX}&th>PWUYC3$h0Z`eXCnd_=|H}ukVq~i_2gdUAQborT(lP|h_IONp+b@}y>ldr4Q zkAL{hv$lBUm8>)*VJL*eR;*Q z%rgzV`fXtGrTGI+tueu%)mg@9TFzg*nBD?G8>%wMye@X^cgcDAGmOPm3C7q-2C5ss z(czc><#lDNjn#&6Wv1a>+2y>~QITVzFR`+6#j?bcy1FsmYrnk3U0=)gLDwmTMIf3N z*X0$E(e(jsMxX$>X3|R)Wu?=X)lMlb#w!BL17>^1 zx~r06yuxh`7rWpVp#G_z+ZE(=yh=j`&{&Ovnpf*4qvk!04plq<>>JE&fxZSgj<&VM zf+!u;Zw8f5aa4yHbgt6Xc?w@~m2P*QN{3r!P;tfe^AwJf+vQXG&iuEm&v@p8na^Tw zFrUF(dQ9328Y>|#ucD#0FEQC1YGW7QuvK-~zmCsWqe^fpP zsB!d9eI5$3K64~Bvv?H-Oy;58`qMz<=n(Y{P0am#zIy04e|uJ*VpDngjj&6h;rtJe z$#PTUf+miuavX+^iu%B=dKWLQC@P`dtW3=(JuATl8UMY+rF#H{L2xD=ysEBJE_*OX zIkad3YfNdMfKqdl76VHQF|fo!34Hs&K>iTxp?f8TVp@WYZzIT;kLWXsG!(5Yqh-Nz zoqGF9CA>Xq4gxJ)TP8Psgubs>zj`h#MR^#IcRh&~Rdw8d6Mm5XsrQnq;UA5$+kTKi z@!h*23=8^#nOAeaZ@VPv`?jHdzi<0A;(NNcg~BNkag3KkLt{ng(+Ck#?eQd@>u5}l zMf+IogV!f%T)YHd7dL3T3mWIp?szmx;td<{P9hCiQQZrd7nfG7#79DEGchK@>w=XP zbUM9O#kv9)C66&u(k>2Q(W$IPj4j(_d1SG#s{GpLZ?Fm_{DLg!{4{2va32~WwL>Ez z$;iqwMmBNznu+++!1<$C@Ce808llhy56>-(N5fO`73Wv?Wp7e)iZ3-SJ!5?FqLR|G z#Z$50Pxa+k5^7$R>it%%$b_`4G}9O%O3dp~{XVGMmwAzChS25n`8;K(9&cZ8ZLXrX z?~l~_?=F5y1z30?+h!Bv(K9lI4InC4%nj=Ms%Dy1iZzk+RyW==#fzb+Vwn*VoP=&hVt7oR*w8ao9v$v?b+bH60ra1k6v%8Otk{l-J^o zANmGUX^erF?G~fu#Ynl?2N3jH##O%`-^OwEJMMOltKWM&t0jG`nElZ89n$n4)%5B5 zm0@~)=Q?HisCK6AFRFj>Fn(j4?B7Kn$s6M(H&I2!<&(mk(`l|;mb(PNXtmi$jBH!9wv?l{CKDykJH9OBnvJ- zN|samGZvTU0j)ntMMI$HU0t3C`5BORDNwl|FkX8qDW^N0$1Us8VEs>mQ`^$zw?Rht zIN8f$Z3}iQlb4X%l2fM8qB|3Ux@25)OKQsvoF?Woj_Ow~+z+a|;wEa$G&H>iu{7ZHQj!QRXi<>VgzsCcn;u<#l)*mHIZbJ~f`x@2mgU zacR|0`Fq@@s7`Gus!Lys+O<7*{vG2$q^u8`lc6vjHw9{QR&p8_>+dXB5-=M5ZJ?SC`J z)%}$=CsG$6Z&p%lPOiz##Ifzk1cSzmwE0C1ZBJz+$o-5)(uEliEv!$?NBooHBcwT^ zmq*&C`tboAhr4Fb?dh^NuY~D>6J$N=derq;)^FIt#hrY<>i?rrAT;0Hk>7JpE;f_n)OPx=c^gX`q!x~y|2IFmiyh^d-Uo(GRc>jGd=IzS+n8T^Dhh<9Oa4W*0+D!_{{B(9{6)~ zdi`zNqhcmZT3m7K?Y*iO?*9CX1&fXxYbz+c=ibC|XD7_NuVL$h+aB5e_+mjp`6 z7B8(?dF9nNZhP$M#-`?{p029?%^jDVu{y%#9_w1{a*Rt1tvlV7)N`)ZPv84>CydSJn<89#=A;9(cXR$!(4+R9R3XVjEHgWn5gI|zj3xZ zHag9f88I-*9UGOOm!8r+B`VPqvv$PX8KXU;`VAa0xNraHSpdlHJ|HS4GS_oe`D>^Ff_P{yOwOOIBV`@CX)23h1H@0u=1)N) z8W|aScXY(0VUFNf*Fd*(t$%2*%m~NY=27eZ7W!u7Om~dic}=hEnG-|5%ZhZk=S2+i zIoI|W<1URoKPL24#_8S1xTB+-Jt9N*TywzP%hla=xqD$`tlQBu)|~<855g;t?%gN4pQFD! z-Z8*6FlvxvuybfX!!_D9wp*gZ>q>GaJ05X9>U_-oxaV8vcM;z^e{i)$Ke=+%O*jA2 zd%^shHr5aROOKv2W`1`paopshix+;n{^nb5yZzB;UV8cWufF#BM+ZM^6K=CXr)N%> zn0M~Q>u*8gj+b73_4T*jKKPkvZ|)PQyaR?}CepE?HPw zcJpnI;*{UN_VK~bTD$kk$tx`jt$%jcZ+5@?UhBWEx%Q@Q5C3NO@Atm_{s+06fBj#t zzV&wAtl1Y_c*(*WZn^cD=U>?U+gJC#*Q;Oui;BMf=7+Y>vdcdDxW~|{>cOWkyz;82 zp1%6!UH$qG89M!(S+lAAUv>4be!u_S4_p8B@8vbO*4EuMB5~X!PrtBx@7wQve2@R` z&E8vwzO(CtP8`i6FTLT^OG#7}U=L}qxVdtxJNyA5$Ia9bOuy)v?$C{q zk8g|Z?@rq4Ui424b#0+moI|sOptI1agEy$w?zcR#eEt? z@BYTnSR*j>i!lwOM|q7g)epCfac&Qc9r9fuQT$+}-QN~S``+ad`ta_bq(9!H zc>K8dt>e9ei*vskvUR54SDfE^>DD>3tB1|KZ`anj;_c#svOjDs5bqBw6fK|3d+O8T z3l1L~c470Otrr^N^9x%YS1-WF6r#jfj0m0h=g95mJuS{rhIZm~I^1VEh77u>TV`~$ zBi`+Z#w{&kv@6RqD&AqF;{>+{?I9}0dAcK$PIr5dCB`|>;dGA2z0d7L`*RF&x*Xjo z9)S#wzRrHQGa@&1dmK@&80Qej1e_a-GZUa5T3r!nnNiMerdBcupiYVpc8-UA3gvW1 zuEXtsa)-w;$Ki~M^(=BYqq{}rIR`9qTmUq{EegM4af#^f;ZHU5@UKC<1gjU-b*eE5n5AW=Fsfk=S$8?T9g)`A+no zuzi3t!g05AVDIjZ5uO3v5?x;S=5(Izn1+&fI%DD2I7bS!I-L>ldz91T_?(K(Asiwu zE)GBOI6igU8G%S(|@6Wu6*sAW+i5NZ|e4-9C8P~0UbkyFk^$iH23*$PfBzXGvPbDSiL+&@AT`3=@e zpMZuUePmdkl(6FyoqMwB6D@S+L-v7ZUz3;YM8c+BNd{#UkSC9FlpyQ%6}*<{b<-R%4BkFYI9?bh9tW*`eVkbR#yD}$ ze~lAqZ;cZNK^OmFoY?x#I5FdoFos zadW;`+`GyvT0m1)dqotM17(H0B4&eEoPNJoi~x-SC4w#j6@$t^6`%sO%mT%C5bnxlSFYaN&M-uB(bR$GSJ4l zB=OzKBr$nalGqKZy)sGs0`vsv!mB``ByrPSNn-6iNg{PilGv~{Nkl&g-G50EuYCkv zpez2KBy#?hBrfB8sP^h>xmL#90rfh_an2V$bI(;&sqlpm#v)zD*Gk$5O<7 zpshcoh+UvhLFcxmh&4TY;_03~F}IIT4Cv<*7chK`^3TNIA@+ujIQvB&uV<)?>G3w{2P7Zx1jrP_KCah@`<-VcRcA6gP-+@ z2cN@v&-=vpFZo2-%Rcc(&|ABFqUbk1aVKa$=u=Sh?|h=~9-o-L*C(z9y$pH{^vFJ+ zSoWGvJn)836pl+3P2*F=nG;gQ+Y?j8_9?02%e+)^^Ndt+2WVw(ns67UiE*Go^U}oA z=ckE#7o~~3O3=YHvA1Ws_*Y!IXahy|N*8@WV@IZoG*CXM1XK=M2C4&H4Z0q*1@z#? zbaCDt$m7cp>p{1G9s(^&%@85bHJ}?n4WI`>&x1ZL%@B81W{4Rz8RF`d8R7xZvuiTM z(rYqA^Lp@WGeqWf8KMUC`Sls%qDL~s%^TRAL9kd)Y=%Xz0&rh<%BcEo8y`VLpWr@Fm?)mR5 z@$ue?V*IE{B6j8^@zpnz#Q8@jiE5D1XR^4s?__a1=&fCo#fPAcjZ;PXGgHMj(CeUc zo}DV1K-WAsRXn%@@|{z~)R(4;H+M}H!97#OCHtldfA%zy2bu-C0OUPqnivn71Ud&) zKXaP+1?YazBcOXPohBwMohA-|j)JaQHcd3&i2U`_#Nl5|6Yt$KO$@kynppS1G*S4= zY2ul4vc=1V+2W#k+2R{e|MRoOZ!gFep{Y4y1L$VZCeVt49I+Y{0<8zVcvp_t4SEH% z7c}bb9N`7|KpCJ0(00(1pq-#0n{&i)Py)yYx(Cz%+6LMVI%5mcKx05&&@Vs_fF1-r z0%`?)3;F@%ye~&g0A+)6K?R_=tvO->qN()4isP-+|8PJzZRuH(gu~S`AtY+Hu}= zac5wf1WVn^Tdq#GsGOwJkUj;O+_=rZ>wjBy`VQh ze*kT(ogofJ&k|?H%o0mL&wyOrW{C-)X}xEO@A}OWTl&uu?>|0EdI$Xy|uy#3SF&5l?`=2K}RL4%SZ370nlq7Q=2IAuuKrZcIFfaBc%8KCiv7 zK-`Y|;oO4kf^W9IQTdxS*G_wM+}KZ^>pq=+{CAHF|FyWtec4TuV{*KrXxQXY%X zl8;?fS5a9yc3JHbtYApTw<~NHHz21_= zOCVTUV7?=gIBjm>@cGlGP##ZbSs}^dI?LvfEWWdB0m+O`vOH5?LT8zo&)Z2h)69qQ zRhTU^r;xSYxfZ3*Ko zntze;;imsIuA@3)*>W5TjB`Z-7CW$PMRjHEvQo%ttokPEn&nqqaRuHuhdl0#66xRa z+LGaUQ%rl}JINN9_88%^LYXh2lT7BrI92Mat*jw?G7xV8Pegn;IL5E->BASWZpe%$ zB1Ga!>8t$^yclD z2pnudd_D_M{eqr9n$SN{Ft9L<;;j@1(Xjze&t?n2DgULEhEUDvRyK;^r)FaU@~c2L z`VrS{4A2jx2wrfqi+(W8XM2O-WaDGtWaCTV6n1mEm5rN^V1ztJ3%4H8Y++Xr z3%bc3KX^Uc)&x#=d<{;ajpYM+MO@p<747IHI_lFn3uV>YCAv+e+QfNb$I6aelz=U}# z>+MdH=Lo~V$rj+00q1uLXM+t+qlU8+@qnpG+E2QI==Yjf@0W~&Swo4_J+iF3%kw+8 zS6;E?ljm&s)GI=CpBn9zS1fdCaaF!v&-b@t-HOh0fdi~|-JBB8TC9>jHw z2I$LYoogB6Ivb2EoUi*)s$o=GV8jhXow3e;F~-+67!4K}`!tMZ3ycsjydWx@VsHwJ zIX*zE5BJEfevE-k1*&@=;(A%NLSF;xJir)#vB4;}z^KuxKF;M1D-+1q{NpVjF$n>RWv4xF&3a(n^D^)ftQfhopx z_RoX3?q3`hK{c|@zcI!?Z7{NMzV274hEZvOAq-qMz#%{00jKaD$8|p%EHL(I7|j+K z^#-ng5Mf*jPNCY6alL-rW4rn>1~L_>P5Thn>nCm)%8GUV1)Rd)3~P*X3ygXVW3vTD zBQOFW^5YtC3L7}C`|+j)#t{wUm<2}Q40=YA7$dJHJm90&BQ?@ zD*>nUrJPpFa@|j3T!)|GZQO}-bCITkIsQXj_qTqy%n<-@WsK8sOxUA2%?nO8>DZgX zu+{irR~V)XI`&v##+^lDWU2GdjPa=rhVa_^mw+@C+&IWUT=%aDSQP5P{UGw=5^(ab zn$v1oj`3b9>UWW<-+IEfso!up`A)v>)a+?S+)LmHs;-;WBE++$yaDl6#vhGis<(^4 zDgP31t8(v~WM3v(NK=8zWG3QW%7n4&!Mz~Dm<3Ll3puTn<$9gh9|wD@^ z0mOAbXkln0>->l@{%V7<$pT}ShOx&2qaGLri2PUqPGL32bw7?;U>Ls6ek35?#Sbi; zZDgGvF~(nQFp6+~c;88FalMAI(E=j~3JNYqzjuB|Sjp73=o=vwAj`l37$J_6J8vcif z2TX*HKCzx&?n1~1Z(!W+IHr2&4Ni7AqOpKyYJ}GvbOoF(m?PK5u0~o{-*X{Tfqc(L zT<;s2(LvXP2m?PQo1u~8I>venj3+dV9Tph$QektF#K6zSW;o1o9pjJ%MqGMlKjIPB z{RjZV0FfV=;1nivT*sJ+^Y!*#t6{9Mz-WTLde-?kV>BuZ?cUi$7&iA#)iw@=VbZZ&F;f zmA;uB{u1_Z#C3lgfk`0*Zh#2e4^G%va$tswSgvCSpf4Pg&e;%#No}Rx0@FxG8MDr> z7~_}?#+zXn;aD{0I}(OP{<$Y~^{)w76zakALFC`1;AHFNoVJGLx_`OQr!W;)WgA4A z3WOc9!1nV^BM9Eg7%?~|?EaiK7@TaW7>z^UHy!O1TJyn$_e2|NO_z2KC#ADr@j0#4_C4o<#(2W|$OYvo%5?9qKt z<+?A-cEUJdVS6Ln9s>7+2x9>_VK3pdN|x)-C*Fy`w&`QT-}xR z1eqhiycxWO@f|p(vgr>__6-NODw8M3E^Xd;e;78|@*(1SJ^Hhd03w}z=on!z#|QL| zytcP1#xYoQ%#nL10jCds)0)e_Y1tgN`;Yu8P}>S3et-q!58>udl7bNPIPf6bu!C(n zZK5oP8Q>J21*h|4k(YD~=o58qA6GZW=|auu3qf=GhsoZ)nA2YrHm84rxU#+PG zT%XMS;7xvMQ_m@8l9&zd#Nl-u{|MZHcn0zwuiQ)hKi>9@I9CN~GusevVF6(iZYWy{ z8ky&VH?vJcr^&R1;AHz<9RD1g&d){OIWnypoNRxX<3E7Y`SX$Yc(xz@5w`1XjM~2&Sbe8<_!5P<5Ahao3d$FAGeE?> zd8Sx2=Sp4=-paP7p2IS5@@Y4?3;bP{k3nA2cOAIt8~^q?NYJd1Ft6h+z&3wxT@?1) zD<6}+q<2r4y=4D>#GAn>D0>^umGNfq0Bk0_2if*?$S7Yucz78P()yJAX{X*k?8VEVw<}|jed01s zKpqvSj583|?X90Bb2NeH!$!ipgKR}O8#1yZ1b)0S-a)pUpr1Zbx@yNChS^MIe9Xe; zMzk{uEzCpA>9tR$Pe`M>^?B{pjE@Yp!K>9KpoWfJ!Rh@X*)9TRRCt*;FBHNLKgfpl?9Xf9Wb-kO zS0WFc|0;NRJ?L$$5qNr=In}u8`wxWqLiKPIalMThi;#ej&%Cu*#zTk)0@Bupz$qLH zNS{U{57k3D=e-l$f%q5T$MbE?j8peb)yp=Vs{+-_F2r?T0;MuXJ##O3Bm5wn+Sotp zLY&C9g4O*OIN5$S@|w0=w4sEVr`Cq@kzWO}wH$H14K*&7Ia-+q!JF8I-eodvJ~-KW zJI7;@hiqL8ZraMveR>-@LiYZL#t(zf>+przP!{5Pxwn){d*do3Z{)ZiabtUJuq**6#W8EFf&c^;b(lka-+Guma8Qc4etn4LGKZIW^JOw#4^G!W z0K9>H_>BGc2BoiM;BMqu4NiG)1E=scIQgEBbHjbtub0*z;k&wC;^%buM)l@Jyak+s zs<*gW8TT`9sewQ6lWcmL{rv)*u9p!=qi_{Coqqs4+;+X*b^-51^>Cte@`cLpV3;pa zh`Z-@ttamaBp?Ks3+DCULHI|u{)+vKt&=`Y0H=C62b{t~;AYu?o4#3$$18z-qVf19 z092if`%`*jSQ+RbR>p)yYAytjjszQf?h^X=Gw(6`}*oqfwjT=y-w zM*7mg+|Rrjyb=D9t^a1fXRemMtp+FGt_P>^894bi8Rs0&w*$aGQQJRJy1F*Ryw1KE zi0i(!TxFUk{8vjJ$Gnl`S4vxFgHyN{oP7E#IQjAg%V!}k)#r9_(>K00hKi24t_{FG z(Y4VSW-nbEO^COGQ&8=!DP%@PD|isL65gw9^M#O6zURP?SH@ZA|L4lM6uMNPYhyj) zUCMZ!%n^5uu*>-59c@#e;VBM?KID|r@6X228u{; zM9>{@wa9lEJQu*XevzW*+-}~OV06IKf_HRI5LfpFFV0ng?t!_8?_&XB6K>#IDQIBs z1rNdxN_zpE!Vlo&!#nGx&0~;<($#%jznASIn@@3Et86|PW;5N(jv?LxPC?mRf4z)1 zF%N*ZuubExlWEo9Wb?xu{{fuNpO3u9vwh|KA8&gD&Q&222RjjOVS%!};RY#aW*!7@ zWt%2%kZD(glkLxQya)2o`Q_l@w(Ixd!V6E`_7l|;)k_4h*Fd)l9vo~#T)!>?8)c4q z=3eHlH_5i&MDZJ?4>{lz8ob>CH+n~!r< zpn3};-ok?Rdb>pmnwbZ|Tj3AcH2G$kb~U(JZyfJ|JZ8OtAJ6u~Kf(6C7j?FM4C1=& zjrG#L7Um)1w@RC4gHyN_oNRxU<3o^#Y+nf;ZoA&*_5triZRk|fRhw%K^NreEd{Ngn z*K#`&5aRBTypiKU#9a{i!Q*a|KFkBBumzlaeFL1@+y~&4_b{i=fe!Nhad6Xji?QJb z*mA=AAM&U`I87Gzw{DU-j5{&*fUSi075j2M(#Vb$@bEg&+y0n~PrVLQ+b_hqDp1?6 zM7)IsgiW~OZYl6GZ@vr9Gq9J^9ssBCF*ucJKcrEp0;lu$fm6P)-|4+HilE=U-z2-` zoS)Zx_cZL7>?3_g!tA3mbYIf-xA~^cNTBcwAp)?G@V2q77b1=9cn;jO!{#^m5cHmE zJJs`(&1Bk*jM#6nEH0?JN%QCU6SM zw)}0F%CW^(_VLSEAk zk4tzQ@xt`Oq7OSnK7{pKs_x@TJM5!!k4IcDXX6`O2mh8hzyF%75n?E0gsbjJ;lD!_ zLWdRB8Vzf`1y<-N?u)GZEF4p~8r%-6$p-6?hSh3;)$+d>FR<=waZKT3a67CqW!8Qb zLaqXpVG-hb8T!9NU-PZh{TVog$&lG$ZMMN`(y;bfU^N`Wb-=oFa7^I=a62sbVr##~ zK&}G$3LRE$W21(( z$pQ;I>xyR9{g6juwSn7VHQQhv)v&~+UHuBgID{8?q&ot~6c&QpVP!#wm0zWht3Yj| z(gLfg8?Gx*@tg<}d=gWF++Y_PU#SdA7~E!e`kk#%2-V+tRG+hHBH!RlMt*{{Kf>wfur z(WcW<_h;Y~CPQY2H6J>x+D1sj+F*gz&>Pnm>(0S3g$Kaxu=dzs9oDdpSYV01xV~8T zLwzJx8@L^ocbT5jlLg@xeZSn;A`4gMAztUVgmn~3i; zwRMcwTl?YqV%<05n8HDDJ1kF?wO?MyRUp4I5ZAFn@eX11m%0bym_jYM9agOk))ozG zn*~)uEo21ocCxEt29k3Om58j@jI{TkMX7FaDK z9U{cKufQ>d{or<3@io?d`5{+<{K`dKZyUkUxL1ynx?^xmp%mN>YrPHD6B^bI3oP$g zhiG8kZ;p{zBOtTGYPG?NukGxYfw=BhQzF_1>t29k3Om5+NWVPTVQ!p(QmNs*L@OeIAnHMu~;Z-RbM{HRUp5z5ZC=`N<-UV z-3xF`VF$P!)=C?!1`TVw1y+6r+6L?XN4mtyhRhD@pbb{+<(>WNi@5Gr%XqX6)_nzz zDeMQg!^(#at1?`vVTCNPf)mg-GNtYq98)L-x5L_HgLP2DI&6U@CZgY9-S=cktRvud zSP3hw{mO@21!^1f5!cJGeiFvLz$4wGa7Y8w+N5D^vB2_AbBGq!{r*&m<%7%) z>wpcGxT3RP9>jIOnzQlz#kw!WF@-(gc39caVb$g)v&a#Oeo`9oFF0)_!F}t^&1O&hEu8rCrjtk&6R8?5_A98)+5Zikg|rL|uH$W@@W zQI5D?hM_qQVdP8Q1942D7TgYNn+?{R8rFUbthfR^6S3~c=1MF#WOi6_S6Ta&0l5m~ zmmhK6uZBWA6S3}098=f?ZiltT25Xy!^@IhM_k4_PSoiDmB-U`q?63~mV8vbC*{^uS zb-$V}z}SX$FTgQ{9pH9Yh0tNu=GSOg>n*VIFT~h}b^l|&#L9-u4y(xq>yU=kYJt_V z0Am~0eFcsw><72Q8WXbis}OP(sBIJ>u9so32xFUzr0y6TQz!+u!`f_v)udtVv%nIU zU~I#>@3~lF9Rat)a<8@aYYgNnkY7H;b-(HtVr&CE(me{t6xM^=VFhilHfvZ77Fb3x z#x|_`rGUih3z;3(hc;O5b)Ef+MO^o*aS`rctovLXQ`iP>hm{K*R&740VXd^l3YOyj z#kzaom_j+Y9o7yTtPeG;gBDoc#b_I>`>isGl>nI?mT`@>U%8O0Ky4!*alH&%mpDX# zb>D(x3Wvb$ur}IY?a;7xSzt9*;GR-0bCGhv0B0HunyZ` z^}W8cUxN|X{i_*Z2R5zros9KjbQq zuepfpzBa5znS#i-8gL3LIj-Y`Y;d+~IE@xK{x#@BSZ^$jDf9xjD$_$YIB_?2_9q^3 z-5=vhjI~+sVaEAa2TrGbyYq3rUSDL{N)0E3xStG0pmegi5jgoEI^FbiR~442yCehb`2-~~YB>l$zhYdH>_PIVW%v9qrV#|OCzgp-B1 zp9Q3mbo+29<~aIESs?&c2P zsO}8Jb<9R!QfL9s2a!*e;3QqeX;-ma_q7uG!g0foseGyZY|?DlW@W=Q(uNRt9Efbl z1SjcCPMgDW-G+mj4XR#aZ|U%z>a{Q8y6+9^;WNne8Jxmp9M{{=e4HQdU-+@|H57(P zD{&gYn;B~yj!Bx%X?}3ZYqf`R?ya!n1bZm|-09@62lfVGiwd;< zw-NCG3zWYNH%fmEa5`$fLB@mNR4+lui8pR=2zrk!08YL)L!N(~JRW(yLy-Olz^PpS z7o6HwHuBQ@6M1|N>a5fEonq@xTxUMyQGs-4Bc9I!f>LW zjxv~sGWcb98MKgHS{eMOb~aLuhWxhH#+DEL^XxKvr@PT{`B{VKFK}3J%Zf> zu}$)=m6MgJYibSjs6chJ3Gw+XAP>k+|1YGyEt{pC_29|-ISx14 z+#>V^QBD!%I89jfFNeto?b;%{NMqkSJM5w|8H~6eoPx3|ZVTqN@0EBw8Xn@9K&%A2JoFodyt3V1X(_V=MXz*13~0nmGO?$77I( zG0V_rKdbueC&Dnp{iAlUKMb4N)j`Ddb|ro(eQJh&KVz&1C+Yp*6n@Kc_}d9P;qDH9 zb?khksbKnzxQ-q7pw!<28~h;hZwcFTA2_AH%<+#nUA>DmRH!?I5Okm1L$=U+T;bm? z)Z)~xsay_+*%pKNF~nQhSi&Sbnje<7iAT`hU?<5Q+$LoS56SpOaFTRKUP@og=d1@O zc>~K|Vfj9e+xf6z^U3?rh`cJ04^4>cJ~TZh?QI43!w<6Yj_pzw|EP?w0Vm1#96z7W zsRbu_Jvg2B9LsldTyOinU)Z;WBBZH6?XVJY{TgU~T-wzD?gbI%5^$2P=ClyY9o?fk z>bZ&DEW|r%+B4gmWKYkIIhpWd)eeq?+2sO``yPw_?I~$j(~}NifXJ>@;3U0@<2rUO z^n~MuA1mx2@~A-AAq#Bp(-OM{Hspf{`%!R`KE-jppW9E^He)zlPPWjsc`VEp8WRt{ zw`)J>ZIrf%XQUkg#L1p!aI(JvJP3P9whf%>`FU_kdk37ZJ16pxmY(1g`hrt_eB*T< zz8!pf__u=_VT0W_UQb4@d^-R=Dv+;Yi^X{LIcZNE^M+@oU9E_lzJWKg->-v{FAn6P zvns&J*D5||K+mXoJzX)kckHwx1ocm)z;*P&UMtCAd#z}3)iyRFuL^{}#lq&sUrCz- z;NBh5-v0$B=?@%7yX^FBvBPA8%{37&Cp!qY?|mJ1P}z+^+zU>DaH#H@pO@I)7bLa- z_p)puIE7omsmvO{N%9b<>uom({i=> zEijI081DPK_D}UY;TMQ7O28>pa$Lvo<9y|Z;;L@Tk){H*o0S$=ffuEIFL)DUd<9NY zH>X8|lPzd(IcRUo_4c-hY_Mowq~may4OFH_5ZB8z_!8EAFvbuZQy2|yVrt)`NqC^c zUsZ4Ukf}fz^AXqkeB)*K$2yNN#`g+C>(93khE3a5WxGei+>f}QjUW%m_P{RbOB{Fz z_#}G`oTP7YT)%GO8%~VvM;;ZZUh@&xua(fRCAJs50r-Ud4me5OoYohd#4@6yvW8QVK&qC-FIu(cF@`+ZEj@Vv|HL&|6BBlY-<}hUEhO{M!9bSr#j!ndChmp zr}Dex7WEe)kIVefWk~ z9OnFrAF}oUdvX!+w+n;_S>$VBS?G7N&US!P_%k@!)EDU_nF&r|5y!6pC;v$&*-AE$ zpD%!u{d+i0`pIqqdnmmRIQeo0$JIOVL&DzO+VLRjn%=ihmfugIy8fv$^Y=v77k;ej z`a@uneS^2jy50`nf;a{8oO}(wD$BqRE{}eEUC)Ppy{2QVOO&pvPp?}AfZ_dz;IW`a{F;rRb!?|a~-8q@gC?cTb#zovh>w{A84 zp{tVV4?=cFLP$nJk~N#+B5RO!m+a1_xCn!+B+L>n!bk{VB)b=3q*ZIfsFsT`2p28C z@Ao{<+nxK)nOkjkf4jfmKA+Fr?|Gj0J@4~-b%{^Ll4(+nU$4@JW6pcS~Q-1=d2RFmgB6TFF5OC|m!0 zUynljc3)3}&FYG7RbIHhJ9$62BgeX zeLj%&*(Up%9GI&$K*q39b+*sGCLfj$1u~wIs=L>fM&dhH=T>`nF7!>dpGLzuJ?0)9 zr^@gwnvuEBqT#$Gv+1Z~gnni~w~v{@mvG+oqVRqVNLj6VQ~pObukid_`N0b1@0@7s~cUcmW5?F9ovBg)PUqdqsiNx5atoPH^6AaW1+qmvf|} z@JIli*0TLkJK_8#kQ`6%Ae?cp4SpM3euXE%AS!M;YA=cOK;Q{9AzuY8=7QT`9? zDx4n$lH-eAh4bsc?cqG^{(qkHBp-Umz+taloV_ZGoIR=voj%pgoX&UTU&lwFz7cX81%0U+w$A;xa1C;e zaG8p2%5tu$IBamGBql`Hmr**yNWQM%5uFIJDQ2J;C2aY{I zbbC%_nm2P&+V)&*Q*H&idGL7V;v}@;bt&g#q$`(!xUHqsg!Vd#FL<>s8coQ`5hbr4KKr#%W}PJ_V6E@E2)WUVuO z(r4!YDHj8|&%E}s&pklu=V+T(06D+@2xObJK$e@eZ%?P$)^p5t%m>%LtoMgSU^NJ~n~<@nit>+!Ro zWf2}X*T>;myLo|@L7DI?QNI3NmNL~&Al4EzRvp3M?T;6JSd1Zh1*mJyf>>2(f_;xFCx}krwk3A+| zVU!zTzAB;5vpD(pY38KW*E_?c@PfU?x18II-+FFSR$4r}v~rNszOZG%DNe)OUPc~W znmb*y4ubt(G+Sw2Vgg{tT4i_y#S=OuzNBg{(`bh|Io zM>TUY>f^OB!r@&YIh5te%QE`Rlb4NIJ~=NoL9do(x6X^;xMq%TtoUegj1+bT(&v$? zPg6Y~hv3usIaH#|2>T`i-R6)v9>+uQpwDxU6An=z^@mk|LiLYSZ;gFe{v?pHO7#M+ zZL6@hb!$1h8^#gO%a60p4>pr;*J7t@WizMkXlQkh;15tB=K_3hjD5FPm$1Jc|RzOAU0Nbqt7{g7Z`LvEdiu^E069 zvv=Fsy(=$pulszGXU(0Hg#TWxonAP9?mRR1de8sL{xkBzamnATm!Q9l^ufl!=WuV6 z`y*Y$ch%S|83*Z^a%}ShY03On&J*K6>OsZu@0+>5^(3RXXBc)rumqUAMCyfpC++#s zF3)$9mx`W*o#QMD-5-|iFHV&@{ik4!M&0>9%H2TLEuJcR-_t~Y0!UebdC2;^ogw<% zvoSBBU-zqKPCH-*NEv;O>=%hhY%c;Sd!H-%zUK+&^+4VudBph=^C>`{D?bS2eEt&1 zsr2l0iM`{mCH5*HV~w=oOT>1jl+*~_ZI{S>0519%2VeYw|hClW% zKRj<{{z~ARQ(Hv)<9_X*=YZsN{AChf zC6IC@kXv(sAY%Yfwe6_EW*UyLCHWc+6V8P~pcc6~4P7NU zjRKjo;MIaYpsB|kQSu>MX5P8haeEm2Gtc~RY_pw7uyK9ihxKTSXg!W8Tmr_I}xngH$Ik_nL?5(}B#v6{;7M6ymz%?oL4%zdd{0ACmlY z?)@PRn=91mMqZN7QZj|TxMV}abd0Z5-U zYJW!c&w-4eZIY`W$T;@}lK&{x**Y>!fmx-3`7>- znx?i{f^CWqNS`BBpQyUI);rv~CNSY8_~v!;?0dc~oq1sEQPefUITVAwR0kb_euH-i z4+j`i-|cS`+x6JF_1Ad z$G)srp>6G{dcJ;$yt4iMFb{Q&uperm+x_5sO!x$W3H4pLL~PYSa@zzX*RvlLeG!oI z5|H-y)!tIuY6s+g_IlFkRdBb~lM%2PDa6Jo==OS&c^vu0hi$F_Qr4*sAC3MGyUO?& z*YLd{ZuzKz&f^1x{Ml|~DX!h%!|jnk%9*Nr9e;zbEY;aQ<4dak z29WWrSKXZJXWw@{@b%pD_no!nJC8SgJsv*Ee=d-H?O&C9-*w<=$$o(wF`nnGLhnIQuwTCU}VT-FRgfYv$tJbl5BaqzQ0J?pRdXzpu z>IVSbz6QE|4P;zZK*lgzb++&Jwd$*ZjAw)DUh}&2jof*?v$pKHoV{)OItZWS9|f|n z+pNx=*TH8c2R@+bV}qto^C9=-$Mp3w__6zXBW!kG*TZJ|Iz@iZTI9!rB(kD$atC|U#yS+ z37U%k^;+C;ca!7rw~!=qy{-QNGUqjQsB466*F&G62681&|8v4O1dPBpZS9g0%Yi`Z z?*l1CsKfm_>ONl2eF*&p{PH|wpbBM1+}uD9slo8cEXTQ`w%-cdl>LC@u}<}mRrm6r z_VDk;hb@=9*}#Y6rWAS(pB3WU{{pUcJ}=vM0x31Br+_Yh)sxtV@)nTx548<1zESw} z;>Z1JviLDy2@ihBKjAleaASU615$oa{f{W4B!DdU^6y)d>)(qHTN;kKMmTmyL$~u4 zuN7Y@U`G93^JmG!(?If=f-*`}>s|q5yz^A|;#uRtljEHGrLuT2PisAR#a@EX7sdY^ zAmu65XRr)%70}I7`;w{c3)?KueseA7-h{QtRcE}nc4XuC)^4wjd<)?xigt`JkMp31 z)xdbjA-+;LrGV6(S8z_L{HDJwYtWrQmW|cA(}3Ln8X)(+RrmGEXFX%dGf(}0ZQ#dz zRzSD=Ir?fdCjd_LKOabWQT1skqg)JRdA_x54%*$`wQNZiC$42HpxbL%C?)=)z=Zlf z>^0%?YaqGwL>Y5*AdoUf_wmZnz_)U9{XVlD-`Yev@SLbiJISj1EI8z@Z-w>bY0?BPx zlu>pAQqRX>Jlf62VFt>Kki#qw4w=8;z6ABLUVXNQjXqZcDH~MB^`{GP{b^P9^`~|8 zpLP8yd)pivi`F&p;CSi;z0z&D;X77ljrd9e{cno@qk)tZko{7nb?yUFe*);{#^c#m zGvLD>Kelf8EzIJ_HDU>LdpsrnD!$Udz*^aU07xE-Reu>s`A+p)QJ1nv_r?EJO~wCp zE%*Aru4!+BZ=V0_`l;-Um*+)u;mZiGLob0IRs-W(-WZEYg6N3w~18JWDWIeBSb}oF|^T5{4yjW)OUJ2cv7s>VFD+BbsC)-y5$>$o?9|KbU zuKFC*W%=De%A?vwzVR?Toqs%pQD%hWp%S{C+t@~ohYiB*b|B?d)z3#6WhO9R&X&@D zp5u4g@?Qtt&QbV%tn=FbxW9|P-vjAyB+4kq0A2rizKe``FEpokXj=Dy;-p+z< z=OkDs{vyDb`X2Cs^vgsbxfG&|(hJD`3g|vw<7yN6Svj(GGp;(VZ{WxEwl8!$XMsU1^rK}&oRX{wGy!y;XN%i&=YE4-!eauFC||IAZ-~SErHE)T#5jBd`tkD|I8PX z*8unXT((aHQl<1)|HLAa_x|jbj+Vsi` z{a0K5V;=tf-{Lq?FaC}OQf8{&0%erWK=SeGC+CA)|27|6XMQ+tDzL8+_FE8oSPkS) zpU(HfApoQv28NW+>p+$keJ5pi11T$j-2Z(bEnjK5SN;;)!QZUmYc0NY(Cz+=ZxJpj zU`#nbqcJ?M`dT3Qwbr`V0;%7ox);yUb-8&q<1B(QBOGT{&~09se;^b1Fo*rP4VkF= zJF0)8x|jdjCj4hC|MedJeLrHH{UH7i15z$h{Rh?Cq7M1N{{>hN);C%YK5Qa>lo@g3 zhaORb8AoBPR6%Y3S|DY)>W8|knByD=RR1~84X$m%f5!4(58cjxte_D8^DXT^r~Wpp zUWGEs<-mOYM}O2r{3tWx#t+^0pJ-O-B(?ny)L&QF=Hi%jz3zA@u%%SuKqq! z{Z}ZXTmsDJzqSeg8OwjYhyO%Lp_9<|KTv;NVWYp>fRqPRNB(op2P!|wjo&`5*t$8+ z#IUaso;TG%536D8`p`-^#DL_K1g4eG;Fg8%`n(U2Wyb=!f?TG0h3-2NNc%C`hSxaq zf4c2B%<*P4>KftkaRPL^UjuD~Qy7?0zk9ZpScU+}_b?#iyh!y@)TQ1}_s#bmbRD@` z*ZQ`lo17PY*1+BU{tw;$J{D;wJbgg&3<6`y=?x%dt?GqsCAa$kS@$gm2r z+;0rZjBsv`hi>x;wJ&r6;KIC|2Bh4q`o1Wm913K)m;WUm{`2K$T^1kaXOjn?bO-U} z>saVS)$eOS#?ws876K{DfwaG__Od*`jZFU>Ir<5H8(DyMjPM?yCD6laAP?rq-&weY zfYhVFAY$S6)j-O8AnV_)_OF4Q`+IbfdanT~9|Bpg7;Uh8S8da)9|nGb7_I9GW*m%1 znGueINzm)MGf z;wugG;Y0re)HVUge4L^78EXH7+8BtNLlG+y7Uwlz!Va{=bTJmQS`;2i?v=2;Xp0+U5}V+YauT1(JjN zZ2494WQl^-Eu7Y?8ve_I;4Dy#5cmeeYr4ufS;=_a6SYm$QHQ|2bn2tC6nQ zSOz_#2GhT>3dw6y(djRGKryVC(ejw;Nk#u2Qa=RbZvz>%$Ds4x)0CF`2NXJ?UQ+jI zAdhRWsD4)OLieox1|a+ReIUnUyFQ{%1yZh7eIt1eG9>_Y!?Wx>>)LUsA z<{q{3tp7(@4WI5kW!rczz)w|&v2*Nf$%?%r^ilO5&j1-FamE$Hdy5`ZOe$s+Q(Dha zJpc^sCHuSzO^&uN=)iWIdgR|08$4MPGEteMUqD>_*r|0J=T50|(%oa6j?& z)&9b@J8bk_)}`faJ|kf-k7p#r=(7~}QcSk)rSPz^?-=9KEI!OxE%XSJ1tHL9I4B(A zz|aWcG3!9FJpg3A*MO{h-Ot26A4vVQpG)~!Kpk%PqlwLt1Cft1avo3&t=wH7S=9-OxEjGq73%9(54 zd$09iGm_Slg!w|qy5JqVraV_NH_&<^Xz zwLJ&OwL6J=#1QslzXf3rYyS>7SoS#q$g+;3Wc@z|$hIy9a$R}?$g#3g?VEr+-W+s@ ztPjTk$>n4q_d5f~_I5v1$|nIiN6rRv)LaT=`3pdDa}JZ^&Ch_WcP5ba=BgeCvfV{M z?pF(>96egruWNxkp7lbm*xnI99{(=@vc4Ic_H&w&|2XyEJ~lZvn5#PYHbSocA5L}Z z)WBHDI};NAF(7RrMgK9P`?Wl&7=}Hj{oHY^)R_R}8b3?*+kwp9Ye43Do!UQE{YM~u zpLMkKc@>cQLqN)hK=yrm^;za`GuvOetNVPuK_1WNTm2()+_RO_69@5}=kxu~o-WDA z|5osPYYTE^gy*Z1oGH!(c09z4iR6hoCMHV%rX~o6VP_Bd6r*Z)v|b3veoUSq7(_Ye zwgaR+3VRIWhucHPNt+Xo75%jFGQVd7$s+;e7Gd`$n(uU$ICh~5J>;$0=fScs^19YoLLN{-*w70~VDc6_S%hycUjM1N_Z%Tx6cD5Ff#y7|_|b!h+J zeOxwcV^Lv4tXvyMK)2V%z!?%>s#4;MDTZNZykY2!-_d$;U`k^?_B5$856E$|LiKln z%+4;S%eXEFvaJEC{~X9R?+0=$ELHt8AY~8u|XcXa-nzFh&X zM%cHVil^i}C(b`Z;teUrE)qSZ=(||*6$COb2_W+vQH<(-8R)?aq|VS^OYV;Wa-SE0 z?86^{?!3NG?2iGdr&KSg5?_8G`|MO8ecc9RU%#Q{Uut>#-$?!LK>9fZNO=;-F|j{l z;Ql8A*|)PbrZV@rZJpfbw)MCAcVG$n*W zt7ROuzedK@2q5R;SwN20TY+4AUIcRgvY7b#4UimW1G%PL2V{9O_-6eMKyu#=NCty} zET0La+z;eA@f&K-H}~eW`RC`}66|Y)v8;q{&%Nl)!ppB10;c~Uwo7jkt}g(|z56`L z(a}K8y%T`6{{W=ys%@0@Y(2YY6VE!$v_(ukS~@*2@7m9_uI2rg*g4Lb)6#YgIp#U> z1n5;v4#cc)!MNlps_5JzV69b*>8P)4Y6_!83WxO3z7SUU-CXdNA-YW92nC)Jado4 z_8yS271l@}b^$WRckdOw4oLk(w8`B30mwdoMt#V0h`Ts^DzW+QeQ=&*;udgr?~V5O z?w!xh`02NA`-b>AHitp?u>fNFI`xQfjRC_C$oBYz#5dq!iFbb><2fI7C^K~*!~N%Z zxX0nIDURe&o5hi>r=a6i1g;p4nWea|Yl(0;{xRWj29TU2mj}4HlxOY^am@P!%$U2# zI)@B**!eNX9J5cW(UuWj%dUZ5D-^fpIP#(zfQ%`r6@t(M&q^HoKPPp@02x==a?u9@ zsc(2*^e=$aYgb5H1%DFz^gqj3yB0{x!$8VF_@d9dfb9AuK<;mTL&|=K%czdX3x7iz zY5o2WyAifJ9ePp?rjHUYVQoY_Z2Np{Q*HsezM6Q)LLGf>=lc}A>X~)T*QtRc$9e^H z`yC6xSA|#R72%Zx249x#kt?NaERdYXql~d#4rJaQ)P2mDvd_uq!r!*mF*7fhWpU*g zS_$1g5AeS(JTfW#wglefRE=%Q6F_o%4@i4c?^qbt8N58+r{HBX{3c-^BV0$PL0_u| z)8Ect#CLKvjt#41d+Zy+@3%nm3ZjhlLqL~jp7*_^$Z;FT0K=``;#RV2F1O5^;xDiU z{i{4Xz((0k%bo<1+j`Z_u{HaBFXPd6_A^t+f&0vW-3VKq1-(`cCO^@&SWn@farebG zWlx}+2ak6wB=h*HvwUSdd}ZFo`Sm(!doH#qw*s?$jmuXs1*~2QkIs>b^Ien{}{;pR`4m-)A+3L+VS6ZG71F13=0Ps@u=NDlLN_>;9@BY(_Z8M?wb#TAA=X>VI zbVr>3tj4@M(AS_bUVJ7`%SLM^|7zJjoUJSZX6!Z%-xJO z?02Q_tS$Q-J$svDsRX>sdroo3{v;s3lhgrgH8AF#T%(2TL9BZ~+9(F4=eGZuee=*h zTjPgwmhB{A<9Rqgyq-bZYS_rnJhLy^tSIN1eSYv6jXFVmjKn?aIa)7XAh}-+q@8==yMv7GE?>WK*rBD$(0-!?;0R$Zd9G^lQ;RWd?=8yj8xs6FJ?cpFYQNPXC2S^ zKejt-%RWEI-Zp(*(o6b!G?0D08kh!B7(Zi;HJ2QOfwWN!?r2}nLi=ouAJf;1V6*!= z37hHbI@C=T<@T!|d~*8Qqn@Mn639K{sRL5J0(~9FawNf4Cfb1-5Y`2e=(4C*8y3#9qO{iNFZZ&-vP6@AY9;U>9}tz54DQ4 z43{KZq>9qbaPzA94j#0w>y-9IPPTDBwK?7fQP&84hoIM!9K^&JC>P!iFp9Gia(l%+ zOTlvix=Jk5fwY(H*KziKm3uows`haPRPXEbnK#`1t?T?e*T$yp2ChTeJ3}g)J9}0Y zITh7~PVaemZ}0Nldu;yG>zQ#g7cm*(??20+k7fr$OishQOHMPpN&cchj)iz%$)gW? ztcPs3?J0Gy2Xg;SK-N93myDa0ePrCM1+ow3p$)pbRojwxC>P@$$|ZP*a!a>AI_K$+ z3A>{|cHsMH6!neJXEpRnHJDga0r1~TxCMcfIBf2CY2ukp8FJadXEvE}UD~gK7d=)$ z57RNk@N$MJCtzT(Y)=5P{P3Z|b1aZN3o3k0MP&=8PgSwgy&CVGEpXpP-)Khe$h)eO z;IkunuFHytdCovz%3vTSp1^)ZPGTS7`z4Ta^}eE)^>07Bf93X#fk_qMHfR@TQ04Z$ zM|&3P8zHwj(Csl09szFP$6S65q?GTk+?u#9x`|xe>!OX{aph$*ecx%120mQ3`$D&` zfrdv42OltSpzx^vx!A4-lIN8{(Qg7$|KuPU8%5ZMy1PD~hxOTgZ}CuP>wAkmzJD$N z2e0p&?7J0Ne3`$M(1SpV>D$bqSP$@_-z1Ros_JEBE%~10FB-q?+HsGM!T#{e_axiz zy53G3b4pH?XvYYTjZx@TYA_sqhYPRdXu$~3f0%GS7sxg1Rn>c-jQbr2baUyx1G$s4 z^*0NT`ySUZ7LV%(MFSeRk!u_16D)4AF-1=1Nb%Jf+msW4^zC&HI~r}+=b7Xiv3ylQ zuX9^#=&RIGIG@qBZ^ky|k3iR#UiS)nF2eNMOW2Eo;1F4@1q&x{^`^(k-joSU{W2pKZsk%8| z8Dho06nyRL-i(cHr%`5veOm{;+KMf7LXnd?R=D*#UbyW6Bv;e7eY39n_T5waR(~rt zzQ(|AgkyX>bUTmE#3CmOe{8$$1o8FyiK4#;q-0e0@*Ow6t!tgNS-u%(%ENc;B&=2N zPv294l*?eFZgN{;<#yDd+}zr^-j>e%(AzY$WrX*L%z-}K>I?rbgqL%QU_$jUFsWSY zft0T&$++6*WYG@>GL~7YFHrq1Aak-FNOv8z%~GHnyZ-O$VC%a}A|K>>50LBNu&~6kACPhgkmVuW_gWxhP5@~)zf)$v z4|x;gO6%IE4Pd~UIP77fnznLNG7Nvn@@u}!%M==yYj zr|FL0X?oyynx5`?@j-dci`Sv;?KxlDp7W;dYG*so!5LA}kST6l{KNY@`a-X@`aAk7 ziQNG*cK_LeF`!c^+i@V}xie*q2F?1AV2S*8?eL{3IjjOXYv=Il|#0AUT-p1AVM9+i9qdS&#RljzF0a`Wyw_ zem7}+I_Al_;$s(VQ@R0NpYFR!_jbq4*?Go|Zy5Z$?g2at6S`mOBy8=!ms2c#T_ zHmKhWq-BM+>At6YxxA;`96$Y8$L=)q*|Fh1FEf5h_MXCKU14APpxfgobUBXQvxHYU zwke~4M_{qmB{(ay}#f=~O1j~2&YJ3ONwjakfq#L2s(-p*xg_@u~%ie`(Fm+{?`LJZf^s!{P%Z@pPPZy9|iKe#w)773FPr=v+8AKt$6LDpsUCK z5{C}Jc;--GyEWHqCbGNr5})( z;?N`a%l5)W694N!=5ZsCao>r$+~;W^C8hh?zu#_RjMi_&oklcpW1HpBhr6w0jkSkx zZ3Z9ux&=siTy^+pbPvk}>~DM+G{?MXmM^vvgKl4Yi6^A}2r#Wa`eK{${Y=Y#2_zRh zi|LTog)L_Ci5~pjFh$?HU+atu~j}ITwVb(7h{)*eh-lH0+9Ci)Lx`*wFJ5` z=(QyK{hg&hLk!!vmSkcGqOK9f5Q4sxP9X&PNk1uk{7)4*QT1K$xY%w1vQGI@;o2Q_ zsUNTVTnJ=43AMkW_O+^;`MbZz{HSKu54A98sLNLi(NzI$PY2lM+3qs$0>RzkOZ zI)B1-sTaiO1|a1-)${pW)P&E~md|w_KK*~jcMtewoQ2q?bOlm3=gryoBuqaj_nw5E zwPjx)&faE!@z}QjKAE$1K;Dy3IdY1V22$9c(lk3Ymx zw9nS~;jxuIg0S&;%@6C*HXb(ebKmg|48r$lB0fgq9yY&+Evhzut>k_JkTMlWPIm(7 z^F6iKtM0>ojGt|iYY@nICji;PRMpu&dB;^>0%R=Dt8T7~b#oe?0Tn(t_gzwbnX3zdtT{_{w$Hv!s{RI$ z@vK+fYhI5zBzIo#tSx&kXK$Ono(`YnzXZs>4j!62uLG}24jdqJKrzUDDfy7O)5>!NN#Tc-M&UWN*^Hg z1AuN{1Kqv`GR`U>YtB}k?Yn)g`f4EK*`T`DydHj7?!4YvTlQSe-Zp(5hEMX31KHOD zN9WG#U`le}1DZZIn6HnG-R|pk@Wa;lF@0SGpLSoD!e;uK^E&!kZeOQ8Y+(;uQf*<3 zRrcLn9lK8e$#1ic;en_}83|;36M?MHHpw*#WL!4^S#zQ4Y@dCdR{cvL<7tL`vA(%p zY(H-+g&6Z)FRn+K5w`6dp8Gp&a2391!3R0suYL5m>TjqXd|k>f0aE&5AJ#XVI$77S zr^AoS>H5|I_in6oi;%5z>@aT&P}c}KE`mN!4a^_?L{^JmKQOAkp8`_;tojz!_jyCO zy$j_2#n?x<7SHZn*!Bzi{i^;Wa`WevPjVfNx<>dtU;^|iH5jhZH-%Rcm{8vzEB|j) zZ~Ygk(;Y}|=c;~@>Rq&rgMe)J44@l>evcpM@jYN2?`Kqh1a(|4oxSrJLA!STY~A$zyev-a`x@wWK2v`a9#Nq0E%ALA zkaDc*r>lOQ>ieTEW1b8Yt|jdIf)3U=Eg!S}Tt}g<5neYM54~CqTl@YU;S~V-)`{;U zfs_+eKTGwFZ%cUyNJ#ix_?=OG{6l%S zc~^W60#YWb?w~H^d0;jtJD<~z+WvgbMO`Dz=R)XqKI0q2ZwMH8Pkf&Rq+F=_RjLnN zFXa&+sRc3;S>O-l}GtTu~h)cYpm+CRDW9a=GcdEbO*Zp-Dd-~cb^T|*JB+hJsL5% z&j4)hbX;X!6WBpJW8|?Xh&GMzI^zWBB_stQkXQU8i6`};@C`ywDd+MJG*%$%o}+qM zoz%SxNO=&*^1rHny0&!-kn8VaAj{2h#~y#182fhqZ)m4bLrffheWBaqFZ_w{@&Pl5 zhrS1VEVg}t)Q?pCOVtCLr2G*ebF)_UZ-A_CxZB6f8u;H{?x`&99CK;t_LvKOCOl%m zIQY}|8jWXz>fflo&!%PN)F6SoZOyx1)?J+;RY-Y~Hu#XY)k3+ZlN4^mL zK44OLY*Ah%8R0buNSUJgt*Zb1bBW_0K$pK>1GLYb+KkK1xmiPpq09)^&=Jt<)L_PZ zbTf|e;71=HE8lNa@A#!~ivn5xwCbm0AL<2#_@A?Y{)Vg9S-V)jt1cox>)ss0Z*>+w z&e3(y6BfTzL379Vz4&_q+mu?M>)*W}vzN2=eoXy;r1nn3HG+y`;oswb{6nxCq3;RM zqiQg@i8ODHpHsxwL~K*e0J^@5ajrW=pQ*2X)74sw>*#wMb9qP0nL9G^jc?%3^SI&A zYe^7d`1@N5*I0>QNcE)Z8DOY|l-&a4evhdB6_9x;Etc{WkfXteeJJ|_S$-0b>)NG2 z=EbZH_Hk(i__?tT$vP%k*RIXn+LRR==hhbJH9(4qE!ro)(d)42>y{43R zfZXpRAUSr?eRl_DbKc$VzvF)T{@c<1w(B!TT1D)U3l0dE(Fs~q95*XePXSqP9gsZhfRt~6tQP=R_W1}PIgAF9(|90jP6bk~1hU>AfUI{1ko6t} zvc|JO%Bw)eD9=s76Xf{}nkJs{o;U%0?(sbLpW0^T@mlyZ!g=gWn3D5+cwaY(A=Ond z24oIHs{4VlU8QVF7m537AmhHJRPvkzvOit`(mn&L2-~OzQvVvr{P)l{3?*l;Ydr5cM_i7;P?$$%v_!E$AwCE{gwF8iS(F4f+1_3Gi1G(Q) zAbmdvWWASwtoJ66vL48KH-Zc2z|%nL=6OZ=o^xC~5q-$_*6zTwmj2cC*;kAq18zp# z=b)d2<1>SX5Ex&wLgJ4CX-oB!{KSCNeXz4$2)ffpw$}kEC-;>)-vOD^(YuL09_W?> zx$hObOYY|Z+2(^l%Hu$m*8$m=UEzZzBZ0IxwZ?2hEIYHFFh?8@ohCKph{uG1(Cv3i z1P2S>bU=6|fYAXO+aM`h03_!p_7eS1K&( z17o!fdES1R`<;52$9L*Yryy4MyK`ag{|NohF82%lm*jzCj>oS~;f68S8~P&X_VLU& zO2?d{bC8UuAdurH3gq}r0y(l`BL#zs4v^!{cSv*hUb7V1;dx37$m=M+gQYwM1my21A=rJul(v(izQ62K59GY>ae#0c1f;LqfaLTtkepf{D0&wlIrjl_zrBF0 zUkBuzYxOg!e>{-KkSZX3{~ky#R|CoIb|AUF1Z)rd1ju_xz6CO-=0BGhy8zvF6-fJV zwU1JJ2uS~NAfH04n+oVr7C_wf1bza?VC_Frd`>)CIG+t9htVO?rva&N>-=x?so?YWe4_}&}HQP^s{w6QCYZB_v3 z<99%Eyb8$uZvt{1xD&{BCLSmA`*%QctOj!a%>^=syMdg48`b`y+P_kJ!ST}02|&uT zKyG~t2%q* zuu}H<1(4&o4#+k?0kYn=KE{?$XNKdu?{smVJLs_BO{k$8{P$nG63JQ`}?r zB4B{QK?rVK=S!SPpcZXK?n}vs%ojf#2gFHepE>1+t+KsYurW{kupVvmU?V@?L&x7A z{qQ{+dJrEYQ4gErVGFA*8IgYa9!P0_uJq?BAboBGQYz0A`;$Q0KL;`oY@0RwK*oCj zka3Jwoqotas`^|YW4crIvTiMBcf-56Iu^Dr*vq#oI4*GjxQZDz|rNu)T; z|2h44*fQYsu?GAoo2D$o!rMWWC=4S#RQnQtuKV_4(jJSpsA~y$Yn|Q{`x`1$e#d zryjBW6xRa$(;9Ndz8?-fOfnDxdHQ}UJkys5?-29|^2M?l7faclK)r=s z4pylyYsg-*hIl*&V>A5Y-Y%!@$c8b*wdJR@oAFY9wyYgvfILrF3mgulnAo|^xQwkS zWEq7SVa(NNkH`(RCXHnUa)p@(KQcmGF%+eQ)|wwQ-4t+wc;(jU7( zrwjlx4z^97rvb_9eAU?&InocymjlW1b=BD}Tk?8#=7e8iELwfW9J8G$%8ao6YUn{V zu$-Jyv(Yj>+#bMfNVV!-{%V`>m$CfSd-zLVhVOUy(BA<-$~@Ka&i6yw7q*#M5-5(e z2scj`X5{}&g6AMck9WSCI4exJE+{s=>tNyAs!-;FJE&0#a&K_wrZW zgujI4Z>fhr|5fR$fpoABp9w{d(G(1UJ^4QqgZ4)O_~^mi4IvO#q( zf0bw>-+YK!{^oi4yBhxB)Aa{*{i*KdZ*3F)obwvTR{}lgwwM*)HShJZNgvL@>l2OF9v_`>G}h@{#3{RvNd}4Z29?! z&H8`2QLq`|-eaIwsKLyE;0?{4`1RsrEs&B{y#vZ9{ek4*b?@?Kw3+k#)19~rVUu$kjw3UwlX%sqEbdDuc8wuIV3amoEGAmv^lxorfJM>*KlNJ=L^-{|L>aV@&8?Ujx#kEVEi?4oJpbF2>Gmq9#jK)lXLQ} z=1yv%@IM~gl(T>=^O|3!zs^6OgD5jXf1{xX)nNRE?r!d6wEY9IO&JNy=dZd6e+kRq zQV)L_v>ns--&TL?oA6iPgg^g~%JYnaQNKZ4d9In~vzz#)VP7L$6J}5+ zVThS4=|?1%I53?M{^vd{w%-C7&#=W3XADT0ulh~chvg=Qo_S&@x#*vdA%K02Foq!X zj2cV~smFv@4Cr4XoE`*Ho>G0pqY}gOK*}qsx57TzG3=QqhLt9Uksi;)VgGp8O+ReT zilGR;i!S!~PWz1TNTN|3PKUACIl8!Py9}*B4!q`%L2K8t&r`*fRr<8 zWuG^IT(?epQI7dvz9i=W#jnUY!CtRQ{pDzbZJB2T+4r(mfuDOXYt}P@7>mmbWkz^> zt%06U1IyWNXbr~bYVmR9U&QA|Aj{-^Ev3%Z`)S=i@9*~c33=w$=HHq=$8(gu?%{F! z{QuoD=APrG{C5qx=XL!l(D7(#S4{4sUr4^=85t8HpesQ3mk;H{xUAnRQUBxiGcIV{ik3H~1AC(j!E|C^m- ziPsJ*krN}lHy{Z;V2!1?+p8%2LHZ}C7*$LvIzMW;VpK7yD8DqI|Il6vEU z$k=-X$g%W1kbcaV$#>7-f|)x$W|&*1a0T`?;;#SDqjU}-(7&&F3m3ycUx92N4WvBR ztc6>zvQYGQfZQ)xB=rpUeCJaWF8$}ZN3pLF<}(J}KA#G;6drM4TI1NYg>XHoShx;C z8Rbx|YdCkwGegkOi&!r^crbN-a-Vf;S@^;dwD z1F#Quc|ZBC?*E$&vhI;z313^^MLsU;-hT7W@_)j{xHwifXT`F`j z>pMGZ%f6J1~Ucdo=7pe2gSKYyl5jOl=A6zfXXa-uC?mAZf(|X64h8!=I*XHA-#^l?-Ryq&z1UyX#m!5= zBQNo4xxVrLZJM>J7WIrU_7wC9)>w}J3~SW^!g1n(!m$cS&hoos zFZXxHf_BADyMiH3aiB${dARYrQtWkV)D_^jjeBs&k$IYix<)v5WCIYFqJXYr45FqtF$4mXafYggmkop~g)IXab^}h#FA3ITU zSPSIv_$!coQwL=E_dt%HR?2N#Ii7XZzc0s&;L8Yeyb`*d2a9LGM#U?>JfN_XM*18z6I5c&g~{PLcW_16lsF(DM0FhE9JQQ%2iVDgsY|e_du3+yhiLt!6*CkSL*vRAj=DU zB{-k&?qpxxEhs8*itfO<1aT&?xS3O2&|b03ajysCiJy4hNvJ4N7;ctEo%SsqeF|vE zy*DYT>wdS^v%3{`EI2UFdGv^Db^hnM-pG7SK^-HEVH)%_3m^o>;XH=iJtQ%0S|a)W z9O%Z#>(@AbHsb4EzjmKC-{|^vLF*Py>w=!V`zpl$Nt9UKH)b@%THeMfuk3~E--j@& z#{0Xz`g`~~GPiDLTxYEu32v7)s&DQ~I?CgEXk`rf;{QR8Y#V43X&sg)s$#9dc$Bf# zI9KyfKg`7gVsaJS&;r*?BsYuJORkmz-CVhxg5Wf>5vPKZLOhqDlT#2zJ8q2oG%m+? zlQtMf=6}8mc5CPCRyn{auNsIvos=89+s4ltx8eF82;UPM+g;z~;@hor5bDfoRLB0E zdDeBvll43EBG`;@94&!fp$3ziRL^23f)8_XE0A)x>bQqwZ#)}yvUxUY(e?0=bq`6t zZT1cQ4Mcq-Mc5bxJ)j2TKkXNvzFvX}>iCe)0YG-;SwPmmQ0@7i@fat+ZM?V7H-MAJ@2~$3n_07$fP)c!C)o%+ zs0Pyyk=-T#k$&0_yGicDK=y?ncJ^Tk^}@&pZTs~tcGuX4fo!J?b=iIo-6vl^RnFaZ zKW$Gxl1~h68KLh4bh{se{Us(xF}{cJk3vr%F2?c&kmKU}3W?<`)ZrMOu61+f!j1Xo zf*E52QO5|mj(~2D|Ih&C0!)GrxqPNP`@qJ$4%9mKoUbAWYtF~Be3E|+bbHSG1|n{4 za|4jF$@s|g{^Bk4wViXT?;je+Jq)_tCz(AZ*3cl#E%0I7zXMX1p^S0ApmoZccxT@n zw4Lvree4Ievm}cTbFvJ27)W6`eMg2AJAr`kSTk67`~YN`oa6P#ImeUVg!ju`>)m7R z(Ru9q=Ge`5hJGxGvHkaKF$KVed3<4_QCbfHcq$7-EjVKRL&Taa~Su@A`SiK z_N9A;qQS=V!66M-GQ93bsYgEY-H+m*-;g_UtbiT_Qp{Wn%)v3_D&c+=kW#0*m%mE1 zk`fF7m;h>157 z6Q4;SZ82c-TH#X%qzrx|A!E+Iolk|%zq+_A3fE2 z@C#lq9DG3Xivok!iT_F<jBtEU zf^HwH0`sKZFfe(OY`+1d6vIYNKCP4Qe4~~ewsGvT%T4|=7RQoXbB|@|`NAiz7zD&eJ zHi<6^q>W;b`%>~DW9Nr05XYc>_BB78FKlNzZ2VTn59`rZ4IBBHch+ZaEzY^79|E7z zs1wA;NXnyLKZjHsrWh_$Z`Hx)i*yOz9u{=ZQl-L+lMd1bvfW^KHDmwi{1a@egeof zuk$mq-t+}>u2(!O^^OFRQ5s0uv|Q?UcwX!$0hx=NfNXyqkp8-@ko^Y&nbuK2@;wts zxg1D8&j4xp5Xg10#S0SeU?AH)70B}Ify~{LK=NM&WP6_j+0G?@68|+o+7JG-_=y5p z{w9$8K307TkbTt}eZuw+f@Qnd|uL`F_ zfRue-lU$4hQhJ~c_ZzPJTn=<&(C1L*yx;FGaPQRk{}Fdo=e%Ja=b$Yk95;)oTd_pm z5T0?M8yk>)>syW3UKd*g$Z`EFkW#%$>bwVJbA7dqlYp#umbPX3Dc^m8rT6T3KkaD0 z{&AlHOF*T~#l1msxivsTum!9eae{w=BhYan_49!NQ9 zoz%YoNXu0~&gFZ7lt+QwKdt&dfV{V$*V|J5Ga%QJ$w0<-5s>x6$N~A?4J5xOfV7)2 z*D=rWeM!xZk2&@YeXYa3Mi|2;==OO|;P1jC3XCDI($T`YS=n{>WZC|`rPMz;c)o}!Yza{%1j`+->mw>svC~^ zuG>tyFF(hB^;~2QI2LAsgApD_7D10Nc!Y4K#t+Zfvj(G>HZStab2(G{{Q>AOo4+D zJ`1WIdWgY8w&wC{i7#9)Im~<``H2D?Zkmej9a!nw^@lhcJ2XEKfkcV^?MnR`nVz< z`S5ICAockzO58E`0FZjHxWru-js;TxOPdn+SXKw5KB;Yqdn`M-op7rKlG|n=NAn@O zl(@&%u|U?}9rq&8<5D2kwG}|xW9>!156JzO18JB05<2pE7PH$Iwk+7&Y54BG@uA#n zM>}iFz7~+Z&Hg0sHVJ*+1<(h5EpVRIpCLTYp5g~;(N^SqrsP8|L;Nsz#A>w9xz7*t z#r6`gF-QEc9&IaNqgP%#io+1aJ;0-(2k|kI_OOLLY)Q4n5Hb58}Nvt!qe|A4b1h z*O1)joBV|K?YTz9=*t)D|9=DdKMQrh43NTHFb~1Lk|!UKHj2S~#o_Lcm%VwmgdS8mQ88Bl$s(`Vio_dNQReBZmD0FNQ(GZrI$>kjlX!kBCkABemzl)5zv|J_=Cg-O zo11~W#^fBKoQ{oY zy>0VU?s{w1gkdN%LO&y*+v{O4T;fC~iN6m|mOOk1q;WG4$1b4X(%ffcc-hE@ z`CO63hw-n5o?^lwrk`U|#djE(0ypwFbh7X|14z9XWt4q^-0u|KM}CLv<*pa*9m5{i zJ{BwkZ}&H)JkJUE7nCu64(Ao{ZG^|GjnGS&7>J2KI89E;&m-q`S zCH@&eHZvQ@{2X|ujH?rX)aCgJGu*sDASN%) z1rl>yF)>|Y3qkjvE!%$pG7rmC9~}|>Eg;)@7fAUS$h=HCPx7?pe9Q*0TrbC!xauM3l+1N{%!|o!B?g@?LW&NMl2$))Ajew< z?GVGXUnJX=Go{rghIUU-14M>?byTpA~_zOVFcR-$#?|+$$ z<%K}b)wY*Q`HE_pd#kPxeb$w7%>59^xzp_`u@43E*ii-K5^NY)iqN8 z_dxQz56HFUS=CR!w#5An`3@kD+52jajs{ZB0MdRbko(;NWIN{BC_}CD^I^|p&hhuv ztY@QaOE0tP^ZE(f`Kj#N^3Soz^RG$p$#riDkk8K#uE>3Ue&Uakmncw|Ft`7rap^ao zVi0J`*-w;w$o^;FGSA%3z(4zxA9`aurQpK;BE79gcwb+7wt zYn$+wvHaD0_zNv8aiZ`^-}eJ4C9qNV@;CfX`Qr3*Lvt-AjSAk*ND#qkT(ClB~JPt@n524hiKV2 zAjjiW)uUQ|C$JIUu-p?^`RA>C<$NaVJ~{iIIr5F6z7dYo8t7p)7`~DFgl`Z?n-3TS zXZo)MQXT}7=X%wfqmIi@pHOtWY z1^Vw79v3eXoAZF^aUf$^rg~@HXDE>Nqk-gqp4u-|-5fXE|9H&0uCtD@Y~#Kh6GPF9 zjbrEp-Hsu)SokJ^zK4X%sR^;w0m*I5!@~6yAobmKpHV=@5C+nIsoJYmH{S=n`eYHf zc;(;AX5v|G#k0{Pp44O7C&WjD*GWsnmIjjN;g1UMCxO&E>OO;kjOQpI?Gd$KpnASO ziM+J^eKHSqjc{DmK)3rO{-p2?1AUJRms6LDtqw?Tmp&m}ZwFGZ2U2#$K8#@qkoM!W zt%<7J|C?3*GPvit?|l@?j1*yGJoE}R&1hA#Dna&&$648lfLwk<(^~yb;3qnrHcnd-w`HgZA;EuLHRa z8L7ILuXTBR6}{3pt~Su^xYB4hrft8XzE(BiYc$&MiYsFIs`Bs^c^2y=K8)*RAZ4=Z zUU4nS<7=JeYomuRCt2bowCzvS*B4Fr^1tdG*J#*{aBPI2+c}KESMdL^_cd^GOj-Li znVDoVA4%tXCSO`IiHM*@Fd=9*VUVRotRQG43>&tWShK|Hjf6qa2%BA58bJ`NkzIqZ zy%7w8Mlc8(K@c>8SYiLqQ|DY$xm}$PvHR}({+-`%=Bab));-TT=hm%{uCB%(<2naO znXbBDT(b)JT4?!N5*f)s6liK}uuzSSow?+nsr3r@v1?rkpLVT-u+b}PodIT^ z$**e&eCn|-j6WkOpLPLlmqPAYyA?o6N3ly-|dbA1S&q&IrT|nEVk$cu|4Ukfbw&eFS zpj&Goo%}>qi3_&mpS&?bp>WvXr~^ge!H-?*6|mX0UIQDwn*BQWe12Uc;8Tw_ zVf-1%__PaYy9{#A+LfRUWosb$O#(8WxoW>#^(TOA&pugea$sB?&>v&y4y4ZhS!?p4 zems!zoTj?juf3m>uSK4{``*7}+0?l9rAc5T!uxuYptq>bxEW*WMafAPNL%0~$xRr@ zm|{S-i(@@=5e72GB|+p+`P~V~KE?oZ$vCy;#v&=>PJT>IVy z$o|ZA*g)%^YEvt6w}ETp|F-q41#_PQcO%^2%3j9vNlX^R)FS(;Z@)!m(k1-(g zm;^G986flMye4@J0hzZXkUd0!yw{fjX0(1MysY=bfn3+&6}kU65Xf!!22xG{lFy|; z`o14X-yZ0}!z-J{HG%d< z$aOySIchLm6ItOC0n(NR#=w^xuGBajT^9tB>)t@hzQ96UyT7_=Tt}h35po?5-R2s2 zOZ;Zu)VxB^DTi*bQR2ET33T(S_Q!xO*UHi}aNYczcMPP-HPCjwQfS$Xft40lXE~nd zbG^6iH_^9+PYB4oCV(;UC5KBijx3Ptz6Fx&7P?I>Q1Y5TUZ=p#x4 zubCCXH31|a=N&v3t{mQ0PGMaa1(NG@-R1&dp}bbVwrP0{qrDMwodDg=Yw%s+ngd62 zjX)1!nH+u&q$G9SgFte9L+vYoF4wB|ldFo$7MrKnczv28*8-m_w0d}Pp2;NQ>u(mPJPZWAjdJFphcYmj>Q2&gXV=xB}MtEPj`px|N%DI0@ zd@=V3kMmQ-Fzh^@CV&}@d5z|xXszVtiEm}wOTLr+_z56$v>He$*FJ(k)_xSwt)ct< zre64dQ?>g%(T)Y4C+hwda`->|{Uzqo(y8S-mbS2M{ki$+L-8`hK1Vg}V zQAaoS5v5|g0?1t4&|bEgTqgF*fz11{9Yx=vLfXv)QtkmV$1kZq8a}B{2XcSAQ}u^{ zZmxaymo?0*XMbUg>?8PgTa4r|1bP}s;d=Jx;N784K>B_dNcm88^L(NEw$WHgv^XoD z3r<5n8+xAG?5FcQ9GLfo&|6$DZ5%S)#D5Z)03Y%iiDk;kKytl8+Zayv@5u*NY&@qr zv^7Fb_0XHuVDggcDLmr9cz0Q@#xi9;Alv;~+sOOT1MYjk2l%`Pd=a??H|_oCCVwkD zTsa4i-2tZC)G_J`#Nn$MIH+#ytDCnjH9g) za!WvORfFLc!?RHIp8}?p=M{Z~+f6{O+ZF5B{y1&xcg?(eqB&NR%mvwLL zDEfCmN_TBL6v(-B4#+8H+>>*US0(s9E}jj(A^-aW z+-LqL+sW~?Fux70XAO9CAB$L7i&?+`u=<1i=Tg(VN?xNtEzkGJZ7GG2`R5<&OKgE3 z&b|EO+`;~Gu<<&Ce{4rv33!kn?*;O^E76f1-Sf>bY~Ks`%!d;G-hgAaPrHoTG8j7? z2Saw2c)~z(s@+B6+8Ich0;K(;I*W5%QGe?^Vd_VWyA1DQZ@13(`WOR!&Bb~n90T*9 z+vf(kjSF+7rK3ECK8 ze9NFGtlCA+5FbHc=rmbg1*D8TUG$Yxg?~3~E8p)q!acvax4^mF)X%{0zvwqm|1WUi zIOTT(<|4O7s4AAKI^?dkZsRCTkKa&lRozQT}Ss$(aYzG{=x+v-Se(b zfNVeVLg6$GNG`P(b#%WgaTSnUt_8B)lR(a;S=CR!Sk8TJ05bfBS+f0wKeX$zr;i}?W+27n zK0BwQleE z#Ma5d-CsQ%cDpI;Sju4{6>Lk^}W|kVtW-xZWC{oJRLP(^s9lCdx7jHr}l2z zS2d8^nSH9xXP=tz72@DNHGJKD%FkxviDMfhj3)uzjwkjP;g$j>mB-e%i|u|Od5u~i zyqDe~dZ}(R7|3|W0NJiV?Wd@2o)NI0pYOW{v25TO0TaV$v^ByQ#zVKC)sEk-F%a(* zE{CMV)(UiExJ$S`2&CRqw;2Is3=tshr>nhD^+Mw+%NRCtT$O#jZVc7X?K(u7g>M3w zQ{TT{D7K2f3b$E6a=qkU(H{j;-UHGe#I}s#XWCc2>gL?X`<&uRaIoJWzPUE(0yr5>pb$m?#E0FHj00_hJ6I$0^_}^j`wxACEKaXCZ7n z2j?H#(bfVR`I+aL0`OfAJ&ZpiF&|s*{`__kZI`=GYEg?el>LC@HUmhXi`4#{>K_1E zJN8Mg%tEIye#V-8P;!$3(nc{@sK&-_*SZn?+qF)@X4iTlY^K&L;V%H+dA0VjljZRkTM2He&+$*TC4qe)jtHXJ^OTPjeZ!{5FlgNNp<$`)>`!$K*n>W>VErm z`rG{ddUI{wec8KgYP}LZUH;!mtrr4Yz>{KXo%_4wCJi(-HfU;E2<=)=LjQKHXTfII zItiPpHJ?8Y!M9!OgpV!YV~eRR@Q~DQG>~!EC2;>=j zx}y_&L^$96sKhwsanWxAQc9i>{h=pCpSo1^#X!ooPl160 zEGwFv_uk#ev%)I@Oev@HGQ#n4AUVINdVjQGea7fEX219T9zz3sc=t{3vf-6L8zbbE zgq~1?sekS{;gAMq)L%EX1%c!>9mw_z)P9%RaV>Hvejn!sJ}Kf}2a=QLJE>+IR<~>8 z!F?eJJ!0_)FT?rh^WyJeAf*^K`Zwp5gRFa9Q_;`Ho>$KGaNu}a06oZ{ASM^#m&9-O zMT{%;{V0%f{R@(V2CSn@1-jgPo~5cR1~2PbDqA--8iBS(I3J9L9#why+drI{efn5KI+RLyFb#tCj>$E**w46M!LpeWSnc?ka@Q!wx!!a z>Z1AAK*TT za)0oBv2}rs?G6G`CIGojquMW5-R#FZS^M#@_TX&2XM^0>=Xk6$!W>V8p5zLM;g0~^Yd$;$w+_4?NkN1?!XONy{Q@g2XV}yKWK%bxn!zccw_=o_* zU&wMA$n|fi-WTgAqqS{Kzw(*=8hW{(HQDboD=Pyp_p_$rbwBsnNSoPTLg>c`z1Ksx zpZQAsQ+Q>7%v1Oq96y!g>aS#7`5IYwGmvth>PLJn`%MhUZBIrYjQIlXOP&)NnlfZ$-z&M#^w_8^e^<5(cM{0_+D;a`CqrT+ku zPmf~hZ#a;C4+7HPi9oKu5J)LP4D`1vkYo5nAp8F_ke_d~0NLKmcf0t^cPlG&zT1d* za`+uDHrB@4lUty&t@ez)4tk2@Aq4WxRSNG|mBf{T&UGQ^Tpxp;)cWq}V7!CuH`!Q(C@irewd0w|I>eRvMR8;4*{Te5p3Gq3GB;bET z$BZ z_y51ySzFF0G33NZH5OW+*RgOA)`0oW4w1Yk6`i3{wznCMgVz? zm;~gpAO>Xr4*|*fRUqe)W3X($Es*UF0#cR(nTJ8(OiM&#Sl=;XPFIYxjXWp* zztWE5iE~35u^Z`&g?nE$I%^dHvNi#<<9Nzo zJu#s62=vr8(&m+6(s!3_RR^-}dv7Q9eSz%j9U$!;wio?qAUT{5q|ZM9IewO_{t=Ml z>^mUG&Hf?ba4C@EZ7Go3eG6niopzA+y8_vMlImvyx&AyLdE5@9j2_Z@9>y4PW zpN;{toy>7txO3cIK6BiR?q-f_=X5#FZ;so1J8R7xEPyW~WWN;pN){Ai=8ouY!aJ$x zj1oNzjO#dfXr#p6dsnH=p+MH;2q0sA3rJb3>$_`TI|7-*BULx|Cl4<0Y*2F#h~7~$_hmGzwL#2GBa+|-x&GYIqL1B2a(6h8_Ip$xx38=}8A$tYRR3D_!QkZ92FNiG1G1et zFR{PFvI6mK>Ujxs#kyAZYReV(g<9y%K#Iv#;9&8eiU?+bu>)nf+d-0>LxJRY2aw#~ z0CM~H)P5!}n7MsVpZ#kYIQ-aiw%MQ7dgA4EU*GDzFIE; zhs~+A8OO`ej}gYU3VL2$qrxi+B+no)r5wMRDCN@BSK$TqW%7X3OP^$(Acn0sm; za{sB1d;iIP#;3J6V%x}jP5+5@%oUHbPM@}1@%_Aff(J-5Io}uz+j2n;-Jv&H zxkybZcS0vi-!rjHxdZ6>^0}6cpbx)i>>4d!ap?B-Yy1@KZ`yY$mMQxJU0?cpy!N|I zme5~!|99=KvV5+F9 z^tskiKKFlH=yN^KwdOp&ne#Q!TP@$=-{F3V`r7Vn@!bVB`rZ;q38`-OFYjk`6SvT~ z&1V4ojLv77`CzVRpuG{E)6a!&-|tAr#c%lcf(|gQ9R8}DUOQJfc1K%|uU&xTysvJ1 z7LcLdu6jz>o6oAf&z?;RPR@JwY;$ei&%3?L%ma^8v*45YSPJA^JYmbpdC#b%&Xf4# zKrP$%$ZaWwkU8NW=Y3)s`sbX>KaK_V7lMuRC;!-vw$ZSWpLzByH@!UX8I=h5)T2!p ze?~Gs?Lyivj{31S3$>n40LiH{wxQ46fz-zXDJQFbv94bXGbI-Z;O5r81pV8! z9|oIU`!HZbPiC8Vf%@2^vfxy$E02t!~u!oEV#<7yyh z^2wcF?nLm%>t-?*o|;(jD;RogBcsn#pO;^`_8DZHS6)!RKQot^409) zD+6C4{4tIskkX>MU%gfr@YQ##b>pgq9(Q|d8ym@4=pTRd72`5wj_Q8CqUghKY&2QE z5c@;l+Q&+xY*iB|nHeZ9E9&aVGlr3&$X%CqPWia@ z5$1us8eucSaS?~!qz01*XCe0EdxZB>K*|@Y%lECj@y_eI-?#R8$NVz-_xYaJS`UX( z^j)%z&-1E_u+Kdp96Df`(iO;DPFDRK)%~88ji66I-;J;vq3^hl@92ZL7S+DrQ(vE{ zJ_hS3M*+zN->I97_xImzj^j(|x4`cetoHaWK_4Z<@~^!k4@v()U_yN?1F|+BtM4vY z=lb@^c|H2{i#rCp5!SsCdYu|f-IHmIcl@#Moq?3F>SmtX!f88aSx8?#=Pb)DUn`(v z2)kl@#UI9TX|eb^70Z-!fNos+o+$5i(X?&z&y6?N=H>2PHs{9k;FGyp0pxdbV%z1P z8%G}1dI1?5#UQt(6hh7q{4>`@LGFtn2#-^ zw%8KM{X8J$aUi*sU_E(^0#e4Qeln1?VxQ!i05Z;7fQ(_G>g=EK&}1hIox=DTYqUjj5CWPS8!S{~ zW4CKviT>?ckATgtbv~11XOH$*&me-C6@Fhp7Hb zAltJ~x7I+$H6O?r{;E3rcWbSB3G&2vx&hhV)Y|**nDIO0*Lrhp-uil%O|7TFC;2P_ zb^_K9&wtiG@`U6d2sAY|Xlhyr?OLyaAG_8;__S+10yb0YIp7t4JipdiA6wMNmR4H= zxo7QKfRt7s`Ms|C=Rn3a9_`tVeX+)IAmf_@B=?(CXTPj*R`u0D#!-wsv3*f#JEwFU zzH44lG6vswm~OuBkVR~M-*+h6aWb|Nq2B=Xu%+l$4fl}M$A{|k zsO94Gc_8I8)&1toVLLMiZQn&P<9a;oMp*NS&^eD#O#II47+dhq_-+7F7O3vNL+b|f z1R~~Z{jA4*<6f-oye~!n1wQL(^>APfvd~kmmo^TG6}X4=mT)*0NI6~gp;$-R8|cv8HX;IM)3m~ZNO=8>G|qHiOd>y|)oRfEZ6@O|N#UMcfuP%#EOb03GE));>G zjefsf8h7;8nLYr#@Ynku21YkjSZMY zJmfU?1F_u*WDbtdHYWqQzNnn_~AinBd5#PVz z_s31FVf1f=V{`)aY981jCf3xygm(x?TlzcP??L>G?H$d-N#Dr27uHIw&wMNTb!bbu z7s&QST{_~v#CCc2CCsx}?i<)*`R}1z%RKzRv0A%ZTa4UKMnI2R^$eEtsX5Fu9V?tj z`wExql|ahGvI;luNkGP6xE88e8vSo7*Fx=0omP5ca5Fk;vJfLE zu>dJ^RX?no>OCa3EqYeC=W`9c#Gb1beJAumIZ^vG&%d~LjAHGh@IU5#h8>Qz`r83c6eFraGYfQBvH{io2o38(IE z_8+{vbh^)TeE)`be=%N;v$^nXgx7+Lpxe(oI)f#q6p%TH02y0ws|qKoarWFo+SCEr zrU}T>|4H>%5d*h5Y(Ry3%$N+M{_a58?lU0u{)1$@-GH3u4gu2s4v?~1bu+%l6qu8o zJ#~El4?Gv??kAhzm$l%$HUylF^uR(CdeGW`QX{n%y9ow?Y?9nn^su6%7{mG)>ckul z9U^UNhgG=OJy{@S+Z{x|706>r)o`)*2eOvaRX=!y`1)ceS^xOXqJIWttyb?M_Sfp9 zzar&Y59GcyN%h|XIrc7BJqaYg4b^mXxbU21_TMRJV}w4ZLbr1m-m}8VAusfq*j+eZ z1EfA{57FlVsmt+iu)F^rRA8)C?`8JicK*-d{=j1+V`5&z=-&vR-IxGE-0 z#l-PC40?kVQ}$Tl8$1p*JzAFcj|#{6K*q8c+HkX*v@L$eWHNqBNx-EYCtc7m-%uKGpGm7G) z5zCazfUZxyemI~ApVIi8lg&qen>rsCYH!A2#>1KOuITI3{k;ZOk>P{rutRF^H+aHR%+rGs1jMg>FB8n2li^fggST z8q1X50;$XQ2Zyfv{XxAh-PIcBOUc6;=gbjfT5a)I3%!LaASOr7*%eOWOz}IkQS)_{ z=;mI4_nEi4eK>aW?*&9*H^P`3pxe*3C8t$5VfbT=X8Jd|QnfqHtoxShW*hrh%7bl`0Bit9KLbvCS#AU)g2V_j41jhd*Vmtd% zv0VgYd`F`VSq79zlS^?{n-1zt&;=!PeWTH92c{ohpq7$nl1jKK<5fso&luHR(-^kqKARx_D3MQ zxn6Y{7v0wx7iJ$G?s;B!ExCK1RW-S)-M@_|b2SWllf^UerwS+i2k}39j_|n!=*^Y= z4v`r8adUHA$B_JDmg5+ob1a`p=t;|`b1n82_@$4Nt`VQt16`kb&g1u;`c?GnbIxOY zcRyg=c>6+6S-ulDV9tVn`nvo&@%;?Y^{w+nohP>w(1%}cJT{$P?+&3NcZH<4|%NM$6x)Uy&_5Xg9=zzp)s<#{cVyO)97eE-KK z=4+pkoZSXwJNNgdPHTH>i2d1eim~gnUgXHWT0I<@|19)6AcgDMuk(C`lYCBm`~ygN zLUr3m_i_0?M!{x;K1M^geI(!`j6eFD0HhqJI(+PeXV%7f>!7*RNIIMOa5Jw(r#*-zJBB4_P<9TIjaVH2RBcpLYT&&BjMn z`$O@Ytv8ro`*81ZqYwMD>kaAT!~8Dr@ZtWu1bT!HAtncb7llLi1&KQe%qpMJSf<2) z%;`ni<}#q06Cb`K#{Y1>6S1uk)@&+tn{T33I0ar7z8UD5mxRvv9c3&l}6H3fG9D1B`(;IrVu(xF&$)`e)$! zxXwlY8{)R1_2kaHF7a^ZxLD!CJ^H$E4=Sc#6MjkPX~aRU?UqXn6f51>%R|3o*wyF0!}!C%#pk}m z#@fu7n}&Xj@Yp&Vx_us%d|P-%f#j6~MwR1DK*}pX*6U-nAN!W*zXNjrxdupiQSC=- zUo}0-$Mh%;OtYzpHo@+8A-?f9PQ~kPrDft1Fz~XTtr>&xOYqK(50* zN#FgriN3A<*wi^?`D})sH@?2W90I@eaX6MKCj-@|@4eT`!}ERmabP}2psf+^f1{yK zP=kp(`=$5|eO2KEuuR{#0J;87U3ahAi#nIJ%~^T}yQZrB7#usMdygGSa_r*&+*6B( z6Kj!y9=13ozQ*|+{>bGVAZ5Dhe$TE~9sz$o&&`j3-3Wb+f^OF!@lW`|AAS7>NI6$^ zzjvO^uzcBmnfC=Azs&n0=yu+N--@r?TI?tIqyH8l^Zo{qvO?|l@3NE~iFiHlLiR3m z{E#4&28RBa9e6| zTkgXx^)KO;0H)Q~tLpn5Ai0!ln;n4E8&v-_(2rYq;)e6qfHp>$w?^nuHP8q9O}lSJ zbetqGqrN^=-(LXP4!c^@+ zNA>H0F1O0kGw?3k=e+N-tvtHG{tvqmcmIdppa%M4f6)?fDwe)eK+1QjWB9V(qLe6s&J zK*~JTtFVsJ6X^Oc@LAs!^y_zgp^w=Xhq=)6=DCijwfY!crW}Cu*&FL9TL6{A8GiTq zbB2TGcOcDiwmQ0Q9)i&A8YjyuorwCFr#^ebMxO~F*em z@SaE%x}B#`SK*QAB0L=E*?=quVWS)j>bS>QQHv+sAG)Rqr&=nFkdClJFS)f3~bhj7>j%al`r;r zGjLt;mfv;7T=Z4wx?)r9X6!BT@GS+8<2Iz4*ftXyz`e6R(EnEUvrc?vnTeNlZr)lWE-!sc>V&+kY^Pk{f8{LMSRcBY0+=*I|an1tS} z29u}Amcl19Kb_{fx_(-Amx44{jTF0&_|*3kA&rK4)n0wW7~KMYz2RV#osT1lor+f{I#yf z9|olMj?*t+;-rs{7RyJ*$43_ZMYPX5fs`kWj{^51x}Su23fzkrg>^=lyV20?>)_OO zsMWR-$GJetEYXr`1ax_1q|r&Kp^EXAnO@byZIiq_q)v# zPR{>s^XA&T-#zm#bH6VGpE!IncWEG>aUT22{O>k9J4y_h;kw_W9b=(zTS_71T);nG za}w9W5A(-A&NJ+%7Cw2-!aug7tqwNwGw*x~!*@OOF#e1reQZG=TU>3y9i%?vft23@ z$!Q^wK3A!|9okdx4dnP|pX3?_GS0(*hWto1!Wx7KPeMtkagfNrgUZmogL)dV18n5;VccWbTsLLlRL zSarWzhfd9}_2$~V_4O{BT2Fva@}C1_t!sakU+d5=Qfmju98e5$TS_5hF8OEn>t*m` z*Lp2%cC7>8;jMLa=loiyeQaSLThiDtW?8#N9lJAu*1Y~>m$y!H& zjI$BQ7-p)@{uy6d^<_ZD^S0{dxwo+Oyh$r!be|{jeh%jI92_}1vB~`J3VjEluhAk9 z$TPF6@J|ARb;A7=Af;@i#MB+gw(e)uSG0XrEx#wx!!h6HG|$cTaLk=;$9?vB8vOb_ zCr1wRJRF&)1<;c~is2Zn$GPA>!eRG)h1<`8V``fot$GY^u!ZUBHA|KrQ~3pr-5w0 zACT={1+qo&al-utm z@8pMo?B_rr?I#17o2!A`?mk`rFCaf-EIU-%eFbE@-G3o-%CkVW?{%2WML{6@TMlIZ zB@-&$=YDnra=YV!oSUWq*=`At+phw09@z!8;db>vwm%%m^$kF_H`mmDzlS&M4D63S z*VO;*Hja7bcs%$Uslmcr=xH^uri?#xqKpTpLFya=(w;g=@}Gjvxh|&moMH&;*)9f5 zV1MEAna4_B7XYb03gosgs=m+hQj3FtTz@x^5}73Jz5}wB9VW~ABY-^4oD8HSf$Z-N zT|ejq;e08OwSEK0+E!^yeSmELGazd}7D&HIU4NIZPpjP=$Lwc4Q@`2pam+r>u?F}7 z${C2?H0s}o@6`EyCw2qtOO*9vsw(PzNB`P{e5F%F+OhTPak^>5p_aXbZ~Cx8^gEp`_6LGYumqp?gm1?c+L zXTZHRpNKx}b7l55!}2u?dL36ljIZ>$h+q4jG);U>1-ia^cbwU~VX)J!xT5GF>%3~z zS@4N(u+}uRbE-Vg+5abO%q8nO2^@^@m^B-^{T<2F42dbGn3*ZDC4kI-NHK@?q2J58 zYk}N9cAPGCuLDv>1DThd&XaA&0IAn%-+KT{(e5B1=dUS1t~d8Yc68d_G1B*Jy9zAO*BK=}R^NdG~s<7NkFTXT%u&1d{B zAupfrF!o$01VV!pZ zO_&Cb8+e`~jy6VEiv)E0-hD73{v2TNGT|^ANO>Db4xg*toa=8@;C}gxb8szO;9TE* zKJ!1Y{)e1P^IU2HxN%=t1q=Wif0ut8NX?PF#DH4b?~&V53L*C;{_z+?9D@E?6aH~r zv%d&z96S7DJK83}Mt;0k7J?!9hf1drdKiC3g5YD@Vm|G1YIClTI`0dl90eq&$}1(V z{y@rjAniM1J90S%$T7;k$(dXj?-C&6Sf)DtkUx2G{q8`576kcaznQ|kLJk9m+?$*4$mj1fqSugLL{U6pDBkNilZ;O%RZW8n? zlMNv-j!aVGN-9Qf5IuOk#F+px{{h&ES=A%JjOL=_T-jz6kbR!^XVKeTE4AGU$Q(}v zvUbyf>??Sk*be}5EF1--oCIV)TY(d6I}XS(F$u`+VnD8U=h=qN?(uU=s}93{k2-AR z@zcz+Xa~_!@KcDa2 zwt6@)XIbbi7KiMul}>uT^u0HhDF*;uU+y_YZ#O5q*g2VQa#HM6P0#=C-gvAx!uTgb zpJR=e;2oIDZxde&Zx`QB0_nRH>nPoUE*Jd_6wiM7eviDBd^o3X;(I+fR-E(NxN=Md zpyz0Zd|#{kgiin%`I~UM>0Yt@1xSwX0@;2*v*r3~A+G3dFd-*3lEgU>?8ZT30O z!;$%10Np;n2t0_-&(zlo4~Xw?f%JXtBGGRIx?IYO$KZPxrxiu8@8DVA9Q|9*aaYf1 z%L~U(5PIHcTksjhAN#x#NSUL$nb*2lV`m2XvG4P3Naub<4huY-n1?0M<3Nh3RrVp_ z5&64d5SUR;yJH<|-Uwv-xVC*A=;lS=pSYFNcK+8m6MQ}IPpt7QGk09SIW}+K-etzj zdkIPO&)8Q2IrmOIKmV8?TP(4LfsBj7I3xdP(>dQ!3L)Fm59fO>*TN5T%s~}0| z+(-DwcC(AI0$#Q)?$a)-wj^rCdc2}F{02yFcci6$tw8$jj`ozH zKXq%1$p(8F#|ZTmpr5nPvQzaOZd z&x{|POYbZ&mrlG8em8M0{i(g@9{DC7gZSCl4CLHMe=Mwp9^-(8n6Z;wA>$WZ)wcn;Z@l@k*ehR^{ckRi?G^$V_R!^` z*S#h&oDF0QJG?ITU4is}JdpSH8da}&L+)|!1LXewDbU@o5u5v21dx8t0&@LqAh%xt zWPfJA-_bf|HD9dz{U)4?*I4K3JXWxuAIrX>YXi;~yw{S2Pv*RC)?}w2a0$?UcS9~G zV=E10ekeQ!q(6~*MHJ&evz}v%QV6*{Ysvg_c`E#}7W`xG+0R_qc#Pv8+tHSSjq7uFvh^8lks1KeFmX7Ytaeh8Tm@$ zN&thO3isSiC@!rBKHfXBw1Co+a* zRtzhk=bh7kBYfh(jQSq=}k5^Td5fo6a>U58*1Kf%Pf0H)RVUf&AGSApa<@jKyq6h7^wezp6lC*G$DWDGgAchkPA zfoz9o(+~;|wqhq?kCurIPCakT!}z#!e}O9FzRxK240H zfA0VMsu=V~hCMQfiA7OMRPwl&gT`^gNJ0 zyPzFq2#|Uh$U3r5a*Y8QXA_Y8uTq`;lXph-6+p)Fx$5TLy7zg*mMikFoi^9zy@v8G zn_B1Kll((hO05?GTcA@IuN!Lz$w3fE8^vIu8XLP^>nZ5puJvr#>{`!<&D1&re~I?_ zwa)q2Vm`Kv+F}^1jAx#X-N%9CSAzA7XB3b!PW6+4Y|lPf>jaQ--2!9`3sq*erCK7Fr}TF(b&p;Jt)qa7s&A)u+TK~vL0 zXxDlI`nPKxht00_Y}ib#xnC#Bd}{4ui}~0xYKtTHtX(sZ@(7Upim~3UHIQc0fK zwFbJi1~Sh1K*sP_)!DyWYt>7TC&tqa$o78wb@J-`{d#k4-hJ7-Y--&CpX5{a2dVXJ zpuJzmDkKMCpsBIJLNzvayVj%8zg_Dou-Uba!)9vD{W?{iU+Vz))MH&3e?}5M?Q&{M zAor}@5+LP$Ao!`Oq@1SuML@P^pR6@GFs{ddjA5DT?4PwJAFdw=WIV%F_xs*< zXb#Q`e7++-0d^zw8HGMU4dh5Z*+7*Oz#o_Q22%D{{e0D*R^5Hi?P>C!TQk3S?}INP z56`>nyvrOT%+D%|(^}~E7;$+pAEf?Dp&aLJDLn20l2=X7vY9>c zIR>9K33@&wSV_O;SrhY~N=r963jC>!1II=X`brXj7!J`|@f!d}z=yv71f;AQD7h-e zy7h6IhJH7e(>#mQLLW|v!Qwv*OsMZyl;MnQbKguYfMMfmJgHHf-s>H@na~+9Pwpb3lbN0MGgO zKI8KP*D*Hcvl0Cp>57E}^fK23o)SlP53Mcq>A9=uvw)P3Ro`tl(N6<%`Ct` zj6D7?xu43~aQ^RpZCh>l{Nh;XIR+0gwMiZ<@#hW_3`Hbg4(zON6v%R>)gA*nVQG8l zUXshRfXv}zK(_r<_1E_n{R1G^Kl?M$zXDQ!W3=eC_0rEtKyF{LpR8{IQq};;cl-Ti z{pDkY+b%zs>f?4iOx37zX=Y7YP-8t?N!uIn*gYP1)S`hh^ke5>lu zsy-ZjQl3hbkkZbqJlb#{i~*~hIK zOPm2snDZ9<{MN@$ZGOtnPh%q#h;@#3N>^sev--K$Py5AB`^9GL7d)nHg}Hkc=3yfv zv9RQp{O5)uC&~PtK2|VzoXr1O#W;}jf9RKT49}b_$M6`?y|xANdOU@G_!&xivb0Z4 zsdB$h6F;HK;T`k{bRJ=H=!c&jCV;#*9K`wnFsj>yPOWly{+ckip z;KVAYC(zOMkzZ9g)lhTTj^|bhU~gay?fOukBzyv~D);lc6x#DM;SAPq0SxN;7}jqI zJ=9R;3;?E%m+cbJYoUi#&q2@V@%E9!Bv&sUE^WsjDaXvyfINoY2;{ljKY;AxbKoFg zmxD8uQm40KX>6i zMvghOF~S(vK<9la3fI$5_{=INI#qnW3#9CQhUkNSBl_=vY%9MnF(Uu>B{pzfH0w6y zx{1$AaGWm0wnkXjCD85blgx#}GY*VR6R!82Beu7JgTHdvFZ-`a$~D3os9R#-R*sU z+=K;)$8#OzT{hQ5akMeQ@tA;aUlV077au8LQvC(7Og?++x@kblJk@L5=U2PC&#!Ld ztovQ#QFnmXMn2QKIql4~(j@pZ!eh%U==S$}0#{3nk*fp~iW$W))(5VTb+-W-`+zG& z-*UFhLt}uPZw>~sCf5Sl?g3r@yxLa*DTC2B=c@zNhqNsFT+G7Gc`>Z^0FcMgAneX{($_se%7~eZk1jy=*&9d>X90OEP6O%taUgqo4#=^+3dm#f@Ee5tZa~H|8pzmw4rHv8 zfIK$e2IMjK9w7JsML_205g>E+G>~)tOF;UMBe#@40Xeqs)?C-P_cS-~Teu4`mfic7 zB~FhU@{f@}t@|l2dDpf-jThg2h4UiM`NP6kI*$bb)zfH~!W>NB z``sn;)Knnnshfd3w{HdVTB!VPImaIbf#mQl zkes4_6|Pf&hE4-?KoWHjLvPOFVId2~fWDO?)Id8{++-_&on%9KKYR!u}mN*@Y@C}PtQPey; zu(i|neT(IP%YSxYb8X(|1-#1~!_0Nbz54tYkh#hL?enw5<5JHkkoBY(bdT-O3nA;r zKjw`XNB_(f|Cl@WGaokQlYeYS+alP=kI#RFVMw>+KPM0bpL(qs9;s|AfSR6Oj71 zK;~lmCnfe>fV963q)n8!5q1_lK& zv1OkVeo4hBFrjh&AtRh`1Tuz|&q_=~(1tM{qTAGL(`Dv14IP}pjb+Z3OOO?ni# z-!S@q#I}8BXZwZ{XY0mde9nURLHL|ku|DKD1?`QnUQ?krsKLY#d>K4n5{^rOls>SL zv;5xkfi9=(3UFFQPFq$uTjG5OzTXF2&pPsCF1kO^#XaAtbmWN{@E+LNeP>5Me7@DIsniK9#&;_ zhv3WSS+CKs8(~aiq1UOw#1wiT_u=4=zWxBDe6G6RJ8NgrR~P@^I$3D>TLeAq_SiNK z!XLmNeA3@FK*}1`{rs(6kH6Z#uN&Vm=wY`gzDnp}x5u{lq95T{qWwPrq*TM^`qS^t_HytH zT*Ps|Q#=KI=($$t`}d~ojrRg#eIYyd5$@-+J$$&IFNB_=Lx>qq=}(120!UjF*bW#1 z<~|W#{d3ah7$Do64rH68>JRDq9FXI-xArjzNEr%rmFsT&AitDyAk?`K~Jl})HJZB$_XPb_MO!DR(++u zDoPHmC~kiPJ#mhmPd`5MUdHm%3LP|DF@8c{!w-DX&lNyQd)TOBeqF~;;9-A1b+8*@ zJYndzpUgk;e2eyb1CVkHY_1>coz_$7$NCQbT+7Ei=tJCI+V+F+HyH2QXEl~7{ebFY z-S7E(d>CIgntiZ(Nn3mzGj-7IIX$^n{KbIGt@Ev526|RGd=6xOhQh|NbeL{45$JL( z@ZRkO@MphwdqX<8)7LT&cg`oPe7MK|CEUY`+3%{H5creRX+Uy48#cz(1a!Gt-_fpn zWZki0k4N?qMH?gTxQ8BAgBgzr_sSn*2$%vN`uZBk_1~#(zbkwmeOu#YspV@KbbGu6 zi#p-+zD}->x7F_|)r*RYo#J-9GH-jXzn^E{9`Y!BdftEFU1shXZv<_OF!xdDSv8n= z!zH}af$Lykv{<+#fs_i^*seR!&3U&DGx=V#KGtVAeILVpg6`{{A8=myG3^`keZw+v z9Stt5?F?W57--3Vt~}d8;!6P;AH^WIr4&Num4D{`K^lITTmEt1WIrom<1vJP=KjH2 z*vOCf4>G_2d`|#|@n}V zOfHOfYarv;S#|m$fAZq`nLx%gTlJc*r8Dt-`)9bW!I8jm&ox?+Z@q>J@hxo|vux%$ z=kd1jO20wqjX(S{E#nysWS{2V zS2w3Ejwbl_?o-}nvwx*Le3_Rt^aPM%_+~4GOA45+5P!95+W|=bzXh`WjcT8-cKmkB zp?LS>4fdOMxNi-40{k}cn~)K-F~T}efQ~Y`V)&&xV-Bhk9!ok2*XMxbbt=|Tl0fP> z9`A(X{&D8GpCkvL<9>_BFY}y%9&&qX%S$4FzVXL?Yq<;wsc!ozd(z)e2zDd%QwQDl z6Y0{)$!Wjcu}ld9-FWnS0b%Q!aTfhq*NnDq#=t@k2ktvdps!(aAtuN1?&3EB%&6~v zUB%W6WV2HGAP4^ThR<(P%d+j0=DMjh10=w9OUejt5@u#U15uuu*HPZiEV9o89P z4#Lo*YA`v-;tkj_?Y~9+EmM7W_wCq@vky>n;QPCzv&o^r?~g39I4ptA`JG}oMEZ1c zg1yDZR3K%U>ic6IZc3WA&hlKn1_1kb{(94ot(J(_)vWw)mMBz52Spi zdd_ihO?d{~hIes>HZv1&gQNI4qFJkM4AMqU3PkUn0}_2yj|1Fdu4`G~_lH)YJ^o54CG zc zAmuwC$KP%vMZX@%{WzuiF}uqCSiGC`833{-4WnecnLxI`0Z4fqNSa@&-T^+j{|^S1 z0uNEH#{u2ij_5LTL_=3+SYtP*wyC>Y<82DmxbKUo@kV^s_MdFSdNIDy;AVvRoCLkv zs#k1Zi8;5A;uygg^z>e`9Nb&-_!^L#_ZltvJs!xKzNy<3Z6CmAj$QE?WjCiE^46`$ z&DuJjW|_}shFj;^BVIxtH*lW4x$Bu1=3ydy8F8Qcgx+N3C3B#}?i{3fQ4A@@6jQ*+ z0n%paSjp4)pG%(Z26BAe3*@+ZLG7OdIX?Ts2lIC}kos*v)@>n>bRGt}<5BN(<5R3bh6Qw{~XzV!Lz6%tbm^33W(vBJ6`xCfzcy{Q_o|>c1Tq8UmYv@!$5MLg|^)O8X)zeKpBp$ zT^xM_Zn`AfE?3m89OKb_LVw-y=zgw_=lL5u;dAxQ?!LZdf!OE1ym9+F<0YRZXm5nI zSPH#G4JO{$>9`Jv3GYL&OgRq7INW1C-W$-PxT+{*?e6m){<*KhcfXEKzlLI` z%k-*HWvn7vZoU`yZ?-c==64A=7~wg}D(Edt9K_^1a-PJKn=Uy`0=Y{>fXqww_c$k< zCT$KlM{{tltosJY`J!)Jwz(e2++2li*#A5r`}!-8?H*P83qUuAy070_V7w<@M-Km& zd`JE#oqDm`~m% z<24L)HwE&zolfaJXkZ!i0Fc+=$vZo_&qk&e2nPQm>$7(VhOnL)8KF;e02MoXf8U2jFW!#(d-)iS^k(c5=La$efN!iv5inB<2A(O3beSx&1ctM1K}YeZWn!{dPcZ zKk{Z-e+ZDzR4u-8o3_yV}1owK|Kr$9mq- z96S2HIT<~OaJ~Z+sUbIsCD`@4#IiJ&pG3+dmf_CY7BJRK6hA6KAz9@zK{PcD}Lzqy@c$O zot)(3;(G>`Da(N_m$G7fN2aS&6h*$=^CI_GS=QyF$A&=#jtz6+bA9J~tiuwE=ThiF zt4_)1QKyXXiei~^Ik1gqZ{gXcqtm6xz55Yyf0fHUtHbA^6(y7LImBXfUL1ZKygZ*n z6k293Id&S*-U!Ea9C}m@W-O&%6JBv3Z4qF6xp15hq9I8P8?N;i}ty z<`nRgw*0jC_(^1Oj;Z|)!ZKw$ApOeshPH9f#}6+s24}y67~SuI6nLieKfI1P<``N8 zUPc(z3h49Q16p8|RM4_kfh5 zk+S|)Amw2oYy29J?!Qv|S|D>=3ZFbL?5@7ewYmM=WaeGu`9E}Rz6QRG@HjW*z5M4e zLwiYlImI-P@#Vr2ZyLz>;;@JJl;x>F%H=?|y&K5bUsAm@w&D1%22vtG*77JI`}+R# zZTAY?!8|t3NrGFUXU#Yk=%)p3jL=^zbo+Dc>=^Np0y?8*c~34weh(zCTeVHiLA_=k z)G*B1w{cr%&!+91o#$-tY&$>X)Hd(n?kkfE>?^hJgX_LMoqh2P`Cj-P!QGlloe^_N zux+t3xVatf3w3eqPiFqNw>SIaSj29GpEpc}j*wk3bDlF%YjC(=<_N*)k%D39v9YrJ zz|W;NmE%SK`Jqyyt$!i*D}fv{M@$g?E+F^Ar-5|)q1rE0UsnJ*Hm+CQZ>&{*u;H;b z0&R@2ztPa`u@*R1xMic`oX|0{{3|R|?gBC&F9QpW`Pm!6W0A#UsSl6TiQ*#;%uJT$ z&RC`#3?z@=Y8$_N^!;$d`528hMwpNB(CvJrPZHk=U{?KYfo00EK=Qay+xYRAw-G#+ zT0EBf@JO60JfgtV6j}b{6ydQ0Y~*pcwyBv=Gjl@2Kqt~z>(n<5a`v1v*x7mhR?fD~ zL!8={t=)Ox&;s*7_#@=);A-dKhBBwVv4gXB6Xt?Bm<#4(E@;MF(89T(TmD?|e{35w zH#8t0MmRSlpbxR;hR6j{kDOwnN%YW#f>~hd99b?pS8De3bkS>ONbME_Da(P}x4ND$ z`lmq74Hf8{ZU+G=L)F)gK#twLRj+YBo7f(oO<>M%TK}Bye1cm4mwh(zWAS1Acu!ym zVl=|*^tZ%to>ecm1 zu@3{Xu646TzX(2Aw|PL;_aWu*Fp%w*0!v|kRrQ+PyUpCaVK--|#!=3;O}jg_bM|oe z<8uq_$1^@dZFlbC?A%c5gz$XD&?bD(tI+cmKeh9J?&PPuY*t>l5AvSW0*pl?K`adW z9M?M>^bj7mINqJV%YKo#Uoi7G!PtYcf8-vJ{UrwEe&I9=Chn8<@kP=;2Rp9|!uN_E zhtB?k=-2gw{)q91R7Zd5Yh=0epJkir$#L$zv73REKV2{Tcngqn**w{|9|Tg~zg0LK zbK5xg8QAxMoO{l^eVlvWaTbt1XWlW+y%*R2FS1=7koML)Melu&wBHuU7)Amq-vT*T z^j#=^y8Tt`#mEt_AGZhc*mMMtX`Kq>y~3-2%+;Mh%0eLhJqYAnxKwq&^OlLLH+=py z18t0u-)!ji`BP}I_;i4gv@Bot58?AHkoEr>NM0LrP2cbZc>Ra3+t=sMoF^o}%Lr@I z4Bft_Pd_1X2A&j*Dy9?zOUF4;&DZpYB}eZ(Ds7uuL|+VK&MtUd^y`7l-G1nsay*b@ z;2ae@EU_Lk-;Xc<2J@5SEHOWclb;(6YF|HVVL+mkN z@L5@oJSW>Uy(oEH0;Fu$D(ipqvebV$kn$yvc|K~n=;y;H>y`v^yxgxG{tjfj7GNpt zFRAV~PU34eJWl4LjS>25hHj6O#9QJs3QT2X`I9$==MJ!OoE)xgimEy|Rg1l!+_!z_ zrHj*cZ#?idxbfb&{{B1nQ}$B_yAj46h8|Y~*E9CqJL8-H{7JYlwSkM?~mHXJR>)|hRv#J)q*W0E^n(L%Vb7|9d(tDxM$z+lS zM2%duT+|^1sfs#a#G)u;iJpomu~Y>u5-Tby9wTy;qo@&4(Stf-)N&5$h&hUio)NsJ=3*!rEnV4q3|EJde`)Ypc_W__Od!BdfTK+_t z^W1wr1^@8VdY=xy-Fbv%l^@3T?DDSSw|@OVE$jOZf5hSQy(>O;n6mGRm0g&p?9|UV z^YNdytU;iDS3A6&F#R?FO}*X!ROar_R{Sk~+FmNZqvRcaI?j!Q-{w3* z9*!;45f9m4&}e8K0N1`y2G9M~(*KCjM9{HAm&<=kD?3~|Cw%Qyvm!g+)=OI4#3p;LK#!6Hk;8I=|fX=pwS4P!?^!(A~N3gBZg z8nQKwl7$YX;Rn^0hMN{U8r(jh|9@NuwcL630oVQ|THnp!#dujW*r|VO`)?Vj-$MMf z?D$^JFzNmMvas*&jg@mFc+TWB*LSnEjWSNXG~XGZet&RyyqxJ>YObR=Bst}=8jX~WO-1Mq_L2xY2JZ|NyJm~3d2 zJaj6JcLMeMio<^c)O0T-uJ)B3E=`;C1??QUwfGJ;eV{eVaS8MUYW{+TfuKKxz4r!Sd%R$=U@Stg%0Jx zr9l0@2h_U%+~H~BC=Z?k)Oc~)Bsel{8;KKsO4|Tl}VRP-*)ka6Z~@J__0X?qWF zKHB;h9GP!9;)I{_Z5Mc)Z~0bB+kk`Pz!dapnP&p^`z%mtyVv1Mh@-Tf44jX)siUCn zV2rkwg@@9XXt(8;+8mAGMOWs}f%;uQn9_Esi*pB1Y5M_iKHBn>6Ym2d9`=Qsh!cLw zw~2XZo9M9Rk2+Wa=Alo^yw1`6d!W*`*u@zHDs5K+=cBEz;>fgRh!cKF+d1IzHq9=# zv?U!J1tyl+GB*MBdlyh?`)7wg22|RX5qCb?ZaWIviZR+AnTNJ=r!BwWU~)yHOt>=d zb@Xl}OldpQ#n}f`+CC4QkG9hn9hq;J5hwhVZ+pPwd>dP7Y0EiS0A`_2%e)k*-}it@ z+s_@ICXUkf9H7PvDi=s)dO@mVQ|-FtBX!a?Tr16)8fjd^zqgh-rJTjK^Sg7++W^0sQt43Ohx0HCC(Lb%>{&>6{8ts+gF)el&wg0Em|Op zMmRh5rOoon!e%K{USi&}_wkNY{TZvL+GHiPFN5}0XkT(#{bN2Kv>a2vN$%yqi#B-C z3@;i_tGVBgmpe+j^BV7@h8G<_vKl^g!H1-@zOX4+7URQy;<>iXo4QcP@e5CodvRk` zwk{D|>r0&6B`3&rxG;{7TmE-a?sCdqX87L{D_3QdcxN0xvW$2g#A{dnbFyo$1+<+; zmA(@zW_cgdSpMq?yjgkTZ21w~(U`3{QC^J;Y4q`+kvqV&X(M%MOxNZ+dK%7O2Q4e1 zWtq}~%*;niSpN9>6Xjl9n75A`dPj_`Sou(X-F&=UhYRCJa7XXJhmMy^abcVY?&6H@ zKVCkH3*$s^7pL^_@v`_o=i>PI(a1!>w#_S#A6ZY^tfOt#O6wI(!OB?MJYwS=v9FD5 zJnaLV-*~(}kkfdZYR@>L{GU+2Zq+1jmmXmpvUT;w0px%Fap1^pe=W3yZJ)pBczHK2 zYy%(fcz>n5f0+MH&+z8yzRJAH@PO7U_BKy@En|BF|9ze2Z3zc;p4KsUfUxk>^=uY= zqw~-)TF2wjq#d`jz=>6MjIQUmhIhHJ^+1h_eja)6;7%>u)6b9Qx6-DxJm}H32>c*; z3aDR5TXMCft=whlDFF2w15P-a9tG+e;HmhTdB(+k0npHF&I+B&S)oDB3Z2JUp&`!u zoX=UIXBj)}CnWxwgqU+pg+}W3|FN?||9^e|&pr$G|Frhiv0w>(_YwM9`00I#U5QJi zS_cKba4e9l?fdc^I~F9KZSmB0+y4hHXf(F|?6a(Y{`^K!J$7`c(d<`_o#)a6b>A^R zXz>F1>b<1wxs7JuvINv|WAwR=X5X_XCwDKL+aeP>-$q?u^a=(YX7BX^pyC}T+5A5SRNj3KsNcoUwDH~x)VC2o3{+l!3aH<=oc|A<|IeKN zZ-L6s(6;{cd2H(yOBjzI$F{zi@bFXKWWaMeA@GGVRC*z6_ZQf*&f&Ly+kt-BJ@b@( z+hNL{kDmGb!gX`eqfz6&1#~0E#aH*wh6lj8gW!5}O<2^67Vc!NSUcbZQCjvF@ zsX(pr6%N0_;s5OLyMg-c2Wooz4)0SXe22H=Fz;ks)eP_Tofq$prPfKyyp^!oorIMk&0^micR-es%aM4cmbFo$K)V_8AUn`Sa{?BwM0oZv>B*UCK9dx73z( z22j5thmSe@-3~u&{mJ*R_4jDdK6d*&Gz{!S?p|SOxE!e8bq@ck!@ue9X5#Ai1fcR~ zK7Ld$ou3~m{KHS%q8~iYkI@m@;tHGh!$AFJ9G)UfzmtGkc92*siHG91bm;#}YhKAa zTpE(E$t^Ba73ba*pHSM4@DA4l9-Z1(OW?ZB)Gw5o(rcjQN=wHlf%-iaKf@EZKj6Pl z*4awA^Xw0tj(_-RS?7R{IghX`c`Y(>mCbuMP`?8Xf4nzGrnJoeoA#a#dUUH?b+)0q zE5Upr-MQCWn#(}-n{aq`H@0u;q`a!R+SX?WP~$vx)Q%C)25R_v(kNe^<C7m5} zG;3eafIncUnv;+58!Wx~G0P_bCf{oP{sPpxtssuJ&Fg^ry~Cvmsw;IS%vR?? zJDL~2vUwqPvPkX3-T|TPpsiXMyCQW9=ZO6tt;*jb_zqLr9IeTBqAR__(sm_KzuO$% z(Xsdq@bM!cTReJ>a{XM<@fin=D=OZVM;C^U$rb_gkQTPkWc; z=LdnB?x#Tg{sh!`XSqC{2UOhNJv6TXMeZJ&vG<;N#$Ixw)^d*<~IsDe|xj?_H_jvW%wlZ2TzmCWHTjfOgohQ%m zQ~r*F@7DztUnnPI->|fmfksZgX=yA2m5&97j~3a(bo77O)#t2#wQ0Ts)G>G0eKyT* zpw{yTKrQY{@>UtU4(Qk4Z`Zn2(fWsDZ3h4FQ+iGTkGJdix3Ql=pXR-n-}=25Xv#Xw z8=zxaUaPTjr_4Wdl(09(aHT=(b(cqj)@MKX0c93n$j8wsTW%IubY-u&-}>DJ)OeFX zLzDUMj}^vV_r$~KC7YAb_c-s2h5Q*JUic}0E(DLiM_-NiL!dv!m{=wEW|3?dxz|mjZI=`Z9{r&*dWS@M@;wSyqw$nL4ZKtzc z9v=c~zMpmY*MO!So!-7w=FTuqDIez1+Yfp)YaJ?9Un1i`{X&{ce_|~Iotk%w-}*ff zsCdv&B@OH}%(WEjmU+q_BH#JSzY72G)AIMsSAJE3eY%7xuZQ3I4FFB~=1l=3t+?Q5WO9{b09eqlcxAWisH@*@kLi;ZWp!qE*JUv6pt z9Z3G!D zVaDO_A&$z(H(lKC0S&$8ovT{jxvJxxEB1XBHV21Y=TP?F^PZMgqe!0Nr_E3Tzs-4s zGF|SnwB}YPWRyB8-TwmA@E<2_-G2r&^;ufe%R2nx`PSk6>!AM#>+l?L!cS#<2YAYP zg!ClVBID4a<-KiK9h;4o}DF9rg>!`*80`?;$Mwlt+8P2b@R9 zBUzV_EPT@Z9|r38-wvPe|8?$robqO3-eo-A5ii6>_z<>sNX#H zvmE~6XWAb;ZZ9gO5;B0(yvKn0-Rki0t%TJQ{g0_fwY->a@VDYB7b*uW8|P?NyT~cv z)!GnzVS6Mqmd-3t=`Qyq%)B)UuJxP%j&|Fydx6?FN7FV<0jT+$LmJcGK<%qH0yVEA z*+&jQ&#}tp5MVa!CwH=Q&epvVRQ0X59YP%PJg(o_GJjwbMfm-(qpX}-m)O>CQYTBTxLaOety96DbHE-zL z(PG|XJTBJni_mej?=j97PwS_29PsL=eLk`I&^1i)G)rsZbXPy{@u%3|?>^Or{S>J6 zcm`ow_w#^SpK#pjjL|DHt;ArypUJQ*M9@3N|Zulup1K^K1k5Df1+idv-U>Ul!><>Q8`aJ;Dcz*^y z9!)ogG^J~gxE7p@(KIy=O~tcp`N^{rk~`Cuz0mpf1C^%d0UwX1)QLyWr|rZIKjqU7 z@Hn3ao^ELx0~Vl5%f8|q>vtPaY5E4x(B$6!Tp^)WA;vB`qck1knfoKf*S6L^(Ya-= z4muB>4qgK47q<0y*3w%9DxGq!?FT8K;yL_N&#=GCK$YvvGwoP#Gf=-0Q1c6jtGudl zdBx8m-9-8R`6EqJ@MzS2y&rrdP`{AI)FAVaqvy9k{SG=jyvxuO<7;Q?$b1d^#OcHh zKc#;NeAIb_G?a&Ixyke42fvj!w>!T{pvJq;`G;$srSq(L?pC^vag8<|qi+U$JVxL6 zc1vFwIQ}e4-vbv|zlHcIeYHTPJ6OC(7T>cdRgqtqTTp_}W*urY^ypgC*?C%Hz~96Z9TF;tyc-Ca+w&m_&B&+WaB&=sBw}P+c^C| zm9u{Y>h}Op+gx0pp*%Im=YDgO#vegT-s+p<3e z)bA0X(o|2_^6AbP zO_TG`H1H}*(-^P_U0U`Pue5%*0hOk201ZuTi{GH{doQ17zS+DLx{h(a86r*iX*&*s z7oCTet7Yb2ZD|m-hjncIOn7GCSpz76QtbJaZc96RanU(fmY5zg~>QC|4zd{P20JCCsL zW23h2#j9=o1YGNv0&4woz&w1=y1n1=WixR#YzI(ze3MK20ib>#0UBO}_vBM^`wV+d zh6mOLmNNgt_;>mp&Y8E9fB5N~ISn4SrA_R%bmoD|hZIojTzb8&*BDUimA%Ho65$2- zpmmxCYFLwtyBerzw*WP-Q-J!N0o3?epvv7vK%G-x<@`hY)vCknqZOY3pN`RH`}c|; z%Fh942tSpdBPw|bmzKJ*4`X<1YA6cNv$QZB)AC(uCdu-T00rmR{PBQey0L8 z-b;XnKDXYC|M%9^6QS+zyx#oZouBed&ln%1F5#y;dlx?Gl0)A29=*ZxECp2ll-_FF zxj1Iqbpn6ocNu8(O8ga15l`hR2VM;v2P&S&-{`x*fj3)TzY?fv_5n4{v)*F!dLK~x zSKnTn=CwdQYqIKko987!JwtF8P}A=Rs$BjMs50?epwhgMvh=G1K3?07Kl%TCZL4jm zJlPNJ;iurqb?IwWw zeGcfiT~};-L8mhjWIxlwVg44(q6NB+IGUIRc=&-d7Rmw?KL1pdm0 zB)IY~3sk<20t>W*=J9Kw#yJ4gIAb^2v_+t{JB8um1z6@gD(dng0dU?~g#u zFI-o}{{v|IsqnTHd&SO}E%I-`l~+phD0zpU(s&#A0p~HxtADg~jsum>()(;Z65z_K z0pK|N(y;p--|{!xG!sD0=M>Ut+^c}fn>|2{e>mH~=F^T{p0rL{#t>=4PwRLYc-eV` zbxMp|`UZgNmj@PI{eA<~@3QyXu-k#!Zg&EGn&Y<6(%(RH_32TXli(#Kf^U}QTO7?m zLo;w3x|OCsy82x80ULHVP-&h78k(IgEWRJGhjNZ~-FLf3qqgDQ;PJI+;#Nyz4mb{d zTK0J#w0_qDmF|xLACIQ?Gmf670pf64b;#2uE-ad7430JzG_C@}vC8+IE|!%`DAO&+NE90Y3IQ%I}4y2jY>X!p*eaC%Os5~kbge9rRXNkC0=0Z_-)GEmc|K5uz=H&D|Y z1ZrD7nY0>z8&J!9E>OQ=py92v$IfSGJ3t-gvjhCS{X#iQK7EddO8YkOvY~cP&I(_$ z^p}B3e+sDe%K?=SV;cSi8nsAu65Ef zX1qFSd(}PT&^qP5Z0Q>VY8w@R$%3Wn$w2+?25Q(rpw_8^IEH37560IKdCD-=(IbV2b-0kc!cXgP8TcXR=)Pv_ zFb*7`9!hJ^SFPU;pw?jwXzFkn{bIk;tn0I**o!O2Xkx?g5dA{#wdH4l6JNJwpSIun z?E)%I?*sZY#r2B|$@ge!+C$v%Q$F1Y9@iJL|K|7vEJK%;ea*jGzq^1+(~p3LCO3Y} zXIng|bRFY<&f0UM^ku+Hj$kcU%gle%(FYv3&(bmQ4eK`w)Ogndk3`?iASZ4#P`sNp-an7I=>uHvt_s+vj6IpQgARUq!x# zCQnAjIz#@;rWpWg-R}cx+&bcFyS4xgFCIsy-2Ys7ag_7w|5QBfOV!k;46Wg(d%&p+ z57jqvzjrbM)Vi1c+w!UauDp>0);|fZ<6a895|{^0INtvZsQg_pe=}uiUY7y2oj(QCGVTVNb~wyjz4>{r?>t-;?I^ZS>U+i|NTJa*{^^aC;tbV=LArBocg29 zD-Tp2zZ0nO>nKZkd=5}~{C1$GzZqzF{5bu-{CwB%)6sWG{@!o&{7>blZK$@g_7}{x zp>j139&f|!0)2rFogJur8^cbZ{4IiO8zvT7|04d%-z>QDea!hMh^KwB2(EkMiHar} zrF}K8yMdb5_kf!AH$aVh*b<$DbZYv|_=lgCnE}r^4-MD6 zQj2NBYMbvPK>dE@aNhJfgS*7L=etXMvzB?7yTpg{SGu&GlOA2l&nfT$pnf4;Qfq0- z0&~!)v@Wi(^fdq#{}xc=|GUG3`atS;lSeaeDy1t^`sPP-rb>V3&HK8;l`?Vb7CG~u zwn*K@_Wfxe585lGeR#37XR4)rur?nwRY+5sTNBv@DU*JBv5elcMLvi-N7FB=kVV5t zW87a`3qK(&5+7Q9+|YX}^e(TG<+~e7b;X)Ob)NT?QoOTUy+Epm*~|OF7FqViEpn$R zkN2@>stumQZ@;U9hR@-YO&p1*rEEX1U`d56N%J07-qnqICqBPLGPsQ|RNl~1aX)Ll&FrQOb3+U@*fM{VBmYp9J0c#FIWH|^5qkeB8RZ&>L&$|_5==d3JcDy8u0EpiaIeOP4y z-b_~+yy-JrWLW*+xrWc-Di@3x@wCMA^XfQ(cfo=!QeUnuEiP6SeEM=q-|8A!&3pH& z(@V?ErKVzIp*~-itIY-*>SV)6t!x;skqtwOWdpQtNG~h5ms$%p&lBd&GfSQwNo4&o zb3-Vle1JXXji6>|)jHe00pG#fdDGm`z#G}CX}i_D)xUbs&{F8wQp=m(O~HzwGDwtX zWja@xwQt@h5zSy_HE(q<<~?-a5bt)Un@ZvP*AvrQmv)L zW*Giw0`BZD%x_RBL3bT#=GBi&9K3Hg6vfR#eLhyImUlyk%iwooXcrdh3hWz*=yf4pybR+IT)2C>In4jyHwjS^<`(In+ zX57e&mCv@#e7|66r7X=XmZfP%J0v4mQzL8O;~IFkhPGNm9oOt^E$N)r7_^J>I#`4M z$a3N=BTff#+GPzduD6y5TN22U-9Qt+#l$z`C;y3%|LYcc7w%w4OU$pMn=vP74Qk7a zOLINV%IY|>8s;-5DfukU&&T)c=u%qOnzFV3B($HdK%Ry>ktzFM1uLjaB9Fi6r}gwx z`YZL_Kz%n1+I|{z)kqiqUHEt5-!<4$UQ$99b#6jN%-lr(Gi^CsC8H}+vUnwJxx>n| zkJ~=WT*e$|`s}QXBkQ!2k#T*4aHvjJWol(rdPzA^YA6^v-%>AIMpns|;gzx_vqHAO z>lNkYrH*1-VQE(D7WNm-i$0_MWnG=DW8PUe)F|s1pVsYcFSnLjic1QKe8Q*inzE;*WaZfQ1XW6nf2;di;ZRGI6lXKb0&xw~3&XQkvrxSZyv ze1=xVE6z?y-jxx@{WQUXKo-zHOxnx>8QqqWEoY|WZkN`_JJ#u3zMi?9mqtjVGGpd$ z9Scqk^Qe;Kc`3ODXWF^0Lh6`v1bL14tG+g$zo|o|6rYunU*l#%+4Jy#IdEjAK`!S% zBVNMq)=Zs*$L__IFn@SvqaT4<-1bXCdZ zMf+=Br5B~7>5`P(cbT@E(r)vL`lIjp@toX`zceL_E=$eMuTk8N)xKX)zd-7PbrP(t zm9;}zS(|yLtPQqFTX|`zxzLnP(2uQN)lOS*bC|ZU<8Z4P3+*^jgDf)^A|opX87EeN zXA-hvXH-K7uBnx4W@_Yh^!Merc)El36{|0%%$z$@A?=g3%IlO5{lOF6&o|Uk!ffWP?r@8)EJ9 zMPv+@x?JlG(TDg+B#vEg@!w5@thbg_%980Csdw!og_OJwca_Nts{&!+Iw2ZHLwRxS zSX{###@xr6%#Ov?lDs=5FToW<+UUPgKZ)SMP^AnJ$Bn~zqsLvWs~=1w2oALAx;(Z&p&BVoTrqbZQ#4o3QR71mkJd#F~2R45pKfmmbt+e;> zvuXG3wEG3JF38GU%iFOoPjk3=&yMG`=ji^Fya)GaNYhA_!M}>%jH5}zeLRvz+l=w1 zUdI{umAfw`*Ws+*2fc)uvF4C4#w|Z?LxnVG9@C3u;9lAZXYx>g^3c51?^fKNS6E&} zamF;#YFUx=@HB$E@wxn+l+;hnjn6)AWzt)>(Jv>8DS6GenfG=&xsLm3zSGRL_ow9f zxRi;9p5ozZdu>H;Y8|xNjGeP;B>NEK4Q_{~(R^lV4LNn)}Zy$SolH&XJvZz2<>Y}$`-AzTQTL&BLe zy!gR!HF6w!_HmCH-L%+JSdwqbC9<}z=vn2IEcmZbhf;c@ewOz}@0shjkEP`OxV=|| zyr^#cf zs9*5XYI!MjF*+gjQJpY2zedg>Fw; zy4dxtteYd?_1LOznZ#{#dHA^Q0W2f^vO#CL$vYhoSzUyFSnlkWffe0yl}qd6#@4vg z_GBx^^^))I=8Rmo+~wj&aODs3Ft(*zzK8Q=#PP2KW#+=Qda$8Fo9qYR#Jo!N7NqY%9v1kjE$fP8$kjaK_fPT z2HCLB+46d@w*_yDrgip9E#LO_R{Hu|wgQ8v28@gs%WMZgWcAeiX6|c5*`FOB` zv2KJlDQk6IkJeJJ03B`^eeDIn=fL~Ksh-|M-%ni9E$@DDw+y-bBDj;&>~Od2$5}aL z9`kVhABLrw4p~ZhR?;Zb*vTU6Rx2ZvpS!SIK8)M%%JXsCkC_t~ciZ>TkF`Gh2WMn` zZEP&qR)!X1W2u&|w6n1oJJe!X!&th8xnT|RxF+3NGW~_IXzYq^`3%mEMH0b-WQ`Dk6lZK7ipJ^aV;;&p4c+gQd1bb!_9a6v zb}@AKHPmGdby+ir-OSimolcMctWHn(_?x<=;ab}MHI@z^?^s{O+2JKpRW=r9q|wUs zDDr4zXL>pRztJrpxTaf93DZY#>Jf|6v4OVLb}hSp;^&z_cBZX;XY{&mdH7A9_$uwkHyTN$n_OtbHy{bHK&ZlYW6!R>Ii1s@OISt;+NZ5g-oX53a=%M5eLH1qrI-ST_feXblI zw>F|eU2fU|o@syD^`=(}DVH`kXfm)%@X+f3ZuEx*HMUZ;Fg*^c?C zeP@{4>v4Zkd1X!_ESd**c)UD=CDpQIm^o$$`zLd`+IeT|{Izar{(5)BhFpPJ&F&jOXYyy=@_L*d z|KLZ=&)8^oqW>;s4RXKh@v3iZtdxzzEz&;SD%Ddkn>6+YoF_zQ8O zVXQ~IxW@L#_}aG9*dDEYZKMI2u9vZ&(B~dv{x^BTfBfYTf7;!PXZKXtPhngP_jls7 z=6~HS2XXV!8V$qF?8UWq3pWq#bbB@EV9B3%%Rk|+9d$Bwh#%`8FOJoD>d|@X(0Lfs zcRKsbNR1SJh>SegEk%_L0+>^RwoZM;D` zcbdI8y9OFzz4^Otxe~W|xAKMhM{wnBG>+9*>c|V7WzgH#)A6e^Ej3l?XkYgH=H!sQ zMz_ys`tc09)?d5jtGGKI9X=kMQDgR~&0gwIOeZF7S<>>>AU&Jb$E}Vqk1kE0mIY~f z5pLr(w(dSYYrBoFV^=Sf)&6+F?*esx02hugJ{~MzB+D;0|9X|JMJKQ}ueM;_P;0O* zvou&2Gz4?2aM+D*onz_>+Ohq@Q?qVY9dRdi&th%C{J$0_C#;U!L_??LkGMy}Iz({V zZzdW?^>OyC53xyWx&5@i-ESDe#+{YQtffb7aHhOr&X=~PCE1pi?R(&vp4}KZ&)`46 zFRy+oL;Ut}KTWWKJwV1bw_iVNYq2t#K(3I}eV$w~x8!Qm@;O}5$`uMDUzs%Ka(W?#Bw&ami~vDE>F8YHk)oU0o@wALAT^ z*%xWdn!T|p{-=q(y;PdKdeU;0=BH&$v$qC*F>bFbBZ}+1$Q(v`iKP$PDx~c(`(O55 zx-UG^$k~)O%4v~-lhbkyZd&tHIUH&=_~s|1r5u($N!j2BaCL98^^4=0$7~usc}E(d z9HAT`Pl=Tk99JjD4L8VfL-p7U`8_zhTg<*NdNgYzvoGxJ30qyIK}MgFmQznn%Z-i} zA2+r%+b`WJwkF%Pw8FH%@-We#mOZ$lOB=7uyy@o1c&g*C_sI`}YWV1}p{XJF!Id3Nde)rF3EPjp?!Fy{8&mxw(HX2-Qr{O!2b zE~RIs=u6lNFCetw2hr z^2pAK4eW)XZz01g_pv{wc7Epc*0iznXN}C#28D~#auAn&v+~8Zi|^O527PF-suXfu z%h;&=?zCqV6=#T)z{t!(+HHXy7nnD5moWC=?7T_dF+Y>X#kQ?9Puq{!r{0m44VOms z4ByY_UHcZKjC?p-qtapKH`eLx4;edpaZv&L4#J^fIn7`7Ec$jedjaFGpsjYMrT;Bf z9(>%6i=0~-!nQ)6n6;}IyI~XdsD!NAH+ROw+U3?^XIeI|jiW%>fjRe3i>-cEm(GX# z9A@2(&bbJkGk4E_oH_PFvj+{gVi!S%Ir zJ$%2G@ju=+!4mrO#i4Y;r07whsnOph@3-vO=1=4#nIgAEotOxv*9ubL$P zp|pG+mwl_{SrpgtiaC_{LVStEw>m8{z7u<;nN!sEZtdenZsBkC_OyHmS1|cACLH32 zP1TEI&W3;-*T>&Ge;2VkTD^1W zyn5#tZDGTk=M5j#wla0El)_|M7JfAy*>8&av3~aBxO6$vd@zW7Z)$8qTfzL}OU z;OySHh>r&+RLKdG4YH9rhO?w*tTl8Z$GQD!`2+6OG1|!3?69q&%c@`Vy=l2i{i#~9e~Y>z4WHO@a%TJZc#zf3R486K!krLy|nw5-DIcXa!B za8`|+HB%>NV80l^eqr`Bkt99i-5i`Gj751pU8r-~1nU*68~4j7`8|wF?6bV^aWkf- z=f=-amJ;1PGJ^AI_x*xpi)GpF$mwk()8-79)@2yG?};BZ(*X%$;AN&nvzeH{tS(<9-@@ zj<{dfGPzKHHGN(6oslP_cRWc3dVAy=+`+K!5nTJ>laYgHypC?pMzd$SDwE<~#zvXb zV2Q4JJmZNu-yEE5^{s-vA22)C=oyl!epxzl5_;ijQa-6io_TVQ?0To=zmMC!TlC~i zqpaFFSCZMIIF;UKMls}rv0`|LvmVH>Ij43;k31FkfXNg6V46M_@uT59yknJ~>pb7k zKSuP~b5fk$GwqB0wVnKpPGas+*)e`LEaSq?t&nqRC*9MUy;HF-F*2vnlHL`JN?F#y|+g8jwEEyaHCwEX^`f9m3p2f8|7Y{=pg5%(2zdhy0ndl-!LnbRYxrTKIzt@9y}xwQsh_hC8BX$!71^F*lp}aRwTv zYdHVWBQM-VzgHR!4;LH!q$?S_9Nil3<9-@@c6#xg{tJEOH}pvN8yWZBL!OPuEb^)2 zj-FeKgweh}9;{i&-a2cPQ|TwIY7eNj_5fzzt`_D%C*!4SdSv6C9?5C`#sF*u;hgskJ<>Q9>Ile4%rCgAMy{eQMi@`^99RqOrTV^+5!+94T`#MY zmklKt|F};}pGdr^N8W|2c&}~yC{7y^PtOHPEUwk<8`16Ab7ZcG>^C9{rML7*=iZ*k z-eAN}+YtJT#Q7;Mw5R!au(L{bPOQ8THsTPL}<^~lnF$bh5Y$L+bh z@GKqY%?CM$^pa}M<-^~hx%tZ49oDdJ;XY2}G#=Gg{gC$W*no{Wz@}<79y9li;@`Eb zQkIRhuxHD^eX%ajeY8hz!)?16e(D;3rrF@5w<8DYM;Z9h&Z#lkryX8rCLrIa&nuo=OB%Z@s>H8gz|Em@^Z~0 zX$mqD&Ryz1rgP?Tq{E)vo>^+wfO*S*<#We+@`nG^ARpe%9K+w*R#x$rV~?DN+pqMh z4IJA_Vv07IY&HJRC#+=ZqBW9dr-V+7ja>IgxF5mzqh~(y-{_Hl#vL$eb-uD=liHL0umF5G)?dQ$J@H+17F;;K zNAS@0%~(+WVUM&w7>-+vr5^6tQ_JR#jOu^%??sGbi68aI0B-#KmVZ7Tv<1?pv;%<7ym!Z{xLVPQnmI{UO`Xh{mnUE|JH>>3kMKPjt~PYSH2$0)XM6oTLjM1z z2OS(abbBO44-a0wP+lF+SJe6=<9=v%4&hK^K3omne19#Dl=3)Bbz^{XdG)NYF0Z@PFHU_M`?a`O?k4eDf8iZNS(X7bWJ(a z%bKB2vdN767MHyhUa9}&R@Qm_#_x)*jO_j|gT7&~E^3#>qN99G zz(0F-wNcivep@rd-EVZeHTyWb`rJBsE_2f={8r(|IrF*m%SJ}Hw|Wx%!-Z#9eLPrI zA*%+>J(bk#eQ?GmLp!=vHlL9X;_5zR`5(c(Ic(sZjJz0UZG1Y`vQA)bi~36x4`uj5 zWC0hByGb8+amx55pEnoB$BpfC5ZkAotNM4@dPGClE{;;-(juV_SjQBBTdAJ>8tL)iR2%2 zAFgEbkSOlrlwXpO>dR=)f3WQy#dSPDZ}H=JydQg6Myg(ZDDR{GB0g@%rd<;5e@*ZJ zkCnmKO5&o7d;oXtZI+e@?&PDmJtO~(^T)xcA9{x$$JH}6n33%`-!>ifV=VOIMD#IT zAL!W%+EU+n8GS`Y%DB`&E1j;55Alb0hxkb}t*cY^xfyvi&aYF{kMYirv>j2zKApZrWu>X3}+vWeYnQ>uf2eAuT({@OGx9cE-sEd#E9%FdksrsSCspS~d@U&s0PJ{A9&`nkHraX(G4t44OQcDw?8(%Wax1-jPt?!(OL2MeocTC!t_gb0vmNM_P@Q%q6X)Q4)zMw%~ zFjFbdnX2M`W22nI8s}+@<(zlcHQk(jRc&Qzzd|m|`VP5B-kFi}a1S~QqCg| z<8BFifZYe6t>q5Jc3jKH!uCV{m@Cw8^{40y>W{p~@klzu2gcw}XXFdG@VmTpDbkLMlD10Kvz}#Ufj4VH;U^xGf%o1>V8i~p70f9Ww)g_imMDnP_p|eVg89EemhW@# z6`8l9T4nVe(Vcg@&oKM$OH{`~u982>$UfZ0PdJ`>cu=`eDmibaZ#|f{v^3w6YtCAIV2Kod1@CY-O~7lFu_^XU zuy?B8!e29Asz3cOg6sK>Yw0(;7Rnch6Z|G454d=7+|NJYTpD-U$}OcO#YCPns;eqx z)#L)+MbR^8+(G|EM()8SKWWSKar5TaFlRZ2^!>5L;@%%C*m6N{ad*~5A&3l@AP)mE|3S4+UD~i(xV{yz` z*G#jl+ZXL`;TSi%q*s23^Y6d=e!?DW9_R__%pvBfKkmagAIIZO=i^cm`u)6a7?m z%*08(@;=;Nlb*gy9CJ=e`!VrU=ZVBoJ!4w+B=nvq_R2KQtWV7TmfF{lA>Pb+>E{nl|s&t$=SC_cGR%9N&kw;P@p#5^z1qKY*(}Dvvu&p(wf-T zD=)-77}83Z;U%<2!?1IEaXZr7gAGof_dat1k+S2|Go&!sE8jS;S2CZrZ5_pln2E)4 zJQ=^ZSH6w2Ji(^t;Z`>=x{2%K%<(VkmHHR=%7iN?f@_|Pv*SBxQ=C0(K-q`*QH~eK zy_GU&mmBVt-{aapW9w4#@L9RdQTP5D=|?6v!{a0}se5c@J)Y~8SL04M>6trxxg}02 z5{}O4;T`CO$r0{{WU{270djHk^a$x+*()EwRezRxYu?lJC#TP=|HpCd8pb#r#i=84^-fi| z9~8-p_&y%oP$xG`)ycIZyy=AeaelgtzE#kZ8NsS*Y&+O@=4?CmF5e8c$6?OPT+Vos z@0D8(9h8Z`zQYsoSG&fDJxevVr&s zUU~iAUfFn;<%5sUopIE=ADnX>bb5;3MH&hT(YV&B}YCwouN?n}r=d*v=%xG&-3=4=ROU&A$qnJY5fLHIbl0Bx=3U6y6maTaam?45lLD`}XyN4{F( z`n3dv8QI^4>^}|JKYdpA%{XJm3*_v}y>c=xwD0-2)p5~pk)P!|osMhX-B=>a_L=iz z1;%l!TTL}d?km0WCEU#CXiK%hvQMY@4{+6=x9uCp{WSKS(2ei(5d?v+RO+W0=M?bddS8+-C| zXQ-53D^tAvQtp*o{)_(kFE+i8Tm7&e{g8KI=?CGPuqN#Y_JaTJmDk{|a%p|sj90te znei;;nSFM>AI%-FOoOC;-z(3--R08ycx2z-zIj$KXUdsp%~*Y)S6+;p3Df$xnNMn@ zgx}IX%=OU-ZgdNqSMiU%QuU{~ydt>EYn1R$Qh2Ycmb zxbeH;t>(p;r}*!1cd8%l5Xb#A_6?IpS+>*b2PPlxq5qk@aR*&KK5lHP_cLY{YO`Ib z8veJXM%GW&%CeC<_^;>no2C4hURm>3=Ke3ZcK2}G?(_|0c{Q@UdZ*ESZN122O#0;C za3d~l1XubPml6y6B#rae#J-=AkBg0b6c-eb4}EiHgs}-dwtmRYjpL+$K%FZmf@?X@ zH(JprU%-X$aQL`=vnC<_n>AfJ&rBhM=;Kn^C+Fi%`J&~4kK1v)g>f9+pM4W^ZnR|I zJ`Gm#*53V1W%Eumw_VMCFnVM?eX@GEMatEEa@yiPxzXk8;~ndGH#KMp&lR#$#}w?= zNoMWF7?&944gzhIYUqw>YANq-xcD{2QdPm5}ZbHi;T^x_3aqTmj6?ZleezLUI1WYd*tnBh-Y0Lyh2u^H_r`@>XP>+a7mhIz+?AVH z(I;o%!f_#jyZ0b-EBoY1T=*WOj~o48&)>TjNV@bM=nVgdz@A)c6>^PxumG=2d5s4D zIew3-ANytZhd6SRob=}BEI_8f~;>GLO#F_V7BIm-HMQtA#fJS3$8RkqAI(Otf?F@Tn zC-%vuxU!==g1a^;5dJ4zC<_tX#hKXBClBMoc8lOKc`2m&XXmm!v5pq)>gw^ z<9*gvvkm@t9LL)koEKb3uSZi@&2A^=A*zix;%&+tceAN0T~^ zvde{R>OTGSI&8UXrT7eZ^2|PInY8ll<7PdUo?VZnOy3$}OdITzYtMsEnx?)|%sUj! z*ZP)cBn%$;c<{U$c^>PQ?L*PK!?W)(U$7_?+Q!6Hd=gjvRa@UUen=YHqxk$j`5n%zmyHbuTMO-> zey34J*5wt){dDfUNx{5j)S_=Ev8TgcT+ImcH|wy`7x&2{xSK<|d|YWCMo)MdwBzg> z+}JUE+{t-jxQ~02%!6tZHge4!3-I^j4!XRfIAam>f}VGdq^0eAeC{p^Zz0>eDE3^0 zmNAJAIlvhFls>ueYnHDOTzN*@D$fe1_DSY6_^;=L4SiJxKO4WBTv`qH@k7$Uivn?S zr_b>sf_r@?_q0CwM_jzmMEx0ey?AD>$?zWXpk4RrdCV5hbMQ7;DZEFe>p3$AO|CZm zsPt;exsr0ePQ7$qA6aAY=f8$AU;W^xhWogm#+(J$x31W8v1dkG?3q!g^Nf+++Mrk` z0sGJE`{d=g0hcarKqxm)N|cIJy^On(t@tKekJBm1yU;@vy!#Z8ET@ zPd<;EaAikuEgN~rU)LwMTP(--KWFeYWlzK8NcX>CiZSKEZQq<+;Q;Z-l#d4;h9ySgelLyYWUE719GqDY_oHsk*{EKhwrxUfbpgeODPb=DRf z@@5MA?)`o8KHN<%t&e+mgtDeS(~L>qMeo2(X?(3C`+$mHfGdT5GqnbP8-6pPAN5iE zy}0UcS~}yn<}sUwJ{-vx+%MbiAGtc|`6;D^{i)JapFH#58Betg^`l(HpN$)J<;HP8 zjeR$BquxI$m>JQ{fk~Znwa?G2r!RHO==Yfe)oGq)Exp0uOMXE6yK*$#$Ne5?c3-DDK$(*xIxo97jp$e03rRiLC!fWg^DWCqAGh;C`@HkP1T3`kK^OlW zj6U#FbZM7|j|Z35$))s<=a1CNAaY~QBB?bs$A7z-_lBCGdkJ(m$#MJU?l9Z3IcK0R z7Z<}!+4T=VS-(^|vDjyvek1tF+*XE{`Zq|011`PDm%D z6VmB>8GbzbX2?nU|2&1Tm+P8sJmeX7Sc^4Vc~fkwobqkUvna0PW-N~KdSUgDVHxIXV&!(u|)5vh6Osw51A78gsGT(7^oJtt{ zQ}}IDKj_zRANSMPdr9WaPIHFMo?Bx-6T9-FA@1{?xK);J*(zfuFZMHMu(J}TZ^`>% zR<~(Jw`r30`)m0>DShAOY-<NEq%jeTV|?9)=g$) z*+{Qh(^hBb6Q^#K!PB8`MN8GJjxU+Uq#$tF2%wGAIXmH+WneTetAcr`n(z0B3pWR(UZl{7)z!_ugMK^F&_r);W7x-{@yp7$l43>PPu;T=SSsWA*@;Z^$c>ziB_6hnSBJ31d7Y zkC2w2nfGNb)*GPIwNcM2R7z+s8r#d*em#BA(cD^k`Z)m)-rk~Jb&X> z`6#aX0j-0sb9KGQJ0OJXd2c`5+BcVC-)xcP_uKtu9S3$$_h4JSY(pnLZL(IL#5~eB zyqN#WpAZ?;?4wquv$KdT;4oXE$_-0znrzF@_$J?tvxkGo*ld`wSqlQ zW4mBZ)Bg?$?WQ(azL@(Q`T@>AyY2hg zGaJ~PhxA=K&N`(z{aA2sZO^bz@Wrk2DqPDC96cT$tga6Cv5W41R_%Ijhng|60538(#C=g&$X$G;uZ& zXa2FXM4aI2YToD2^Ul~hu+^)rqiZSqv&cw;v)z~P-zs(A**bfMC4y^Pk~UBHIa6ER znP+%-h#$6nFHX?1P+CsKrcdXwXPWuX3;OD+JLcX_;huSKCu@lI4Cl9cc%hDtqkYP} zd-&wV=bw1qrr?=k?h)%tIVt^rOAXIayw$rZB>$(avgsgmaA;f0#QmVlixV^jj04cL zB;cLCxqJo^{qiQ9pO5cn){}R*vr_0Bc8_-{eB?hAhMQ%)tzY`u`=#)p$}02V6mJF) zCh;)k=QMM}(tdd!?%;c^Z2Nd{Z;jkb+Z1Rw|38FmzhbSjs$Ui-(dS2P+6eCY-q^~1 z`6SNodr?2mU3qc%t5s>;4L@`~L^kw{C5P-}BX0ahwj3WfHcRF;#=N{4i|A8&9%O8N zzpUK=Z6*y3g}?7-->Js7HW;-f*)vWnIN#*-!ve+YUeE~dW@VPi*opm8x20c_KZX{w zPF!yAui%$aKV)6QeLRvz+l0J?|9q8Le)iqGRgCQ`c{fl0kA`3*s_qk6M^Qf za-3(Fwr6`2L3kfc{mh;EdmOxlIJ(yweS-@LbbWz(cYLc(zJ=cWb##-qpe0PkpT&McM9cSQd;boMM8^G*H*{c~7r4&1Sl;`% zl@0Iz#WLLCeo4PPjC=GyY3Zvj|E(rZCStF^JLcW2N}+f z_RCvw=4_9S8?=++AH?l7`N|=@r{hx~)*Yp}68B+YsxI0~*aXgZSGX4B#_mzhDKQn!2!N`fNbN&PUaucp) z+S2Od_Wut%4*CDXj`fSsCDtJ`{P(cqwFK~Gsd*!@Y%GL%_|c+!Z0vE?HTir_da_txTP)>)d?gzJAdW!Cc!QZjPJx2!Ut|Aq7rebW3h5p~t`c&tO) zr+5pNIYQ61jZOE<7jZitw!Dqtrd@g0Xr^BVf5-g)e{uFM;Bi*f0`~gSv`v$=o#vi4 zElICwfilzqnp-<LK&poG*;Ad5o1L_M2Qu-C>%pUMGr?K#&b9x z)UifIMU5B)6*XdxprZco+IxR9`or` zJPZ)N|KsC^CUb9Ali=;XL%g%1V><~gPeaSUvQa(`Ou6!X+`9{Ob`-_3fO)3tp!aJV zWiQb9D_f@su61Icj(>e4y2bDc7uh&I9#pYzb{aW#@9a2zqiNFfrT3|g@>Spl%~#jm zG<0JOc~|~7jZYh1ByR10ZpR2p&tvTqB|#6%gA>&%0Ga@ z7i_&FxUS!HwG3u9%C~_qP6T&xdcV6-J^_SrBDjlFe|V!@3WRYYxQjEz_f6l+#fji9 z&M4m(jOXG+a2IEY??3b6L~s`;_5F?VZ$MZdAGi7jizW1#p=&_<($KVY12PcyX<*}v zZoGZm9f!Pa zaIH!mGw#V~+x?z7b{32!lp@ae^zbqn|9r z4`n$%D9fbcN%*Q!<&a%_DK|c=NxFfs+z9T@+P?fi2v5jdmlGt(w<7{31r*j;~FQ; zy~RR&-vGW(gh-f+H&oXoF9YG(z{jm`vNFy&JqzZja+B+mf7FKPeic^rDqH@&}z ze&ZbM$8~)dThSydfw1o)xXL@H(a)J=U+Tl2d1;fhE^9iXUx?^8Wb|I#;QSIfpS`AU z4BLR6^Cx)Ubf73Tx7Wx_RKI?Hk2 zdo}z9pjW>cnJ@jow|^BL$xHi;x*5O8@a~bap}#(E@5Xo&HP2_Bu~FKSy`zpR?KZNV zqh>|)ads&^SD6%iN~|9qrLRJIS2jsNo9! z>5{xK+Tx`Tj+%`QRGFv@*4*`KUyd)7%$6ouvb9O>)qKob=JVZHaSnsWJEOBnt^-~S z%gIl}`1yHc?NSn)O>@4K?YT6KEyx?27sRvQfWLmd5k(NLsTmMa#$=!>QPWrM1S-rQ)qQPO# zG-eH(wZ|J>SJ4N10hhmzXU}32g_(j;>ZCTOY5brvj-k)f*gKo#OrYpx+eRNZ@2l(! zwIISa#Uy!S6FzvFq({@3Iio&#nq(X}OT+a1!Ms$yUc(YMHOX$5e?A^br}t3PdLE3i zhw#o8=_6$sx@x~i!zB{W$d8%t=8eQqAE}T1=s=TP2FRamTO+u(10F6u+$7fmp{zKH zv##^vSlf$5*u3&S-2tQTH(>gtkNV%yBz?f{usk0(U}d!Pw` zJ^wjc>4lkhd^x-IC(u=c4=vvjzC}?e!=GxBuLI%!>f=VPMBTGIAv9s&-X{4xaLly! z6J^Z^L(cETvF~)_M}c{@2D#Ik1aA@Su(}&&EvC75rcN{bW%Q#%`B~N&aEmDm{=mnz z?P>0!zuY9R06yOo4USxe!lNSDL zoOwAToc4I}tjtyA;K=CoPD%MU=$7iy5B;i1z5!&y{0P^5G#XC7`tjVH8kvMgejd8_ z1=|iE4^*$Qe=hyR{|)$+y?8eMwXwC`iF{P~c;AQeIOq5=_Cfkk{?H_8pzqH%&j_xx zl{{5;F#6jjdEHA*R(HURbCJPE2)omz)$cw&GYvivUf^Am7jwL_j|W@k$`;Na=N!I zxL0N^HtaKVOivUkeMjD;-&G)~*Qod3p`$Lnj|Zdl4|DS0buHr?!|LIz(zoL>p(dpA zcPejdFnW+HkU6fDp{33848qqZ)-2Bh!>`)$iQ?p&7svW5-=goV z>yBsk%8d5W$|6}g)+Tl7O}y2jZ(t-vs+#3bz^g8AAFoB9v6?e`PScSl(BD(Kuh($D zi!3D8znpwl@ZL+aTvpL6$-me-MsPE)q46u5<-zZXNka2bJaqFXC@pSXnjikaai9F2Lx9>wJRu(R&#U z`#sS3SKGFH+)t-EBI>I=dw(!ckkURI);?1iN}^sy;?45L<7uPjr(u0n20uvHkSjyK z`?#M*@Aei4_(hrWEJd80_Y}sNdN+o?_=m%Iec-9g|EY zQ=jz7GPJ2#DmFJu&EMR3`nVgbiC*3~Ih{C;Zu)p&-uYUE%%^U~J72-?=gaS>i{#hi z^JJ2-`*}L1z6K_;=g=j{kl25W{Aj|w>*M(J5{X~fEY|~%n|kS*$_vxF^+Pj=^A%vi z)!$F&&heIp=)HQG-Z?Df4Ozy!AKC2No8{|3&1<&pJ|3ibV}bhO14CDrl|`Akg55Pb zOrw`J%ej{|OP@>YH_-dS#uh0`AZ{nw0vA5d8*C@ZtuWi)1rAXES$wWe4m{Z*XNyu0$>{ z03UWSbMyk{=y}YGv$@}|{Y$Zj(6v}DL*HnY?*Y%6vh_@*dWP4~!op-f7xlbd54*o-4mgU#f0%?2%@9AF$h`g$E&A z<$`{APB)8pyb@8}tl(Xx@~+AGa!tAvUpvU|b}%#4qAE3~*YL#$^4>ikXD)oNS+)T$ znlho4`C*2B&{xytax3v30ZIdH8*wMg^1`^6kHldx!NdH6(@W7kDU*8SWA(^n>kqko zdK5diO8f}#u+-i1N~KbNxLMu`?AP*&cyEcesXwVmxQ_i1!`a{b^kzRQ#QvpO4glf# z&d1H0?ZKS_2Ruvtdb)6~9> z^J8#NNEfmNjM^(fZ|LjC6mkpJtx|T4%XF@$f+3o7=N&YQ}qWoXJvuY?kMMy)K=P zTN=sT4EkNcv2)~D>ePrX1v;q{X5LW0`k+P5ENGD@G`-_P6u%63+U1##`)PucOXcM8 z66xxLhf1)PHW&&!iq;@LjtdoM#ulec-q6ST;ubj@h!=+C6&d`UgtdlYlf|O=-6bv3 z8-`7n82l@Q^=laOM!)-bBn{uSoNT^2&%m=~>sgn5Nbhxq=eNjVAiR@~;D-O_W4`U?`_nE@jqBr)^kxolSGKK1P6a}}iwJJU7C#oJvj%pw z98pgw^3BbK6!EVH!n2-_8=ave=oW_SIljF`-T`EFJUl!=zA}bR<>URUWHoPEXQc}8 z0QP)drh4)b?PWt(c9^qp+>|jkTc*x#k?J?`_Dm7|Xk^{Uv{+vnwjHR@aNWO^-a#ug z>>{91!&#g8cqAR)Bl(B@d`^pO1dK0q4TBykz7^Q-^3BI%`Ds|6Q#)H^&G{`^U(h~o zb@zEggL}< zAU@CbfsY&i@CO{X%B_VxN0!ONo)%eq1#{4(fxa;JBVoG7vKICcXLhQew^tqp}^`TPCp2ofg&0MyFJuSu^;7)rMHvKV4f7}3#d@o~COu1X<$X5ET ztq=KK{x{9viyPFl2lk`)51&@Q!=pDku6>*#-`^q!fpaxq()zfygUh}v?#{OJWNLql zY`C#S?$k79&J-E^WWpYB`RI2a_tONYmC9*jCDIe!+cLVh**li%DBr*shq8(P%l<4w z{mqz6u9k_R7P<06EpkkWZI_SR_i<{(dhd5UR+yHvV*KV7`6)1*JC1=KUM{mYa}=kcW_mA4lKuse<-$W}eVK(6*}1t(A+^=oyV3 zu=O0)da6uon);}1R{t^?`UG_Jo))PowQY^!dRI-kYM+%C*ZH=Y&~u@Avs(32pqh4ZP8hQa$O{(YcE!|0QIT=U4L;k%!&d*^IQeMUD_p~p(Oi{KSQpCa{- zwaE3rfXN#^gYUji5&ye;^V_Zs_}P(1TI2=b2~BJ0vh|;%VgCfiTz&KLNII1js{RBr zoQXrE1B||hwjDlG@okSn3l`-1L-7lNMh&CA`FJD^-)H0t%@yj`4A^@cBKf!*i}*;3 zTml%r$c=^KHv{*&vh(ps8uKP~p{%7Hiy6lS@Xl&OGx7Nr`702fiF`abZZ0+ih1j*v z<-Ez=#a8&N#j|Abljwyg&k-+`_;ispj>89!VRwM6E!NMS0X$9SKbfyUVxjGqD6aOS zj4$cb&fUHtt9q@`biv;FvX{Ak>2#r71l{dtZfD;W*YdR=()gSDUW?2d_r{94D!v#P zb>-*dGt(5x#Q(HN$J1V4c(~m!N@N-JS(aeWV7~}yaQyo%avN|=%(gX(>zd@g)Qgkz z=ZY`a1pX9un#3ki<|%y0&?Ou^2E5}o+G@-YlLhV%0ePM0rz3AXkt?~qLZke`?_0PBPy}al*iNvklP;$ab zc&&P5&~?;{a`zZ{1@+RsizUHZwA?SavqY$opx=lhwad}NK4|Xvvin*O;bzWpM$IH! zrF2WHOliFw-=+AeTU({5+|KQM+)tzSsLPP=EMreyX6;|IdKiI@@gDP@MfN=hQwHaf zRBNmJ4A||;h~kV@UL4a8$bIUe33bqfBiZU%9x8iBZFRk&Pr8@Zm$%9nfM;EKK5k@X z>`BHq-VS8A$|I;OUS;asl4xJ1w9l5zktLJphNTypbCs;&jY?o;h3zLFclYC_&kYYT z37t%1UkvZryR=nOz%EUv>k3+@_{g$WO!aJD`M96P`Y+4#5qxSPcdFJ8*~rRP`71Ey z^73)Z=bRFeMfcL(ykURBivDu+$2d#B4v&me?oPnXvn1^gR?p#lRjKDIbANAb%gfN| zFGr_e?;I9O@=dLBFVI@4?a(!he3kE1#>k-k@AmF?iM>l4wVaps^{Do>nTv~MVrQ$I z)88t$nEY7t9v%#q${_ppwSDuD0U%$@o$*uFCN*K~7osOWw_XF<{6vX7F@21&)9`N1 zvg<@N&N_4pxUX_|cWOP6{hkTyIkuX&-CE_EOIsygWyddy)4_RhEbqPah`hJvYkgqW zp^vcyJ%h#A?^M}y?Ev45Y;Hd5u9Urr{b`Teml*%yn^{-Dn5#zwH#8g{-8Z$$dM}QT z2VHZes~>sWz8uZ4@)Gnp$I(w1@&b^bpN9P%h}YQu$jAM3f%-$HezhC0Gt%)$ z!^_;$DlY?rn%<1j9E1Opuv=W7`rXISMjTWNtbUv z?x!(l{|z}x&~RKK{tJ|bl}hHmR#|d?s~l5n+w9}k&$uT?uTje>R-=*{M zpho#g<#Di|>MMjE&l2^VX70VV8lBdhj~$h_K{r)?9($x!J_tPK^7Qcl`=+%!%pR06 zZwkd@wk|5~d8k$1@GyIyNvCTx8fIxoJv4;#UqpIjX~;0^)UM*QHMCcz|gXKM5j#5XZ;k)=|#+>n~ z|7NSa3iK|q^^D+V4WQHWwO08H5Wc?|!Ofb$j^OL?3xLmiM#Cf$$L{Ou6No+PWpu+_ zS@OMBIR)@-(*3aD^jUH`{G;-$c6?VHar|_DFnK~#Mt%Zac$U5IZI*YB;D#4en`Nut zmH9Dr1PFb@L~tD=z4!citK1K~cA?GB#|@25KwmdR-;gqXjDs5W&*eB5>SyE^=;Wla z(d#=(Mt{{RAAf3ktE-vpRsWzqZOcAk;_k@n8l1O!m3A&a$h7I;tG6Z-yK%W#`X)i50cU zL15)FTR$JS_qF)==guMjy%u8=xf3ll$3ryen=tT`)#*}MK$~WdBO@$rlM&!Lm$#1x zz1Tm%N1hA~UJSj6yuGP)h91`N-MoLtexNoXLltfE?aDUyewIY=;FePKPUgw`iFa~Z z`Cs_z4famL_!mqZ!#zKK1PAm++0wjvo%1?JC)aV#Zj+N^ZPIv@?FS#v`f^rX7GEEd zy<~(u9vzOXp%&ZS>DlNnViQA~ z46l+#F21ZydXH+8r?X{{KXGK7`NMa8Lo6BxIlY(0oayX|D`VO*#(RV8*=6uZ;kyz8 zHEr@!AYQNiKs$(I--FiseA>cV_2bl@SSpRI@kVqT8qsZNJe+;gCwq1>{+tfvtT&aW zCTYIXqos*zS$ZhCBk6ZTkInbW8TTDw`oPG^;5!llYq2Q2@0>7t189^O-MMMT2VQM> zN1GgdMw^s2XuB92!c{gG4M(=<#S2=Cq_v+t9G=|y8s|(7k2YS5KcO1w?XN~}-|-ag zzIi~~wQ4qcg;io-o40dK@1Yy?J;h1h%|KSXbPPR?{w3y|k%_m-w&UC6PE$AbD-Soe z0rZito22bek)PQUHsmavjNEWq^^ft_*VQJE0J1!6FJqS)Ja6PKq_ zBRG5N5#spy+k0)}o5Il*=IR^Uyurtlq%uqI;VglR?(Gd8;s_V|%i5)b69mK?W{plMh_jCdaI> z>)*$Nt|IAzu2mr`F}4O!5M!&k!?z`)&v&=UwZL^Q4<9$@yGhP>tkHKQVq)HJvL1tb z&0a%4c=~`=hb-;R`{_2`D{hmgOuo!r!qxYFeI#5WxS`Km&AG?uMmDH#C+zQ+j+LOR zVekA#uWXaQ19dC4&3e8iZ@vj}H2>&#_E0Z=ki-saQs1u6zNM<0Ly2Ddjnn3pfZBV58{vLR@UhUr1$1F zxeMr6W#@>GTmJgP@YgpTk-tuopPjqdPi%xH~r>W((~C=l|EJ|65Vl6`$nW}2`* zr_8$BU?phAhKzBmWbd1wP#Z4%0v=>80y-nQ{rtKX_a->a$fWkGd{T^<8-BqEB zfxo+#bH47Ben(_d33Ma(#0CuScfj&~Jxa^K;h z_~`>t-5o`FSp5Az(ZP3?LYQh#gqTuCXZ>Dx!2)*$UU2eT?dSZZOX$V>8Pil zx2r?OlmSmN`1v+@7>GBza+wQ?e-qfKVIHrukUAApZ}mf?-+vCAqH!oAACKh0cfTCu z&z+6wGFi!;cs+CwU&9CT_3x9UvG!J0K3%uR*;{Epj9FXck*~GMaZj>VTpgk~i;Z}y zf9Qv2=REzMo%7JS_&3_*TR?oRZBGQ(@ld|%sWw^g-)-Lg6~5lUR{;GkT|R!KG(*Jy z0$_abYu@k{ihm1u$mNrd`)O*AK{gT`~_Rp-t`pUK-$>t6}tw;`aml zUAlbSPvhBfj;il6(=Yv;-I>R_?t1^$CVv1jCNKDMzUds-_j&zq#t#y-sba(2DNEO> zn{1MYftq8e|7>W9o)@&vk#L>sbGg^rB(DcHYFx%Aic{v1((3tJ!%06QU-IzFiRjGl zv9#CjpK12bw;y@`#9k;EWG^4b_V6(K=V(=`vbQ2`?jUjofjua;nym?NcXHz%4fVE*m+Qh4fG}%2Yk6xGz>n^i}SDK zWvXXlbi&hB+_T_^@?}G#t*u8tZ-bn*35Cy1GPvHY7Z10#;d(z4_3ae27fCzkty<<$ zZNmBxsI5ak@<~hIOqrGVG~nLG`KC|VeyWhcTQ|uUfN3qy$cfNrXP+s8_tfy?KDbE= zkF#~j$NjW+Jh&50a5gz$$HVORs-H@|)TXiieVb$-VE9g5=gfJG9`d>xvx1lr-9IR>nLQ=Oh$v-VV@Iv2S^Ts65ESpnzOzU5N?rA=}p&>Oe? z>Eo8i#cxI4`RoXOX|?UnCku83>^Dc{{1&7le%douYSU1LZ{ta8Z$7erlgzr2F>rN= z;?OAKsSSc39&DT=8=-mXa}nA&VfmoB==eY*fcWvYJw6^Fw@;)CMD?hG2j|IyoZ;?e z?A)DF%Gk)N4ULgkp$FBEkNulB$!Wj?=d%weKgwRBdd(X4cVNFOCm;9I86GrhhZ#5Z z?ZeN)mCys=S(lHG2NlST^uFInk{CPH{hUM|$G$yr=O$Tj7q*cbXs6a|Tz!YlH(|#T zzEZ;(Z;j*Qe!Adm#qu@g&SK8)5#4fqf0s4GT~KJnWcBH%*}IsVQx|WN@9y3tx41HV zytW>`?yx-xhO!OY);ZF9{U*5^u1?gFZ%la+CZ3I3}U}LOIiR{pkAyk#E`_olo#K6Xbu*FIYFB zFC4;ER_KSD_jV6pEt27kY3vX=M~vy+0krA`#^J?HtS8DeHsktc(jpVqN%)AVi{#-> zW=_RbR7 zIb9@YrWeZT$VWFZ-xuw(V{PSvCCG!23GFbtm%YX=g|@4_(D}9Pwe+P(M*h4>-tr1_ z-}yf9aqBxQj?K&JBl0~eqqgeDl6|! z$7NJD%bSADQgNbP2R@Ge1ah5?^xsMNu8B*|yR_Yh2dGo+i6z_#bjhlq^@#P(Xq=VU zo#Kzt*W*bN-mt4sc1^EC?!G}Lj@v93#W%~atA~%o&j6%`!~zw4{UZeEX48gD)rxD@BT+yH%n#P zX1VQQy+6}3pb35Wvx$Vmw|ThrcNuwWFU#AG=$>xwPnS#lg3WT=g`1^rqn!s)96B-` zjT2loPp+CSl|AG0rTRIeS7Y)u>o>gsz2Ztq-mzJ}dgo?IyF8<~(m3uC^5WH^-+5GD zHFFMr@^H?^Fx(HUoF}{9;1A#rbN9Hm4%)A~X3OxN&GPnZHp^?Sd>^+qt=ok2r_q;= z(?ru3eLe7yo8^~4qKUpR{P(E_fBy$JOOJ-pZ~EQGBWZMO$VU>VM)I=nNv;rjE2BEo z+NLQT1H(7eOXV2S*Z$=)@S)8z1w0Uz-?z@-|8`)rjJopmyN^fG=)9a}Uc#dcy>GL; z3T(Vo=M3^w4>vx<;Mpq=+qoU~v1v2smcjj-?qgqZPju7>6dqmONtmw-l<1qf$!-NVg&AbTY7RL|YW*dy^+!yayAj)&}gQC`HJ zO`Hw@XU%Zj%o%B)rOg|)pSz09eZ>~a$i6=ZEez2ATDJ?i>vP%n3e8<;gW9j^+D+8R z$kUtUo!{Cl@mAYjAGh*f?6K^d_Zjy_1ZP<8yn~JEZ^3aFwk}GS%~@>n1a#_ngRY-< zJASZPj{f0h+3)iAal5DS9>|X9o@V9*{LIvUZ(^yhgEJ|j5 zq5HUZA323S-l*DVm~_ZkWlmB$fxBI~K5pfnRzJ3Ghwo3lr6wODSQ zTmTQgQ1JUa43N2F=GcLZveKs%SE(P5+y zmeB{Q!x$W#CkHume4KB0($D6d96cu(np7xLbxB#ij5)B`_KS}jzoqG{kA{?$F{zy; z@0}iUcQtwrY)s0MbxC>A>-H{`Ij**$31owQTy!@Dusr5{;*O ziyNzWJSpb@MIW^5FoJ9Q7|+ykNx2QMJ|FQn>)}R5fM1E|E!e`iy_4abL?4EHuF|+h z9S6p96?X>qT^IDoygOWtLld3sTkn*ueBbicE8wkbj>z+kXc|Mq=gX$aQfXqmDmNJ4 zOJ;|%eDDeE4GH+*V`lKdz0kMXWAOvr_d4pl0pH`th?Qnq`lsK6rRrNl-@ia67E0ut z4vOVF$|b%#DfeHJG&Zl+*L9ubv?Xj_8SR7Bb9o?r9lgjUnb=#U^L9f!wnza z$N3w7Sw=pNY+-)d%2%cald|L8Ntrh3*k}1>-bUuE=YKPK*t1{CoJrvu!gm3N_9f*H zz{Ym%2lC)s_$IXf&HCA&C$;eUM*r2w2Q4kj+>n%0-kX%`OdhN+){UOW{cz*2AyFaa z_~Mu|VEb}V9DPW`zulOW6K+aM>|)2iMR3-7UYy|eV!53;{GkMQq0m3hrBlW((wuvA z{*}#`e>w-W%wX|sS$xphwvJK<<3Ez~6gu=}eaKKbU-#b1m;gN;+Al@6U-&M3*YkJe zyQ2ZUA4Fvh~2L^3!^>RMhg>&d?z|?f4> zjkCiE;eAf8p-H-*=^Go&o2ASf=Z|pI?ho^1_(w_k5%6pe<7jA2k->jU*p!CRZ~EQG z{WO**=54{lmM2bWKd;5MG=W@m61mEAN%^0iekxqmv%OQ9oGFh}V*`7kFZu zZCeCCIVLAhFOV+oJDSI1vH{z^72JC*fi}nb)Q*X_tNbeZ18szR(i4vn=Fyv z?cO4<06iMU_-mSM9B@CM+V#AP{3J3dCmSe^Tl#kv@fu>-Zm{pFkHf)TTVxE_;fTiIhrbN=WJPma!=zTF(VWQ*JaJmk{)cyME}+z9P=dN5g!_T~-bzEc0Z7q|7X zx<%01-IS)ILzAz8Vm&J_@4tyEs7;{J6aP%BGnmJa({8T&t zSbB@B2hMW&`gqVVTN<9M$QXa;Df;JxA~^wCu!261QI6hePwm+vi>}xrx4HB_uJ(%6 zhtS0vKuQFss`Q{I>}T?sO+EuxZILekSSKr=3pZ2ewGfty^T{>)l)#<17K*4D@Iib;-v^{WL0L7{j(8&AjGZ6~CUf2VAFX zPv_%wiNSwH*ljL9{qEy_8Y44%a?V7kCu#J~7=yaLa+$CFF;2g}cZ<9om^AqnS=vju zkuwo5`kk}2A7Ay@^72c)bBlZ#_*eNwzjL9FT@J8Bys`e-KC0w+=d=uhDze9ih_$%@8nwQ_iySK=3`~G!)(eLbcUVN+bgsoCv zF*;Ak$I3jNC$;%Sp1&H}wmLCaR&S^sFk=Y)AN}wa`3I0X&CUrQw|ed6lJBQS=W>$y z^MAcPxJ$p=H8A0?fnLJRT%WFxsZVZ^EeE&AGp_6?u5>pVM|lhUVon*qC1j-aP&uLD z^T*MfADf5Y1Nck$_|$z{YjV`xw48qC$)~r->A;@PzH`DeGtr4Mb92V7bo4+;V?@*8b?dY05bzD4!`lN#6bM}fiLPuNQ? zy?*y`KTU9VsoV|SxQ#LYAoQs!VPwP;dSp2gQGZxABw=a@SC);<- z75_ZH*PoKZKh5ug*XQsn`F+^K-+C&32Trr!N8htZF1>J(H11v`^8x+Say0xP__BdT zG7Ip-ZwJ4B?;^Pc@WWSMO`3NvlJ^5)xO``kTz3on(*ai>@bmb6#fNkF*Z6(PM=UapjPyPvS$^YEp@P;q`f;Y&Y%i-&PN%_AepQ2e(1feKg z4xjwGDtXEGzqB=;tq# zm3ykEDksW~CYqT`@Sa0o-NL;Z>$uO(e;@Z`+SbN~+XHKJ!rDm}OZ~T@hrobK>*JOt z&h%Xt(nMQ6Ix7EU{S|DLsqb1|)yMT7P2a9Gw+xOqNYR%K%Q&mSpQvt75q3xug?r&t3qm*Ut*j#(dw@M1g zw%5b;KC?c7zrF)esbAP$BR|4!8aaJRUnerMEO?M&_BQRyOwCrQsNE`0xcd6I`Ym6A zJke3&R7leXwJ*$FPC2w3AGu4m%GZHcH4n!pDPB`Y-e=l=$jALOcFZc|U)g6Fx=>PP z=d=4ivc62-U0No;2lTt*i(+N+P9VhJSzacUODvu`4*$fP=Hm;qU5@SFD#s?a$g%j_ z&syj>dOaGreTF%j+O$=Eo!pw8qY>O2pVaHO$}kX)kB?I|Qy;m~)+6?gGTCubnVjCl znCVCUw7wdCA7KYu@$;d9{Dt9tZDsQM?lKuRp}Fv{6V`az%<%gOTYb*V@Dal1zjbE0 zLxj!VIWzqIgx$S+W_^XoJ6@iO@UZBQ`%4}Qs2v~{nC^ZODHzx&!UdG5O0 z_u}iz|`{%F8_}jM1tw1>DK5p)=4`e0b z*}XVPyUhBa?*=a1DlY-?v+eru@n9Lc_gfcD8Eq!-92eBVkEgi<>z@l>&i!hFccrEl zPt;_pMuRHey5-(ieT7x^&tktV!1uD7%L(2L7}+Wx1;RT`A2%|Pm$UT4(g|J1=~@~3 z{8sq~FyZPM!OgiEIs#9dd3vicsicY&e%`4%5os|#T3C^oPnQhm79Suj*r`Wp=$0}u-D16)#1H+ z^rvg32Kj0YG_hpB@^?ewm?G;mr#|#0f_D5jx689(9pL9wwi*rRoa4m{b{5G__A`6u>uj~ueuFU8KjJGk-vKJf-BIan_M6lb8f@`^;BpL9=u_Wyn#N6zPlLF#~U^8W}3SR-iSZK z-I(r^cQS@~x^L#aP2)T7P(h~Q=mp3n@RL5tdkDvJ=&%CcHpcx+xe7_`)Pub*;0a? zMoHf+GdB&5g9aqmwaYcYy)F+QkF3f3ZZkJq)!F5nrL*2jZJd`d50GF3ZK zovF-vs-hqDj^64MWGR=SdE<+uzKK2pj(Ll1PZVc;+0 z)i^v~|56$0ZkIcI+GWb+=i{b7%FE?vzbG?s@P*vC z3=%&3McM&;9SFxu!%O~HCZ7ZvUyg=n{svF8GG2ZVO4 zKAx2&jUr1)+4>k+lGX=)BXw1~d>Tmaq(2sOewyU|avWbM$d)wxAHXg8jegC?{j^rs zE$1IV*SeNt#^?aDThGT@wtQrD$?MzY8^E-dF}G0WPDAVS!^y{wXX#6xj*p`+M#o3* z!~4(?RQnWn2VnI5*<oaI%C(oHR#HnnrJL zoIIgV$=loIVW6g;`YIiQe^R{pj&}TbxUk7Z2EUE44h^Hv^t+Eo(rBN0`5xhIzA3#E zusl9`VIOXn!?(4|-7aq*4{DUBgP(&h3wb(wr)zDpvie~3X;vRhZG*5?P&DyVY^Vow+meSi7`+zFl5>n;knJ zH~uWf7g(On-YnSnZpN%W-N2XH9(=!4}2vpR8x|25^)w*yrj@>5{arT1~8*Bs2$#SSi; zCzp}-?dh28?8D#OLA?Q^US>YCN38CUMQb{oO#*XM_l-yx`-YF3baQ25MTd;8>~J;; znl3+#^N1hE%yI4=7I(;DVE6(%wmzPEK3~2&wtze5N~wBo zj?QFGue8OiWyY5})F0I${{!UKvhD}b@ZgLhIfMJ18up3s?akm%^W;zDKjY3;>pfX0 z8R?LxgAO_OBIb?jyNSQCpZ^_t`SuI2ja7RFXV^ zzsYDEL-X?b!IX>qerS7#{P^S!dCBGF<;Ir5#A$pT8BIgtbDtcuj7>; z#=V{wCu>(Y;msHH%u=xqnE-Z&`Q(R{aQ1<|sZOpR*Xje7sP0@=AJFPIu9y6GmQw*^ zs&r@aM5&+CA&&qVEzj`KCmDS9T-tByfctU2`?#OR$beqX%7Bb5obncX83Vf)F6NDf z4w+NjA&HCa*hF#dt7shK3+RCF3uu94&Z2M6?vVW^57MNgVZm9Yau#EJ6g11dbDrfb ztPL%8?s%5WT`VP@X2-z|mSm^a?=WnyIu=m_rd^)B&+ zenp3T9N4(qw%f;}z8$$M^?f_)evNO}8f4Bj_`Nc8&hQmAGI4E(9D6$koN%A?o!j`htUu(j`d^9+qV5jc$>M8H(@{BA#3mJ zkj6`GANaVvFXFC<`mfw!?u#<26=K?e-az~l)c>9i>33-(xT!C8ZbQ&tg{v%$_i_7f z>G9a^9i#jzH%c^z^=NdbJLbT9mdc_%)@D`dL-libi^&-7KYQ=NG2Q9ms0~ZCWIoCK zILMlCb@FkwRWZE4gz@*3mCGeHk1}{j#z1Y@20z94-U|)5%=U?o*RIB=EBf9w!Fmbn zt2D~mUh=kDPS@J(t=gVZ{eJvBY%qI$|I22-((eNdW9`w%v9PgU$~sa%t@@6zejBE4 zwd+aSe=K)O$B@TrF;XG-z220qX_2MzM#$1&aW?I!rbT~eanL5dKEdOpY3Rjo$gVos z$lGS?CwaGO96#w}ol?J{QwD*?0o!&TH!|?$N05Op!v-QaO7g!1CVbJ%@HM<2KDkuZ zr0aN3dQYyzEv5Sihi>?{f+4KA6b|3MQyK|Q-1fhZoBn??zn3X<1v*y2 z8kG%Alx1RB51>}2!F}7I+?_t%h%bH43W;(lf7$9l4rmyD3(FaYa@rm0qz`NOS>@7w z=Nj3xzfn%uyH<|fwGP^x!uI#fBkGi=bS@hk;^Wxcj>UFj^$gnyGiQ(Gz9bkAoUKD{ zEpWs&dTir|gQBtT1<9UHIc{60jP9X7%%1<re|i? z>#)`_4oysKWG<~gayxWg9S^UVzKC_Vi*?tZT~{@;_|`gK*6%Hs)w?RN``N(!UuW08 zN5@P%SE>(ziW&BnwHxu3yo+-=YkGOG{D^g!(*8H~Tt}Sxe;FsJ#1|R7VAP8)X^)#r z-QGamP8D|hEPd56GJTou6S<&MwgD^Cwl96$^TRR0OU0&Tmi8}{-pe}WcA(#-i{cc( zxh@iB#x5ow9q5#wT;3^nn{>pRj)vL$6Kt1retEKVdYJw&^`1nB|N2gOAMi|AZx0W! z2R{ax(=mIFnp!%sBvU(DJ)jDsSwR0hdP<*M5n{vH7k)VtaKTwCz1shCbLSy+fVyR9H6;53Ved zE4i~d4_>64JssZ$c8})%E%V_{dBbg;5uZQNFwS&doS>e!tL&R!qn2YqzgGK)GxqRD zI%Uo6opRPYZ2$PU*N%yQ$-|Ftl+<0FG7b#6Jfb-LlNZPA+3W)~>;pz;8e*k1`7E6a zs{64YndRQO=(u3#^YKpkk56>Ui!N^;4-Oa0VeW_?LylYBmwlfsRm+`8E&4W*eH$XF zWhh-VZD%eGf3j0H9_*B!t6bY7IQ7npW8Z|R6zrWczPxfU%yYV2GN100_UlHzbo6vtxR|A5$}xRTd3o1KTdB=gfwx#?%DAy>aBuJbS&$MOKk`}X8`0F{~BK3E`ioXxX77R{KI%FuJ2 z@(Pf=#`Zx3H~q8#pX!}*<_n#&_Zlac^Y8$9LO(pvTNB1-##CXZV6>rO4n8vr(UVYJ zYh+`SozhI2yImPR9(=4wKGq+Tn>csyhWC_eZU(D($7?6&!A$7&H|!Ja&tB@3NnlFz z()vx#G5EUQbxPs2whj8-$Ne#X?A}E*r#eR?$FQM)g*EYNr(8$5M*eaL$}(#D-sx^)fn~gIz z$brA{r%w4Tu*>A3cNl8J#d|@Kypg48IBAT(%^BY%5lmw#iP0VQEU6O zOzdp8>pTQC!BER3XCx_p`@3XGR z;dk-7ES4Hs{^DNVdDKGr({ePt`szyg@wGF<>#wVnFTZPM zxC~axulLOizxX|sG6Cf0|F6P#y^nGMKfbp6m0K$1=N~}V^Z%=E=>Ly<@$lYP`{Ca| zQYrV{St-w$-pTdPKL{%su9Uq@Mg0r=?Ja~o@M(M>=7sm)kN?Ea%*^Nggx&PW%zXZf zuwu#&^D%E{L0_sj7%Dno{636ftA>16?Gs}QyJSC5^DavlqB!y;;u=3b`Ehl9!C%E= zU9uan_F+nI^TIS^nB6q`+yNshSDAA6yKxa^f_UgZ#Ez1m0woC9^D78*Udgu%^u|DLa#Z`?8$O^ zW^Xq8D)%Av$9Bo}K;qrnKFXL823_&u1V&B%-|Mklt>dEx^jn-e`ydGN z`KT!^Ti+-jM~yyF91LCDC9&OIQuiL)1|PR?AmbMUzHa6l$h=>2WtR*ADVNsA&3(x} zV{-xrr)BEcER=;~+)FVwsdseAjlkV5Z3H)Tfcu!My5yrk=(pa-jV?ZGckv#hBQk3A z2uwQU|D;*Jw@Y4gc}H-yX<}Y4W{xZzw{@w%x=XeL;XH}p`SrerdIQ;dd$^SqV2`*V zH?PfIEBuamlVV?&+yM;TVEek)$4%Y2Pyaxdl-=4Tt!^&*xbK5Ksbj3~@f@~#U@358 zE0W3ShK_VO<@m^gI#h7Q2$=H&hx_T`D2-X{>Yy5Gn8Y`X-g&b zV3$;Xrc2H;`EXz6;dcIWPmq&gWaqz<7L&(hyCfg#lAi*1yF8*e5%c2MHIa9(>(<1m z_Q6|<sW=?;tOa2brY4W4bJlwn+!M@465%J)PBDn(E zR0H2_bXFO^K;N*)`JPIZ_VVtMo|)5SGV%Q`>G=U`#pJ8BJ3maKaVpdgY>p=w{8^Vg z3WRSZL~(cm;)Xnd|IN-Ze4-~jpYqf>^L&?l>Q`NI!~5-AkKj7j`_Q?a-7Q}O&gyr2 zcz&2!6LaJ*#3`H8El<0=eBA27aKD$}es71lCm%I?1-b`Azv+_y1q%052UBLT!8iXF z-bcfjFZ$ibBWZNJ$w$w-ez@_Iif)2>!wmN=^PVXCeL248i~5kw{k}_@fW5AqD6aj9 z?hBuJ58cLgB&3KN|$VX zmA0FFbvqNI3VL9N8`JWGgRVr6ek3H!Uc^h=V_}|M|Z_M_MSM0+2O5rI=xMy?ngVBF7QMrOUHK=Hqx*e#P9Mji6;NE)GU z$xp`C6bN}rex7;<+HdF3(1vdLED+wa`*^TQ`(q{jv4Z|sPJh%z`orpSlu5oHt3m2# z>OH+!2D`iE+MaH?`xaa82(EJ<`O#o=w|o>RdIlP~xllHOpohJ6xvR?})+`daZ{ z15+-)C=Tr)Z6qCa@$)xpiE+VKUMl3blV^3yexUaQwvG|p)DeI1r*=y-V9$A+5j@=Y zU*D^3H+4mBdPcW=3h>Ww(J=N#FOKz<^pJ#hBuVt%8;&lLqx(l>>Evf5mi{bs_j3|E zy<2*Kmt1|LIAc#-A+C^4^5X0J*GusmvK0Nnr3w7}9gdkbyo-99bHE1t5oU58EKFNC zpVhy)Th0M?-)j3Pg1hz(Uf3;90Hr%~=haBqyh53m7HC%i@2b(~z_9UMsCCTt0$;yHy-vaJaOu6-SQ~#n%2jZUu5u?35$Ku)=|IvxSz(H!PwuzHwH9+?SlsO zNi&TPKKSQYpZaDglVqw}?gP$p`9^Rp8(u87yIWQOBUjlon~$6ManRC_BxRU4&aEz6 zDjaJwZ?Jt`J&lYR+1zY+x!7ghvH=)(<@&g>)8}rN_qHbVT%h&WJnZ~7cSBa+Q}+sF z37I|Jvh0d(i4WPn@$q0uVQ6#J+pwls)=YC}Iu5TvJ=8Cf`q&&M?do*5^qchXNyPDG zg7AxZaga@TX@aHL;P-Qf(YKa)*T`MQYKaZ#oI_Te;Es61LaX~jT_>*VmVW{huC6|A zbtczv|E_-Js>Qr}p29}?+(J1QSzgg(6*}16ayC%&A#JPjiTEq_!`zsS?(LS~YUb?q zcFcTSdGMu)Bfm@7qho0Hki(HZWPt6}_(Gk|;0yJ;tkoY%=DpDI_jThV&GoyFYdzBV znb^-B2KX{0KP+f0mPTZ->L1aZyR4kq`ZQ+_!+oobvC#x?s4kT1ariU#v58-HOWS0( z)E%&8`*=_mNEvg|=%{n{t=Kbn!mcCstY37?TY;3Oi!ry;)^CdPiIH#ggO3Mi7R#BF zbLDi}WNpyk?bSb*Tc4v}>6Y1F?Uq9AZw;G<&Vw%l##|lq@kkmSOJqHMSnaY|vJjb6 zxQ>jDpXz>1$Kd~}Wn{ct{sGi~n6~J?haPcJU!@5<=?C4C&~S4nS0##H0Gy&>v@IXk ze6nfy?&odR-OK2wjuu#1Bs}c=aeeEkLMFb&eEfE|JP?*e`HKGlcq|Nq4^sSZK*p7y zk4Mso@~+6uC`0ngpl*JdK{anxK4)~HteisIOPbV^-SRP@<2Kq`seW^zIjo-|){BOp z|MhO^({JRLk4MtF^)z)`w=Dlicg~J3J=frC2)oziqu+hpPh-!N6`U!{WyxV@6Q^~Z z#ykHpnHPC+jNV0ht*q-`gU^@MvM#94@h%WbrI)YLuDmksIabTW-YR}S zH0VLr!AEQ#__&pW;J@oYP7Y$_Xcf@2a^!x_udn9SSH|5{w>12&TOM+GMR3=D$!EId z62Q0f@x$ynl)Wi|pQZzDU2*Q{{U7@DY4+XQsi)?}dR4p!sM9donU6=(=(@_w$KSII zz2jb|mVT^7Co9)t+m93EZ|(cHp*Pio-c&bwQ~2Nud1u$(Qvv;bV2&KoI`-7Wjl- z7WBvmfrsuOuKEtuvsZrj!XoThdH)xl)SS)ozFQuAF+6xJJa`Q}IPboN{mTAXy9OG| z9$@bM^$ap#&+B}$^p1Yj`8V~CZW;V1bns4FZy&dN-Ap|>T_Y*Y$H4}550{v_o>kAWeIeYHsCW^ZB&s<*7b2Gy~p!?%^ozcum^Rb z9?7^mMsPE)*^3tS$VOn`Gmgh(uZf0nAL++&>4peKqf^&bPfEwSB7beB4iK-tOL+uery1sMoXNzmPw3hd#KnN1g{JTp2z- zLvJ_Z`FUYIkJR@_Lqm_$-DT?+!Ck+^8++suAk^E9;2H<{oRCjDPe8pN3)zPv}C1cqJt5!{uZq3ro5Eh zs7H3Zy+@w8MC-}^NVxS$n*UAD8+@CQ1|2Cs57+*|bdQ{QWsiO9iE@2BScjhcu36BH z1<;M$+cMTZ1sfpN_VBhI`3Yd^rFl}W;x}z)PJYaeO%&JqSy`l?*1bhERgj_W=a|&i+P8xP);73&AV#wX}TWX!FU0scWd6<+w)!ct~O}qopRFYdxFt;>;ZXcb8o|! zL3amUF&Ye!$4qM@=0$7ma+ZM}Bd4k6h>SjN;Te zFHWs_o9I#*=zj+~v6qQ22TG~#kIoJDnUULjBz6a|$I-aFFyr%mtFzHrG)EROzNO45 zeH*U+qwF_8#V53#jJJ+G;X2o&-&oduT&3}DkBblY$fH2M|BGli`dnT-qd!9*E@K@m zV;w9zu*mMY%*ptB7)#&*Qzz0zaP6mP9J}Wsf9qr4Lq|J*&$Io6eC4qo`4QmD8zNz* zKj9ZX$$B^#jpv6M-ktu*>QlnECcn}nHDB$K{(I<0)un;nt9&#P?#WD};Sz}#=(%GL zp6R&5v2=kmHFJLWGd;5Wv+Q}M490$%IR^f@huH%)j5!#^sRMEB+d6sai8~`d)^qQ@ zJ#s(bpDiO{+DE$XAMcS10Y9D}7BrShW4adG;TmZ~N3-$eEG_7@Z-&&!^23q4r{3CQ zRrmXD;p8!3J?hzYKgyIeXRgVQ$<#L)oB!#NCx&US;q~t___>5V6NZg_S``2D)9@V{ zMqBf7%_EzJ?|#0P4&B8(8ag5!8qoR}9uIn*z-Is3tRbNBSGxZA$Q~nk;r5+dY`dp& z@BO4G*Z9JmgqCox5p%rP(06*|1>nw4+PeF=(UZwo{iDIUDx)_OTWbFg@c*voE9Kcg z+3$+CPglwh(cRZ{iYE)IB)!Dqskc|js-vppnz+SBF3yGDcT$zSu`7rFir-JZA%_o~ zStZ*@ulY{>N0q#=yGm|lM2gDoFP-s_Q?4^h5mhtGLFL6-t?)I{|3&*eJ1>ieA}(x zC|~3GcqFaBJCRmME2@K^mv?Y!kz7h&`LYsAi_Be*Jx6e6nEDy>=jXIp%iK3d_9d)e z3Oz6Q-}G(Isvxd1DYO4+pAH1{X-xeW>)SjhNd517q!&2mUR!@34=T7Xo+ma>NmMlic zqilw4$sp+)*5VIw68p+A^hd|%(>`Px|Jx(a0lS{JysD1}+vb@!RBI1%FO=0LadU2* zGy1DN@?GGRPusrnaVzhu(7t81S~@mF9n4)McSV)f7Xy;W+&4?(7R$t}ZSs8KHW_yL z`gqV;B%R3BY7RMn7mS?g<7w`fWt;qauuUdhIv)>IUgP;=YN*vWb+My^_Nafg;i7Fa z4bhlql|uI-|*v_Gft5`@Ae@#Ua(CH7jAPl-|)vC9-LV!XHJ*MHh9U! zeWk)%q1I<4@@S*(SDW~XpI=ffWi{1~cl`l-#?wdKGkWP#Gfv2> zdzWsLdw|CG*f|%)mA}c0axk%@O{>g+;zl%0_X_S@ZAs7JBM=ae&lo7@jnJgDu5=k#!6`vO1j>3j8t@1rSSmR!C~z7F)c zv=Lm#1b!fM(l#mGxGnqUm5>v;EUW@>XO8Z%i*z8KIthQpN|Uria%YB<+_0;j^cgjsg7-OeCIal|BUU|D6acmEwpAa^KA)xE^k_R@yXJx zGg(zF&o8c)YwD_veUBf0kgz?=ju1}RACC~;byT(NtFIP4ulf0Wov^nokA{z~td?kdM__c-qR*JD4}C`NAR_JMls zUwz;FIlC{UDA&GoRn7SZel1Zcs}5&*X>%8wi^JImdE_eOk*jk2wuv*K`K(i$d~8^e z3mP9fB-A}WyC%8+kn^`m8mN27j+c*H8F>>j@{P#IPeMi>&&d{D{gr>vKkc8P6RR!F zV;>o~Zkzn&o!hehStGde((DWB<96r<<|YvO>h$q2-`M%pa?8eQ*|Ob^gW@mo`@C~= z_=9iOwpd(#UM)Ahty;Q=a`<6>*WHoBf57iGUvl_FwS0l!uluRRr~bmc_(iq+c`}DT z@O-uO{W^zd_`UFtIs7hu|Cn^z55w&>>>Jf`#=@E$9;=ZLH{|gB%WGu3HHU9&tC1nn zY5IZxs*#(zYUKJ$b9m)tHS*Y1IsDAMHPZ7@hd)&#Kj8NV|Dy(Z32%x#SCT4bd>W1` zlHHCEeNYuh)pF`>Xy9xa-oH(r0-n~i z+lt}M0!fS&V6QQk{NZsEh35NTh%>HnaI9T8O&Q>`Zr&y@hGpjAnrAkRju&`XPOx;A zEPXCEurN+NmhqM!{ZLE)RM3wL>BnN|zuvv~9^59^1HGTq{zC8E!)uR%pTci-=1h zf9N;JzGJu?USaVJULnvv8(S!A(hKm{Fdu&n;Ct-rjvthaC4E| ztZk*=Yw34=pU}{tN&I`YY?sZg+oj`CTL&MvzUZqhzndyBZPGPlS}v_^6?;9BuVCOEi&v{?h(y9j3(V& z89jeHXP50FpSNQd!CkwD-?m-80@yPadx3|0a$hTJp`7{)w#)gzxtgcuflOTSG_cE+ z6UEs}kCcu+AN~Ms2mJG$A7yuastKh5Ve zpX>f!_ce1}*Ua2=&pr3tbJH&BLH|R%EQ9*LS8NSpH%;iif$F~95w&^eSoI&v4^uZ{ zEn0JE9QV@5)knj!R?fcv_zwCZL|e{L2Y2riYuh5nSe^22JaPA2bq`|N*yCZ-9>bgG zs>z7*EU%P@jZ7BjpFy;3*2SU2xSz>b^mo`tr`S-a&kxGU{tfoI0?!kjL(m2q)c7r> zHo*3@5Z9%?R=1R{Rq}Mdg?n1+g}Lfk#P~KTPZ#U?re)^s8rqQlul?>Y=G`#ggnMWH zvAL@0$8*&hotFJk82uIIoC4?c`#wCEj4sW40`p4_5it z=c+&b1@{1xzl-IW{Ak=~CzrkMW3bctzO|tLcdnnQB{TB8uZVxvyZ2>$1|n%4Pit{z02)=DUf>#6_4m1I zIHJ9_JWPMkPv`$NSN#D|uV2yETVIX;4&Iy}O4;$ei+iR)dml7Uofn>`RxUT=D~yYL z9_C728T;J^`@TN&)ISmJ-pekQd%`B%6K*ZrHVS-KrR~NTuW_Eb4AGqzba{GQ`iL1v z>-wz2UhDHz-{JGr%m?6W6aKTd8{f??=UxSaajgc<8$HqLd1?isEms$Zmf<@H%uhtH zziF2NZ7cD>do-!CWo6*sP^Q!8+tBwO%JfxCXmjI-9T z-OR65^RXVW5%U|3Z{qs1>t5@tRQ)6PGAWL-I0paJ+>8IS@9eK8;Q4I~@@(LHw-)U4 z6Pl;Ki#X&#)+_H_7|TOW|1%GA{(0P&aL(sp&cn&0@r!lpi#tcDPqj4Tz2@j1`*-AF zv)r37W;uGE`T^pig50Y;Y|Hi3dFnz$xBj9Y592@=vkzD<{cYm3dFnHWqpoBAXcXYH zuXXvMbpzEpJSSX_aqb$7-B;rLCp!n=f2?(C(7IkpxfTagY(~TWKu3RGT{eNK8RMAhmA}I=O1=tJZxm556x5a z5p6ymHZnP!f60;Yu#t)X2<3xl^YO5eiR4f|h*rkKMy81K^$(Y1JZ$a3`Ij7-oP+h= z_P5(FbI_-9Jc#vYHOm`R{Hb~BI>fz?@Oovx*MR3Q>_Or3xt0liJ@08xfuBbl^{A2O zJ)j34^LuW3Z6o$(e`cQgHlqC|)5Da(^Frb0^VG=a=6P$iJRaBmc4BPOLze4G&=KLB zD<3+oMxBQ1eFW~sBRb`KUu;g<6$Ec zR;_9pqHQA{HZmEUf7p@nu#t&|TGf0+n~#T$Ob+K?a%4PgWa7PA)y0T59}gRu0?vo3 zN-`ccGD)1j!IAN>kx|vHn5Qn~<6$F{#`(>TjE9X(q<5=23DMf@VIz~p`DYv%4;z_S zpH_7~qRq#{MkbH*Z#Xg@HZqC6t?C*?n~#T$OcCenYf3U6HZm!k|Ar&uVIvdnhxUVL zb$QsxWN`jrN5;cOCR&U3gJ|>du#w5({7a6EhmB0UKiUtX&Bwz=CS8X*MYJ*=HZqX` zs8d8M<6$F{#rbC(84nwo*g(`NqRq#{MkbH*Z#Xg@HZqAps8d9nkB5y+5$Ef}B^eJJ znH0`{!;$f@kqOtMP7$px4;z^b&OhwPc-Y892cu3AZ9X10GC7=o$&vA}k%>2;P7!TB z9yT%soDU5t$#~evBys)*N5;cOMh!)ufM|7j*vO=DezPOvVIvb6hW3MK^YO5e$>RJo zj*N$mOl&yX52DS-!$u~L^KUpZ9=7(3hCPTjpNNaCJ>Wg#$Yfn??HL1m5N$p&7h8M4 zd&7~*yV%Gi4n=!LwE4JL)+gina7llxPsTof%jyf}S*H-(FSGku2hUEasjceNBU-Vx zl=nnDBlh4aPe!i`-QvHW>z>El-e2X9Y*p`zwyG@iqum&f5TAg!L+emIu$v~N@BKAu zz_s>SvsxvOYE@rAlsR_Ti2J(F!#ih3M%LWpKNv0g`^=<_IsE-(v~76SOSQGCUm(h} z3G(j2ga57!eZuouxT95_hG@Sl@vyEhypvecs(yv&e(&b-j9hM6t9ljDm2-LWT^#8`UV*cXLHwPEG|0~7!M0+u3l4@0Zu4z>d&@Sr0TuJfTR&~T@T2*zk zX>S3Z-nXcw1K;6cJ$v_GH82du^RfPq)yXyZ4uoq;QMWBvA2J=^VjWejjzXPq&m9@- zVa&O%RrR~kFH@H%|7WuM@yb6pLu31@vA64eGxGy;{L2B_p#C-tV{OcbCcfFKb|bER zTFTkQ@{bDaInaqc2QW9oeFs8^V{e0J{hcDUeLDxJ+`X;pj{DGlke9q0AB%U}5xmn7IOokQTQk8V*I(4>%pS1?Xntm+1_f^yc2u*Z^wE9%zeb~X;qga zPWhSG=wZ{|!Vk5o$%uCT-^JZ~e&z5knf~kY#=3p9p`km&cviwq+k^czu&*L3{E6=up=M(iP?sJIxdp+_nr$xLGv1n`$VlNG!jgUtFJIu|?`uI3} zMC|s_!Lq;32!2abkd=N?#u?7PXj>vG{3Nbj#N~M@M-QW{x9=Q=e_CP94(iN3C;R3$ zD|d#8^%vpXJl84j#Jv6Xs0!y>)uv}#Ro>?BVCl>8pY$bRd~bqpPPUkDO;EPUU$&}O z5QjV?cDY#g)oKU@|F}o}DO8cYHexTfst+LAvT?C|FC12fv|x?@I{89W_Fl#{!o8Q} zTL-)$kupo!GQ&UF^1o}vf0;@h|AZimhtmvnU_k4>f391TRJ&((t^C zy)@R&eXtX;+fE0|_d8SZ9%>5SLmiH}Y-cS?64$BTR|b2^bYf2#yvrJoclX`bGtXaL ztFG?E9=!{?`;P2`oU;JoBAo@K4Y(kO?{<@x2Zc3ZJBwPGPpm) z4{1{$LbUVzE|xv38)eQrUt0g0f&bDcj8HkGoj(d?yi>}}$Mi8E!}f=!jO zG`_PTG`?kUXnd$HT7knSCF{NhCFGKQuwb`<_4zV{2E@bc@h7vGJc z$ow|75^?);Qid*WJiIsFYpxC9OENzX?hk@IB0H}Ojo5x8@>++yZU}|j+Eg5|?iZ4m ziyJ3n-TXS9^011Y-KK6tTxim{SoSDdr{Cr2J_b!%*Z=aHROXyE_5KgE zskBMw;>IIzZ*Cb78WpMu4N8drQTDlP1Iz0|xz0BASHvAAt&1D6&T&lW{rtB@_g5R# zo#Q=2@AYvU*4><}vNPJ$iSKJu)xQ*fJ*?}rugWiNQ^#F|J|GR5nrhrvalPXGp~pA% zpHH@_KOoxc!Ns9z)oPkMro#Mx_>wkt1>(ZHWDM!z#;??>uk6IP`^#jE>aO35qU=NC zv1S9$CgVFnF)lajH?SWf|L279#RC6rzwW=FKlAA}buXf|(ZloucI8rS>WFJfcDY#Z zm(W>RgP)~045+C7t8TzamQ=MGz!nOvLt zJ)-Ly@oR_=JTJZlagQ|ct?+Q0iab*C&BdXUYSl?QtJTcqb*csBi?S~A4YAmO@5!HP zQ}s``sfoWf<+~kw00NIhjFAT)gV;?Y`%U$iz5eihlg<~{R{Cdc>P5sgHeb9?C;ltq z29s|PdujM><6f*4MY`;>ZR$^mOOB#F94p{mbq_w)>A7;O)7@Ct@as0!=Y=-ab)ob< z9;OWXid+GG<4d@vE*BXO>vq@|-xIc}QNL{~J!|6~g~u~(s0%WeBCdQv%Ff4p_Aq-% zI{7t5Yt>kcL&su$(pWq%j(t{-@ASLpgww`ie?UKqXxo^Fjh)#&xF%nPzvr9!?ChiQ zjz6}k@NdK>o_DdEMxM>_?I5npL#ONi>vF6p^|~E<6u;S~{(-pAkZt!EnE*We@Z1jLQxQEoZbDF9DH+-C9)VlNHK#m!g#8;NItb+Y!> z{v{){x>l{;IZ$2IIb02W(>%E)%=7;CK`QyLHr1ip)x;O2Y&=Z6P=1A~cD1>8d-uPH zJxrOFKKO5DySfk2or`gKp?NhJdzYC@!aX)#*RHNYERClEJnF#xc+`M)6+zr(Z1pkP z7V^^H)Oq>g9iEG=y@T7;FA$|Iac&GgxICjXHlkgvLX^E4F^}V7lUEVEsf{)-e81{o zJuh&(-q9hc*R2olgEi~eV*}4>HF#DlAl>AV?P}9+rTkqi|NR?}?}wW396Uz3-wzc~ z|9YM3I^CZo$1-0$*AK$;5%=XQPHIF6KY zCGnW)?J92a3Sut}`zNH~xA87Nr1$UCb4|(6SYGe=-wL1QVC&d*a=pv54ZdwDnrE9R zvch;S17GEN6?@1o!5*@mV^!`r)XDqX)lOrRi{+VDe}iAJ-(sYg#}Ir^x18mEh)T?C zSHD6W^^%m2hfUoVk8f8qPH6Y$^?V-c+L4iOeviR7zfmPS_>2AgRw{H{tvU{ShfPPF zPi_h0oh|;q_iUde_nRCXnx@=wALWJL;PJH&x=wJvJ-c0vM6_$gJZ$XG<9y>n-+rHm zwP=ov*gppLV~!_T`d?fYW!E?Z|7=`x0p=E#V14YO(s$QpERe?~r2iqv{|E98n-Jf% z&3rD!{6rZ2JD*GAA8A+H5!b&gW$)t9v|2R{_qHjR-)t_8j}oD^HEJ#TBE7eHiB-s@7Yzu$}X0BBdqi`&)h%h3LRhj~K1N7-1+jgIIsH>!Qp=SSoGkRIpL^nF5K zH3VtVDw9~Z)IEoz)9Q0WdYseg@ZD)c3)Y>Xp4pBQ%&WPtlyAX)Rq3>G&U5X>cd+QI z3)i%(4_}Ku7xr@u;$rzOvq9NeIQ_f@8F}6wjQ`!XtD&pf)qa!K!=`OSSGTLn5#2d! zpNBPOj!ffJ?tykJ=C_W)9%xbNixN)zzO|3K71y->uO$4{wxAx=TI_RheY;BUh9A85 z;Tj;`iI^b|cK5(e8mYTOP&eiuZBDyPA*r<4MwBV8>%ckPf8oB7zO`Nb4AJ$~Q2P9m&iEC#WF4!f^h-0XHU3my;mAQ!Vw!D&YD>ZAwTW$eR#m}9LTe5}iJWb*&ruKK*?r}KHZ zA2~AeZfFqR4GqM*A&ghng_F8mch_O9bcgyv-ww4~+kpPj!SXG}KztW8fNR4GI!z1q zIq27+&OsdYs)4|3_U5EM}qP5Y(MkYV7Lw#^i zNyfuQCKtvCy}l&lVQnLx5eIju-y_bPV0{bn@O4|U+kNL`{0Vh*gk4dOXI+t{IALEQ64$6t>JyIpMj z%^cF9eu3zw^LeOCSH`9r-JzaCbjvB@@sQ5NCSB^#4s{Qro6hGc*bbSH`4M<2uwah;BNchYQ=4vHmroToAo-@p$mh#U@>HLWlYmqMOd=VU2+!BlU^8 zL>t2QmW8orRI4*EU&8&hk`s{^;9@@PtW70*AM7u|H)A>BKdsjx6Z;i@EaeX4n_X1+4&qF(R zWlXy8Q61_OL^qw!Q_90mnWc{Iz&8p#%gpDCEj|xz*-h)@8J^LhPDKpXgU^>deID#| z)0*Hcu<(WIaL;V%eEl;0^ag{4$(nVq& z>P$p8ozFwPJ2LX^seA_|_bv3bvpUp+h`auR>q5VqFyD#0d^A^2PV2|F_Om-w8)7i6 z$46QhJ2oU_9Md1)0C%Y0ATBBz8_);yIp5`TH(K)zRA{ML-xF_&?d5@2LT&(k1;^&h+y+gf-IPneR3+F3%PjUJ5#l@yP6Z1OM z^@zdp^!P~YVUxDligIY{nbza899%h5hN<=r^*!E_MhvF)_(qR6 zJ#6eRehAk^!YMa%J$ihk^{`1BJs<4^vAfJoT91#kE|xw4d%G;?Yn}}-##r2;Zbh8= zSKB9;v4_h?KAxQMJ@?@b^*UlOt;a`N51X`!3(%h+2FuOkBdv!`+U!TrCnE;adVHky zuqijy)uE;$2FuOkBdv!`+Sr91>LSEoT91#U9yT_oK88L4F<4d}A89>o(&j&oYXmWv z*5f0shfUh#MIGwvh{3Y*_(qR6J*?AWo4_TQFdJZxmbziU^wBJMVGNgg&b#Xq#GukI@V%=GDNqGd>;BuSBB{@2bC?ht5*@-GV*ySTUW;Di@w>eK7#1#^Le;8 zx-v#z=0EX%4AIr+^U$VU8Ky&>ME~Bd9zwKb;9<%v$A4hI+M#Yi41Zka*ExjlHOcUMN26~1S`1^p?aH;?P`j9m2VxK|*$avsmfwbJR=v`h_Mf%E9dbjw*=$KM?2JJ#3^BEH!kKoE$+LD z^=0|e%0)Bp&i5nwJ=qZ|zP&@K$2!ylZ%H05mOQ4oYt*84{b=0gvHcj8_;rVR6%hkD z-F{sx{~di;>HVL~+VDbeqrYW`iu}GqeHn2!(+;av!*>4&>mqZS_XPNh$fvD)A5z3G zAtsHUAZ9+@X<&_;cjFO#Q6AIncLfRS#~SNL%W*3GYKN-*V~2XuI-^g*hbHWIgmojMur^`HPOQztcQL8ctjtQ~~vML}ec@OW-JHx!WK4uBm$Ba_hOVB?pkK?_s z_~T=?6aGIuAg9|1_HtYnSH~ij_WG*P_zLh^`bvI0@8X_m@D1$6arI3^y9Ud}V*hAm z_rouhO(VW#8;Le{h{{|PSCc*wR~hQm-+PR}9a-OAs>Z&d^whPNya@Fx~5iL)5(AEVNWhxd-(5e5iQ!hZ^t^4Poo|YcXi?3 z$#TR!k2r?dRU>5<#68mBUX-~yuI@#g&Alp_&)#Z{9{?}Qe7Kj@ZrrzUPb2R)h}%v6 zLCk!*)1iIz$Q$?f7-T+-DEEAfu^k**Ri{=#*VWtmt1GZh3u_>XW}n@7=wmh5539_2 zRq&EujH?$A?K*i6>$1WB0n=z-i27e$&R#DrU;m@A!gn9~+_OEu2}!`u(BwLN^NMwZ zorAEJaG;vJY;^IELSue-ZfH`kwMW^RZ@3e>jF)2_`1ZIO_gGwws6`pm#@&52UJTwu z@{ljjyVy&^bw)_TdQU$YS1X<}Z9(B$1E1?|JwA1G_EqV8T>b6YxaxdT#zQWy@Q*`d zGv*Y_d)vN6eoJs3qy)LG-Ct^bXKY}{3#xncIxT^b8TO`(Ru_jxR;!V3%5I`#53f~+@5NrDc-9}bbAYOa?_6&j z`*U1fjkwgLcd@Q#tapyI)T_w4(kd&h8*2p9ugBHPh#c{JZ#!#x_Z7kqxXEZbyUQcZfQvCE44Zz;#X4{7%YgH0+5GN* z^txES4LwZRZ{Im?)%PIu!^unLtM4FMyFG03jxV3Du1B=`J#1uRm*QJ}MEj3m4;%j@ zm*ILwEIuq{Rd!?kB3b@YQ=nY9HK2p4;ymvMu+ zH@eu^Q@CQjI^@cdJsvjpEDVNb;|uWhH{hp_Mv6(+XbHI ze{I&4R@ie)HV1rJzmES25cKy?6*=Njv4F0JpvzhSCsUapQ}HYE{?Q&)HdbPYq< zb@fsM7Wa$V?_0|8XbYZp)C{Dt0aN*E4)8+5u(qVvi{3nFWStymL3w@=cnp_<60b6{ zjYDfz53L%&ue+jp{;VK2-lc8icYW9~BH1s2-C5(jj$CYQ+v(U=gS>YGZ=x~;Yg=N2 z=#PL#ZW7!60m^Xnm&K;jKv`}tf->wg{J|#e7*JiV!~3lsUNs1_b~RDj zbniTX?)?GX)g!x9M(18Cr}Qo3RQPM6>jE4zTo0;s59o7gur19-9-(^t({Wa*9a&$O z;+zd^Gs}UKhGBgTe`B1A-6r{e4V2->8NpRJ$4~>R^^fYmdQ=zoo<-S@F5~|$+A^k} z8iRISzqow)t3ygQ;i^2ETTP;Qs>EHrDmN zpsuR#7CejLYLjbw33P-o$5=NVb%y(jEuXcHEmg>KJ#g@vD#DgHBJ;inl;J^x8yotr zZm8;yCn9@wi@rV7H^i@#Ahy>|cvPu8SVs}ytkzO0kHmk7{tRgJ+j6`Elp$~Mb(`cG z%7E%}2=s4DkZ-VmTkGi7{sT`8=+4~<{}Gwz8c>F`!RSLzK_9xzmh&D*ht*Yy(tr9J z9$oUE?O_J+3@SmeZ8Y;8(VM(W?8pPto)|Fg4uckqO+#=FJ-(U%%5$?o*?%qrWqwzK zGOPk+9*qO~oQZ4dc3Xq&pSQt=;5Bt1On<1a5b$RoFq)wb)}L5bY*3qpW`Wb+6MI_j z7T$xPlz#-2cJ_u0@u8sf=U7l}|De8S4yvkMSL(f$zMm}`10NdDUoR;2-?rVa!Z{mQ z2Wx@n7)G~^TT$<@k2*GQ5u1JhO8ory1-}VO+}OW*eE+IGv+VtCCw1c=ApK|YYAf}< z`yIVi&{utEmx=`RChr-iQqawOe+SC&7lVU(W+Ht#Jxjp1fqIsf(UbiF`grJ~p0PM) zmG3T1~-PQR)?!<-n7@# zhzQ#u#v}_$eO3%S8|d2{;1z~p>n{I8++z``^J}0Cj~d)qrhi;TJ!SgGy8^nl0tfrY z%mc_Dk-9G6F~UU#fFuo<-zJHCQi*=U<4*HgQ1pP`*bnOFWh=5057lSffVKCav1!yym*fz79dYx;) zJ+^&+-C-qv@dihY0!}bf1Y4KcM@3H>G;4JI1eE7LXwH2Ulr~)fO8(~!4z}Z^$UkTY z<<~oQuquzQG>hd!MO+Tq3$wmEIh7M235#&1aPn( z(vL&8$@@$kGn@xX-NA8uE7IG0j_vQ32Xw3io~Uyvm2>7v+*=WuXBQ|#(%{Cyy;l#e zs(n*N@Mr_PM^F#uDKVz-+EpQ-YY%Yn`Yft5RPn6^QfD}3xEfUZGq~o`!DXHqqIkdz z4eyIbAOD%b`nZq}peC>!6Trc8R8?nS4>i&AcTk4vURG}(`iPwpO3x{qsMGP$J+^H) z@95=yw*b6B=Ugh=T(#&*gQj2u{d^FVVKI1YgP#D^{@3?jU0>A?V|!jnQr1o5VaH(H zPZs<4lUDF;pwFGaDZ^l%%&*WJWo`2QE{++V1J$}JjNdj<-$9Pw@{SF>b_&2*t)=9@ zdPdq+3^f0=X=6V#Z48vQ9G;hJHwLP0tF5{KW2-H;45mzgP3HO3QdG&y5YBMWbs5j(PqJ zbM7+Gvi>)}jsG}jgZ3Xd=zngf=uVR&Qpapi>i(cPca7l(`;?5M+g@)w9Gz9jBM&^$ z7-9WQJ_lWh)HQ?02r+|$I;tm@{IfcyfM)}Bv;YTn6p&xqn*9N)V069H_mkL8fHfx1@#&oK<^L-={oTlf|3v%5t1H*n1G zBT&jc3#x7EUwt(0^^5JjK2KW?aDD7^Y~a1VW^$K`GIIoLL&4Y({x!zlIHs;k3~xOs z<-TtC_Zj{(1~;01vq6>m%`WKB{iYd*yT`U{(vY!%c4dImhGFfB|3+*{fhJ%Z?fN+= z&rf_o%4jMm`R9R>Kg*SXVz~?k##m!24(2;joSS2jPBJw?LlDgV@^G0$Cf_ zCT9b$F$`;C>bGJ?6f|#iH@zslKZ8SNv^+I$W{Tj zfRcYQs4kO0+rA5S9H?#YbZqDKwHr9tw&T0So+M}<_EMKJyuqNfaU`g=p~AfBoT;$o z9nPC3k;VqLofL5J-Vk|3^d>;l#)hfC7n@!MW$1--w6WgEVr+dW`hb^hAFzYAIeh@@ zmGVVLKg)X`a1xY(=jm^@&lxI=$m1?hhKmhG|92^#@1G4m-_JY(`YJr%FTpt*sB z(G7yViA7Et>1xWO+NJQ;bgT^|EV`EP+Te8=F%!7|<* z>5O+b!X|f&Tj|*P^d#hMVBfhLc!y!wa?ZagdgGw9BMq8@Up#);`1@#4e0cp0v3WdX zn0~fN)BQZS!d7{n($636G3}%8OCe(eugjId!L}dXEA|!s6BLnleVxY$KL({8 zzcPI3%kfSV&j}-(a@$2)Y+t@io`-_i+N7rWHidyVX>Fx;ko~LJQ3TDvKH8*k%y1JZ zZMw_IRI+I)@(tP$#MY+u0h>0Ku_^v{u_Fx{`@wwppfpeZwMfTpTM*E68}p5Q-0X+uqQ6IXJpb)Z;brv3yd75R~C31`otJhT)*}`DX^dXz<&Op(Dq_t}^dp-wls`u|3Q|-Zl_-0SCv+*%}#3 zr9kOx%wPptG~=t!^*uwE@ynp>3;zL1KW$kD$3WZZ6U*9puM)(xQP*d{#{Iy1jM292 zi-V*hso;#uLd+e;6fDx&5dr-b2>b>Av~rhFH=UYXm|>g z<+&7;;cA1KhPF@#b?*eFeJ>fz^t6lmcs>G3TaPq2I3_E?c6Xe_G$UsE?KJ{C5qt)o zr(HSZ7f0mr8c>F`!NGSu3z5Fu^JvP^Lz~wC$8}C6J%w>iDvU@y&7cge20w1_uMEaJ zzN7K}e6jofd=GU8-th&o?IXj-m;7dZMu4MQW67TEc(I{C+9Y<30%bS_JeJQ{ptSd6 zMs}6q-)itT&H3Pay0y^fmXmvIZQSbE$ZKFbZ~~OU)=i{Y>`|bR31Z8!pgjLHD8nxe z|Br_M4};4+-;Fo{b~$|wZDC$9@NHoI%>fQRFN7!IUIIH<9v?DxT{2Pd-#{69Lx$(e z>0Vz!_X7dl+so-b9J)>32~dX1CyTCsf->}jOeNjn6U+NO1AH6kcMLe_cWx^3pCWmW z0A-j09(CQ#a|jO^jCOkg+U+B5yUkGdLAKi+jy)XH?E+3v0fKE4`Dvn4O~>^V6+7mG zGMo!axun6LGUqoN{tYJW&7idZ0Z__6VQ{6jM@wSx;UM2#t%a-&EYn+ngJY-!z6GKF z3}_U7@OTF(L*C%)juP84pgfOj%$pzIO`Dwik!{O$CzbSbOfm#Gc*nJZo^UK63#*L7lue?s0UoZS5Dgj=%t1}Qf8jz-*W#h7hGTm-Cm~GtLbQ0Q_-#_qFo*K?{=lvtRHOou@Ax5ifR$A zQ5z1!!I0B&KVj#BVEehq64Qr#K>CL`DEo!{Il@n$E6*-zBd0ECQXKOpL3O{B5Ssar z(8PyjPAh)C%ys2KIoFk2EHnnn=fs>z7e+efmp-pa)q{o&O?|LQH2^D6o=+`mQuq=R zPGLNKqS$tBO!~MBL3wX@0hE62JxP4Hbe24)y$DL5eg{gq-_I7Geto*&_&muw56XGT z>ske$(blB!7ZY_(yV$ZD6knOEEgiGPDKqux(5(j0SzW^HaEAt8QAqh$!7%VlHx1OIM zKZto9FtWXpu0{SVKSs7W=Cc(%wg*Pak+%ap+Q<2oU7-1kdd{UpVb2_#iy_*OEh85; zaw*gc%l^MX8E#oB*XfI(4E0D$-B*G#tTXsdP^M$vw3)Wh&pn{@t@V&;qHq?9InTd7(Uh)s-nT+KfX_xkp0A=6t8Ys)3fn~#TP|Kuz@)y7R z_HYaGXBjfu_OKniV0+jFo^1~W$VQ=?;&w83|P(x0sc+jsx&wZFTg=e7TCc?Y`o z>*7+^t)RU2cYy}4{rII)1`$x!KZB*gYdwfrmW=k=UxWNvPK>s$v)~2mdOLWwuG#id z%X?nug)+QE8D7rtqG+?MyYHE{+j@!A^%p@I9tNdfheMuW7AWxtK$(tt)8-T?{oDXb zKkhJ?dgy1t;Ju*qs|w{t`AXOR-udOP{r8f8u-E>m1=1cCf%4kl0~);cvn!;0QlPdS zSQ@PVAP%;N4alEm$Y|R`4!mG{*a@C(4+Y2;F7J8m$6!yeKggAlix{~S>V@^%>oV~t z14{cI2c*DED9bbzOQY^+(`*cH}mnGSQtfZM6hu4P&fSj%*fm^QL3UUO_@ z{nee-rS=7EOw`GH#{wwr4i6BV22Rz=yU6=M8Sd*ZGLM6@-olWfFUOla=76#+K4kcf zBm1o$*@b^M;v3cRfice}*b-{&s~Q8}lN>D1w$VKDv4Pjw9^e`}f?(?*8x}i@hQ{j8 zPzm@++vf}t-_8Uj9t|1#wgHss?>1>t`+S4#Tjv zMjOPABxnkD(x%%6i;cs;quf*@Q^}@1@4%+;Lf@tcaL}gYP_ZKmnlrk8Jw$9;03L0+ z(8%aD0$td533Yx*pw4eW-UnO1<>YLgZ+C2FU;F~_wm>=NhKtSd5n`VLRl|f=i*pRK zL23IPpsb$PwA6-9tZ*r{S34Y*1pW z%l&q1A@V4vD;3bS26%(c&CxX)x=h|t95b8+s&(o0{B`;|bl1+-oeO=o->k3(^qrn( z`LJ$Ukhcw-2U!FhY;TdVVrM=gG;L_{P_a7(oHIWB(fD-g80jw;gEBk^$~sIS4f}_i zK^eXcO8zsTtdBjQEQ?UT-m2f?-cjtHljv2z7&EZ$v%oT`aNn$1RPu?sMgT7aWw3P~ z{(O_hg*BMZK%~y~pgjLQP=;p=zpe8!}`TQI{&uJ3} zdGG9QBhEF#@|l6WY+##M2pqg#bK|7GQlKoOn8C%vaKAzOpsjD3cG3kN>ogBapZ@@= zec?AD75dK?=+Ap_&#eAn$(I`F9t9k1&xISLY$NN0CP3p~lH>b98Aha~EsO`H?QeiG zT#K~y|1MDa_^8S2?d}cRV8eUiTOr`vzB0ZQZxVa6h9*Gs#?Rw!6dyK#(uX@h>D$HY zh2I;pgS8?1HLM5ts_0$^%J5Z#hvOW>k)XO<%y+iIx>4s> zwqYX9*+3hjz$wG9HY9Gv`2H5rG3)E1b1o=#{>0$l8XSBdzmmEu^vxR`-PO>!6?jHK zckVXPmj(?ZQs*2{+V(+n?i#}{w?=9|^#|6P*ml{pxa2$grYXR|XPeyZD1Suiy%m&U zv%%%w4=hI>?mGeZ*tWe}9KE{UfwMa2QoV;aimv=OaX&En=HQrqUkJ+Zb%P%RrG0kY zYIB)&tEmseuJ?G2@Vm*6Wx@G_O|Z)bjyVdzQ96lW+h6=Y#J|XQ#Q(yb(kEp=DHAs| z49fCMLQZ{4(yacrl+|sUWS(LxD6jvgK$-Tppw*zGpo7mZN)m zLy1b?$u3!f@@??HleO(^Eza4%cD5dPj$v3I3*SW_gUEXP7AQm3;Bs>*dFl)IoJ-jk z(4{Wuc}=D7#Ule z5}>pV*Yhb@J9e$RcI*Y(5xAa%*xFJ35#Np>z%gT(E%(?Ku_FbVf-ThhGfg-? z-!`_w`?fCRTj_n9Z3F3mEgOib1i{);+={Y*9kd~eV}_eSi5rL3o;kECe0%U~9R2Q$ z`WwrCi(~bNKkApo2;jKZP|~mNMH{?F^nKx8uCg5PdoBE;X%Ynx4ljA+03`K*#bHB8Y z9H_RxB2aS(fuCsw4nwEcL5gz*FY>MWnK7@&C2Bd zvS)*`Z@(Cn+1?7OeGRM;toayxGh-5aeMG^tfws;74vs}Kk6_K(!;&pNbAK=FwJCdS#+KsU6ZiMRo}=t9-wRBC*@nB2 zcQxoHP_8*ybWu-#!R`^*P8lju`p)w#Ge(Y0D7z1O*ghGlm**nT$^MLya^$su$3V<_ zAa4$Mw3%xSHi1Te+@#xh497O4%J9Nvc!@H+tl=ddlWXEmQ0o07D8pNZ&-`dR_0y+Q zLFvytgPAw&rY$_b4wSxq#bD~8Pk4vneUGyn{<-gZY@4k6gp>u6Xgx!KV+07ak7b?v z37(CSFOP4=Az03v<`cixx-%lYj&n=(~j~E;* zuN7rp=XW|$00ouN=jh0r)c18da4b(oEd>vu>w_5h8Ib(c0` zZ!e6OUM@FY>P*7tG1&7M?_`E9F0-!o|L`2^h~>2s`P;yDx*m9;Vc7PT&x=11LzAHC zr^L6Ho|bdbpUL&}eNcucK%wfqm7$&@5HTjct*&BKtrM(MQEU#P+mCEP6;&uo)2 zjT@>AP24N|ENJE~IqrYA)WbKojMw!v`TJiu)U4}&uQrwq1pj#sPFn&cN)KF*qCTQAj@muzOe)BzWHfM9LTy)a%C zjJbsl|1Sw#m)5Q$9lMr8Upc#O3D~s}IM~PJ z|2$sh{v>uh@tWB6OHggsP|S67ou~$cQrw}zJPE+3L+Y^Y`6$@;{vP&;-ADJ}+rDCa zD0uf&`dgz1R{Y;6fx(cN1?383GcB< zQr4rVNLgQWq?GX;puLfHGbq#cMjkBVdXtxa?hWnn+rPfgw)pqPnku}%O{q`<&r9P5 ztRB}jUibNJ73yHdm8gS*=<^ehvw>Yo7w{Y!h+x}ZCO$#MPZ#@NnJ0eU+$Pvwch6L? zqh;m)-nOs^w%Ne8uogHKYzvo&pM_4kWoh0rPnl?E81HrL-g+{gsO&Xdr zG>mk)o8(;k*QEaM{JPZd$c@qtZoNa=&b)64z5tZ%;O6g6(DON0e^1)U;=3p4AxU#q z(tmlgw3}~%QvRP?C+K;Te#XYe^GB~fzv~?JffXN6XRJ9_&D*d@oxJHh_5N)iR7dUj zkUD%s*z8X z8o#F({tG``1)sLxRoX?P)FSBZgx*%@JsEnB|9?a8yYct`i#ER-f8Rw~UWa@q{3P0# z4gBVD)U{Z*7q|{{zmztf+a)ypD?^_bns`C3k?4y;^S>3E__aCz8=(sPthttV<>Y$& z`6F`uUGQVMu97?CI!r$y*V8pmOWMyoC)e9!pzJ^9!Y1Apz6i?u#8-`t_THy^>@wq^ zJpB7V>9crG*oU+>u!w3tgKu2|WB$Y&Vs8O7Q;_5Pe=olN_|M{N>+6CS8QI3^^{c0M zO;?AnI7&6GY0-Vc$1C&+o1il^bch3|}4;QRG8m}k2^c;%xHJqQ`L0s56ko;J|0 z0`Q1{U+Q1tO9nLgcR9ZKAL2*qpMtmS7ys@DWuIu*Oq^S0&BV-A@T1I{3EIT|e+kap zKvR|i=L2J)R8_MI|F`J6u~)MezYUbS<^KHPp7(7%hjNNHhtk+Oe06KrVs*-j53A$X zEKw~RE>MSW`iL60?W4LbDvhJ|e;z)ZGEAM))mNRkqK|qXE}ZEb&?j#~pS+EIa(&M} z`QP&YE}ukcN6*kn!_-M=KQqyOjz#;KcA)n2PUZjI-rl~w{ZE(YJI()pTK<2yJ+S{i z1U+%n7fSv27~uWDBY49`u;csWY0_6GP7)fMBQ$$Lvz{A?A1kzYe6xN=Q!|7nj}f{2 z(MJB%W<4fI&lFmGpP{ET>wO$zNYAlN<~X5I@cGOUha73~{X!G7O@7eBdq^C7(p*ev z=HzC**Ft8N(6HerPn7ct{K#NA-q$Giqbm++*3Xk?j}d;~vCZ25D?mp=cl0nh{|G4e zzxe(5X1#yI?Gu{S2;iFLX4MG#K~UcQ5)+&Co)Qg{M6Ppcv)+T^Dp0;7e+ZQ0x=}|o z>wO;%2c-{hO~bts{E5?>^*#<4f^tubpMW-ieyF8cajtv~D68qGpqyrIMj6+D9%IV- zd!V%A#|GQ+R;Bj=3)jB$@m8hr8QT`e0x9Ha1IH^HfP?e<#ZK`%d8W`DXtGs~uj-Jx znKfU0d3Ax*$zMTPR0r~D|J(Rv$1hFSmu#fXQ-FgurWZG>=pxa1V?u1Y9h5eNjvj!0 zibks`E5=|%(pV@PKqxog#X!TsxBAwRy_mv7`%okwm z+tmTD-|8>={?!5J0`DbqUu;&{)#A_0>%_mrh z1jf_h2c;achGrf@`DBIn;1(&X@%Ko(9DJX&)8U|O8-M+w@CQ90_)nm$lPZ%}9?Vcz8m&vfKdF`)-{WjF#U@I`((81nk zVn3I1%0DYKVQBFg!70$lqjLQH$E55x|5VEKi;oL#cv9-%(Wm5|bmh;afBYOM>%>0m zw3T_*nRo-rctp?tu-LvLj`KFq^o78Qz_U(zSF>pxZ zZXbLw{(SIN@nKL=e3O-xsj>}~YmWIIBK8rLq8|Q3bS+xQO*CSPL4P-ZX9IO*fP-ZkT{%%@poe+> z(&+tz!NE1JHD7@aXPxLfJ+{|=6#3Y|G0Q^Wm|=96!KbARB8C>P5*xFi^d$kBgzdC@ z6)4O0hoDS93Fml?A7Ro|YL9o(p9<}9r(+}ay#O36yY$r)RSNdehQo2pFawl0SU=&f z_N<>7;MqVOG2oz%!g}0`5Si!aKpDPla8SqcGCFPv=-60BNA@OM%ZSu*HYmeK4c2Sy zw)iU)?fpfsa4GXnq3&z&^#J#{7RcB@-)916Sa}Gx4a9Co`F>sOdg@lOYxQlWe9b#! zz4D`s4e5ihVOzk49B_;c$+4mEEnFY4gJtuVZ;B1EjlK=jD%@v>+;ZS@mhw3@EWYtLiV- z{Ckk8qe|_hXL zC%m(NA^34n`g9^>4#uY}^i?YNcgnZ*v@76Kv5ZfdUyDygQ2G=HjqehhFaDMAmOn4} zc~JV)0hxpGY1KF0d!Oz?o;L8gV>@uLo?->@DGf@WioZqw@`BiW*KdS3^hLqPfKq0+ z!HXeFACsW;@o|G+H~2u;+lt%Yd!IAN(*|B|+kk^U$9Id*8BqG8h+h&P#=b1Prr!zv z0w{fa%isg~)cVc$-lyfr(+2vq7C7ira*z0w1Eo(9(D3iYhiR_}@0dRbz7v!_9SRxN zn;!Sr|AE=>0rXn7Q9akPY5v5XeEn=Ty2rDbe77*#d*?3w^Qa#Ev&c^JWwpLBJ@g&y zJlEEZsE>nuhJ69DHn8vB4ZMj3g}^dpSw&BrqzcDP(#MD5nBfReU5?=ztm{71U)SB( zAA8gtT7F%i_HA+x-$I&ySOtEx2fxyoKYs^&4~+TWDQ5r3=Zk&F%LcZ=5#Q=Le$QSd z<&pig&^Rc|B@CLoQjUAAoTS@cf5@^-uLNaTuL7lPaGbvgdVA zRW$mWam;WmsMb+t56vCaQ|8;DVnElvGP*LUNh*fOygv)d@Fjz>uhr4m*J?qzeXVAH z8#;$q-q&g=&f7pgmjh2U4BH+ftKjFgqWi(mi0;QgwVxH{CU#Ko0on!YolU>!*r2DZ zHubFc{A$q`{p=(ahdtCi3_ONgKxyk8Mh5kJbZu4d1)(_lD10+K8~NG#wbbffigPwl z_e$WP|KZPxo&t0y5vlvzpw#(8P==i02X*J(M)#h8?tNu+7mV&KXbh3MF9)UWHRjy) zh9CS6HU1y)`yl2Q?D%8_3 zzaaT1LGwmOGmhz3t2s9xl(qzQKkzoXcL#LuEu%Ygo#;-07L1OOIHv9s&AHj2TDN&N zth9$g*LP43qss3yQi*TNDUGx?uw7(;vxZ^YMP!bA$C&^vnr}A0bFzHXxfPT)Hk>Bk zbdCabZ5~(QS*hi&cW(3B`NH|_g|87p159k zvq0&?a~q_s5BsX{mqV8PG$_L+gYlj31^CYQk>J-e?4Mqvp9lEPcgS~3cGHhhzzHfq zuyz+SlT;QqQ~%jGX81HHvHs@dcK2&A{SChN53(-g>Gl__f99PI=-vPv>=!cM!9C(m z(RDeF8NLjvb=UM(HM8s&p0IZizcbZ;Xf1tbs-LGP^c=70?;09q&R%~bGuV6ICF7W3 zJ;y77`TE)4EAQJ<@NHnZE(eYohAr3Bi<4C9H{#1VIA&N3O5gB}@R`^vdtFtu^i5xu zy5v3|?VIQmx8=AipsN5pC!j0(66&xZdG7<&0X(fMuoudZyP+r0f6fHY2KqA_IM}Df zUdC9-3GS9i73}+i03infbHzaR%3+>|kk=X98 zPAyz9Ky|Dcs7~21NWFhkSWVkjubOuZR-<<{;QPQyJ;wiyL;J2CS~cL!;QNu*EXrq? z|9&KhZ6CKBvNrHF<|^P7hGE-5VV|jwe_#yqck%5LpbVE7e36ma0m^i{Ky|s=c9JZ$ zlijq>84tS0)~>qECA)Z!8U-9|GvR-V4GGW~Y@@#OL3IF+cJu?)c9{Fbmn!tRE0F)& z^`XowHEvzPMk=$G8vy4p-{7cH|2~gU&?!N`U4$AOZ$kO+FK(!BMPpby5ig4;QOWTL^ zRs(Ebi!o^T_3zlmaw`C*nK=UUX1?jF$tnf=cs#b3*x3e3Z1<@Q>TLSH(K*ZX?~cw^ zoU?&CJAs2b3wiYqjXS6IAOg^Bi*v^&OzyZg=#u_;&&a`=LaC(G>*^*NVQ4 zpe&1hpbR0L({>E#b0+qayWN&H@0(M$!j6O7m!cE0Hqf3Wz$hjiY}qFU7<)i7M(+pe z#GcQAGJFqI+hhK--JnX>^CsF;=3DN(qnmZG3piK@>4B3~4tkmQl{jX&4wP8mFP8=0 z83pbIk$a#!a4(nxo(4BfR3$YbR>r%UqtFS zjK>Jm4Gz8&-A5f2o>^?482LfTFVJ5*WtgbB(kmwtUf_btG|wp5se zwuDGs-vMR#xxwZBCHw;Q1g>A}YxOqY*E-;Y&avcccnWk(7JWZCT=e|~l=`9XQuG%u zyZuEg@~EV5c|hMv;AB8wpa25Ery@&5B zl?Cr<5#U&Gt<`j~rvMst zLpuA~wa^(FiFu@D<@ZP5>e$G(`2g@P77&7Mo8e<7tJqPZE7KyjeC%kWduR>EaG@bw zjgzcSR25|ZH+4Vs2F7rll1yumQKbT>!Xt0x`MvjI5RHZt#n9+U59aLjNcsMcflv>R;pw0n|z%${~u$KHUB{lIH< zE~WCz9Y0y6XG)$8IA&-D6&+Qpv2Wg+cFrsI!@$0Iz^+b~R~LDpDNsJwZvtHb%3#Y+ z5WeAyi5`o2p5raj^+*>3wIK^x-8YytXMs}gbD#{j89wEhM`PHxeLwPZ_xvLc+TQel z*gg}Kwl4v#X!}W(ZI2^e4C!siLRQ;u(wqgVZ3ktz&G0FwZLhGm=|0-WaiB9Md$*Wv zg}z1}EVcU@;5ooq8iznz*&dRoh|fh(^5Un8y;)$|odH&}L}uB^;@fkeyr0gQEom+Q zWjm=s8irF$+KWJ?&Go%B+=YF(s`@_bj)Awsp3qS2;nvlw`#&B*OkZfnYmP6}y&rfX zl_6MPqNj_#BxrJu9Df^>VJLW%n_^^w);m;h}I?hC*%(vrRT4OIBx^(NC4-zg7q&6@O^Gt{5l?(8G zZ;Ku4G;Q~7B(^rT;+Sa`fzrlRpzp-SB;;dAXG6i*m$+yHj~@R4Z_pY`eO>-4(VYg3T_ML$T`Beax0QmY;vBgxXv6CgpB2_i;C91%1s=zyRR6^A`2;K&*k$%JGe!H|quAXwCK4}zGw zMvIst+NemU7Bwo;R7K-bn=005(WcZTT9>I?qowBmyYK$)WO9?2OwxYs_kI8Gwa4E% z=bn4+xy!llzBj|f{I?E{qx<9E1`Tr@<~XBWnfb1u60w-?ooZv^mE%_jIn8RhHD1?^ zxDTyYalHYQ*SnO_Mw`#?6YARLj+FJ-j0P{~{Y;?D?;K#NbcRc>C&|lsk*F_OCdmhT zuT}zU5toeB2b6WHfby!LEX!p*GsbH8iOp{*>lo|7%Q}rf8Drv0-HY*S)bpaAzN$8; z82vyQ<9eXHHc^)4R{su`zxQbU%c(Z+d#vAKm;ah1_IKDFgXJl+_4gR9x*hz6tNeRz zSL{g& zhHT#3LVrI&xW8B9vIi)yW1*Adgmz1DPnFR`Pmc1Qx(@_$+-vNw*>i_d+&tS-`MWcyX_t!KeNXW4;az*dj*b! zgy_E&b|lK*uyhNDA8pFteV1s(h~JYtBvBkvg0+>?R~#}P?+eByH!edy_Cmj^zC2$H z`s#df-36+jMc^-wksW<{i9X|c`I7r3h<@V}<(?Cib>&z;0lVLWHnZ+_@SlJlqx=>4 zA7aX-+!9lsba)?e`1nEM@S>rOLxKnUrC&L=6TUuQ9P!Qh;wAWzXvHwEm(P*l5DA0P zFW4kWegwWBz&cMipD(6=2mh!e(b3BxdLcm_LlVW19MA$hbD{4;#<_xyLe~Q;fBA>91d&)|{oM?YV-P;m&H;_@Ed~ufDCiiFAO?)@CkEi%gX56i7|W-` zA&wf+hZ}*6OI{i!uh-qW->P*g$6Qh_* z%N1_erN*>7^mF|EX|z%EMytPNf5p4lW%Kdx<6CuCLl=h59n;1(=pxzp`?oQ=7oZEG z-SQY+6LcBS1^2f4OZ*b~j=E(rZKOh%jy9@ebmu@<23=*0E(l#NbavN7jHSF*%kjgN zL!3wbT*_w>Q;9=~eTZMven0Uw;#0(x#LI}c5UYt+Y<)_}YoAeIw9B=)2IO3E3; zbfQ%m{~1iV`47t9Nk;j%m|uC-5qA@J5+5Q~5$_;wBwkG{BNh-di0=`tM)02`#e{|u z%aKV+%MF4zDFER)aBnB@;XDFh}@Ewhd6}g zsg$*!p~w$;eIHTSK-^8-PTWEqNBdhSmk=)`p2PACVm;fP#&+u{ZzH~A#1o=?Bg-?0 z<<#Fo+)PZ>{wVJtK2F?C9LV_G#EHad#O?I6n)WXc^I2X``F)}uzbjZCq5c3df%*$6 zN9g}U;xuA8?R>OLq`ru#+sSA7Y}#vm4)t2z`)4(eTJ}>eB3?nQR1_-Pa}Rv{FXQnd%nExp#1{sM-n&D?{K!~qP}^*s`no8Wn!4PnYfX-j<}MT zK};u(C%TFKh~NH+?GRre?jYVmyq36OEVvu+t zaSCxX@o-{);@|NdiXO#qsXVHFwRXPKa#FXknG0G~PRvOH=YQ>mLEi5Prl$8jts$Ucc zbWkW}Sf%J!`$CLC5b>-P7g;t|57ri!1XfvLFBW3zybF8_*v-ZB$7Sjse1tb(ltbNa#Cf@dZn3O zCc}{mu}5j91*}I>{L5n{Pb~^yj--3>qPDQww^ZT-rJJ9(qChGT`)`#-PBO-IbzV-O zsCcn>U1?_q3g%^DrLDqSOXqxRjAxV1Y3HDXc_sOa@`_4Iv+@@ftidY9 zuaH=6m*lAMg!r?JZAM;xV8Pm8KqU8GT$EQ5kg^zH_60pDb6gb!$km*3Bg6x zu7<-X(KQ~Eu}>{6D#9{ekc(N*nFT+OCM?J=o}8awn2mR`l84cvto+h|cuYzdA|?G& zN^;1>TL~N_OZu(!I=x_ZUQuDeDtKO$Rg{;tEI+VVR42?|lUI_RyP$AJ-m*ZE_%(7V zKOl!oN~KsYa^YFh^fJ+spa*C{VRY2QPZQ?n2LeIyiag4*-m*ie1PO|tJc}2z6Tw^9DTAI1ogk+7y z__PtZyc%1I75;)kHJ(CTsP#(0uA_Tms<8G+E~Kwx*1%M(A?$eh^Rcw$-n?H-$97j_ zs>KZF>_FD)Ks$Xc$JH$OIJ$BItMK+oZrI|3gvD8TCCG&Nc?B!-18VmduUm6imRB;h zFekvS+|Bu!uPY;CX2<3fM&%A`RtgJ>3-bd=WB4B_a|%P#s`(9~$jYG#KHiL#;iI3K zH?Voed46f2Xss_$WZjkuvav&!$}tfwPUPs+tYArLbT<{fW!}y%EWD&NsJ9vnAT|Z@ zV9ctCZXIaTx-T*lxSGU{gav`3Re1$il3FEpw~GTy{?gJwK{j^gUg?3Xph}!svJb2! zwfNxztJF#m@xH~+3n<(7^{mV(#XSvU>Ok~!OXQ8Yw0J?`w8CPw?G=c*C9S*5!nV5? z`Y=pPv2HD`8?H<3MjYzJ;=_*S8cT5lXVwY;qkT!Bs34H9_vC^Syq~mg_sgvNgu3%5 z;*I4L+^N)p$+ULAP%qzF$z-DQGxD=m6pL?Rg`F!?Wti&6_1bDy@%++dC34#o*J&MU z&d)Ez>zebOnZC7|a|;V_kSHq6hNhQ8`LcE&-U;T>s$|xxV17XEHh~;%ztAdMP*fWA zFxS$|$jXewX%>z@#U)u-#9}Ax~xxp?7%8EFU%i700iu zlhp)PI3?W#PBm(7XBFfG%2ZgwgGlD%0&0uI}0^=)3!kRttD`~YlD?f8S?g`wpcWd1|oFK8^>$}o;w9;lg)R{}X34P3Z zpA#s_EzH5*)w)XCuc|9h%B(L46y;^BUF~*wQcl&JKPMx>PB6Iy3w#-NI?i&r)MFjZ z#L=c8I$?9Na7@5V;)6o%1v|ssEO}pUiiu{HyayD_D)8lJA)6kGDVbb6y+Edw+zwYF1iN3I5?@pztCDaV6Ci~T0+09G!xUcW^xeEQ#qm-txwC#X3nh9l2yAv zORT*(uOwFuXsIrV=2nT;$is^GD_UV6RbBLRGIWTc2r~tXWQ;;rX#>poOWhd_#(Mc8&YUklrjw2UWM1Rze+GL^| z*0e3NGX5G_1FL050P92COv#!}+{bRDjD0NXK#t5br8&g%zSxHld zdTM93CLPZ`TGor^vsN!q$vE&E<84|~I(%TNqnekOojbK~RS*vi_W7t@dwn>9Elo|$AcC=^NyW6gcLJ(8};nSr!M)Z6P+Xc?g-1^ zhXc8-RilOz=XUNh))o{DWQ!eWZEoo*JUnDtHx41@Lu2i~lZ&l8^1`;VrMs|I7rP%@ zWnalw<$0x~Feo!Zy&E}F<~=&I2+y_hJl+phQwj_7)r~2*7Mo*2-dGux{5@i&b#TX*_z9lo)dXh%HQP3Bcbh?WUk37 z#>)lN+#n;$4;0{E`C5IDy*W%=T8tYm{(WDj%g{-%t3a-t>dw}aK9yeI<6_PK&)Ic~?;E~Jf zBlg~sqLRYWeEjVZYsB&jGqVdZZv~mFi-Ypku^jd{>$)OK+2`YX9Cr3%ld{IZxDglb z7N?HSJ7t`}U;Jp-LUDFh0mkMS^aM{}_}d}vEY_$X1X`8{uYd?h@774lUim~;NnsxT z^1IY#7Y7T(t&)=r+QZ-m3RVkIAo7ZfaeTn=p@pn$oQ?7dmt`);%NgNp*XD9IxeT+u zTz*MGTrL!%KPy(L8AjtnMCLNQ2rDSD-Y3ZCnUGi>EX90g3wd15!YJJ-N(yoO#M4_Y zV#vu`fnJ^}up;wHkaMfVX{~%_K%6b-F;}hyd5e=asCDH8Fh1S&A(-Jz#UlD~vTT>SNU9D~?VqWX2X-FZp7P%ywdCB-X4p zVPS#Vta75e8Q!j7+VL;s8Z9WxhO|;bA>T^nNO?zoVYt zCy5rlOa0)eMlp8!FKF*F>|1R7+vyLwU5$?!&!N=w`!CT}nr=|`W`FJUBj|_Udx`q# z?)vdO($88Ca!tf@HQlM=JbI(Tc|d)uhw@kq#dgMUE|zg;~gmfFP;ttB}Vn{8Xvp$S@W`5=jQ!-7xm_S#7=MLKk;?t z-|VN0dhf_Dpn5pWNHT&18aVLfUzxuJ8M>~D(=N+$G z@3$SVx6s#0Z=M^wYi}2io!%}^JH1^zcKYu6v9s@FNwz8a|8;#<4#~F8v3fA%zuL$Q zX5o`PrLmiTSMma@o>@Ma`gr#tv%ZeQPM>jvYM0-e*XAORdh>bZN7S3oB^zw~Y^L7a zzaO;GKTf^5e(e10w(;|djlO|;v%eoxZ}#gu>IX(gMlpSdsc|!(s}82#?5~@8v)!@X z)DL4k=Kf@-A4PjJ9y|RMn|{ru{zzjSE}@?PP9s`+74<1mjbiSi-n`##q27Fs+(!MO zhM%XYH{1Ok_2#<$Gxg^9e@(sly!!+7W;_W;s(I(X6NyH3F!iRNqg=|~?C+7ZH_tDr z)SL4)!A3ua^K1G!mwGer$5C(YCwA+>Ze0zgAG5!IK3w&8Saf6*^BVR1_d3ziTI$XG ziW+pmnEON*=C;NE)BKq8sypVNp~l}_x67$F_l>fd%HCW*p{Yu5?r+!7-kh%=Q*YYe zL%q44AEMsO$ET?`_u*HlH|OaM>dpLWpx*449;dF*Y{#^>8~=ZmK5@AkfBrkSX!Cad z%Yw?@%*R}R$MbkK?alGI$wpsEy*ZC|@%V~WyQY1#BV90Ejei%_qs9N{Cpr`zGF^?2 z-TeMf(RbMC4wPMuLkCqlRQ;cy4u>VG{GT>H6;F4(uZmqA>-$k}_OrYBQunO#AMgI3 zQK#(9_j60AH}8*G-PA9qy?L&%^OH||Gk!b!Cfb|l(l2cE-%@YhUz{(gaWK#4gQ+*; zx6`N4-h6)PuHHjG=6dMv_@vqRu^Uf2`&yfEc!7HJ{7_H5xvut7Z?3DisW<0+pN*eJ z>dkri&_@5MjsNHd(*AqyPIDgZ;_R;eAo@4g zn_WD1{jwWpJAD_+CR+UOT0hYSyI}si#bbu+Z608~r_UX>(8AF)$T(8T=6p1qsPyA# z=N=uOU3#2$WpUb7$7xp|r(NQh`1+AXJM()zDJQA=V>vE<%3ax&#c5X=r(I2)cJ*=E zHN|NsPFDTzs=q05+NImrrFv95V>r&al+AWcyK)=5O6v8x7h^l_hiR8;V^>bSUI+DY z+C^;a#5fht$?UI}ve{qL&TnHEq+X9-I8M8I8#{*8efU!CJKe9SYWTiW^)n`_@iF(= z;3TCt&-10!oA#GeZ@$0XM7??6|5xd&&Q@`n_tWjvoA>c2s5j$zntJnGvB$>#U!{ME z{>}5rze?{vUX73bT&$Y1x&BSN@;L2kX=mQ&On*&r+NGYL;x+xH^S&{P3%=IoK4RL1 z;H$pl+M| zGVPjKud9CeY}z%)IW=C)Z0yo` zzd3;$lihx0+SS{o_bY##{+iTK-Nsn^dBzBuiIv}?CcPf_dqSSCz5WpiBG<%iAwV%mlI z9;YjRjm)>M>^wH_h0Jynhj*O6rk&va+Eu%$aoT0XY1b5IKfH1FBQZ{YHJmqd9hl=% zYv+&s)92lqIQtu9Ke`&{<~aN7vDu%^euV7$!Ew;S-V z8g1sIp7%@r9w*V}y;=>QU-Y;n@_EZ#FXnlp+2;L>xlaad&Jm_v%?Oph=6W&h8soGR z$8_w^JYTtO;xqf3VYB~baR1cr-@-QgscBair(I*5c9n73dB%4v4K{Y>x~j1`N0@eHaoSbJYiF}g&2}5&w5zvS&!)fTIPKhV=37~u zc9n73`Qo&5$2l(PaoUyH*y-mB{T5k&KW4zE>dmMVe+NZgPRh}89^9ORS>9h^yYe}P z{+DVebY>X(0rWG^M!(R|^NasFJ_iq`(e`z@**^8jd@*I(Cl660V(OzZzd(`9FFHr{ z{6a)B$0eDvSss-asCJzA8?*9ir(dG<$^3w@U3r!&cbM(mukLVBd;E>yHvX$DQ8;JV z=r8P8AN6;Xn!n^p%1=AJ887XlcKDk@@^W5av@@OS;(SAozprH3AFT9FEf1%j;}G@V z-{^n7vTHX^ms@T{yYZzy>hECn$%k{CYG2!HjN0wuxS0Jv-iYU1CAX`8j$yZj@#%F! zIoh64o{ZmEl2`H~;$nrSz4N%X{cz5vY-c}Km79K&`GJb5cP{SOK5F+o=h>s|+Re)~ zM%y?GtUwX>V7a z{0RGLH;*gWp1B^VkNTaa`qM7YpJxBlRe99Dh~ucs{Wj&3RQ+hZ-Hey@k|~?z&T|ZZ zvkZAB`$a#|`dV+cOMTRi^O&sX!Caq4dGb45jI*|{Qg(VBv}@0dOV_h&f3ost`iaWl zsQoJW2*d7tB}e;5Ia<#sPyUwncI(KjpRDYihpBmS&Q+-QDUH$gXs_dJH$J+YXx4Mi zSN`ql>GOeIxxW9lD<8;pyxtf;>Z5TSuk4&h+Qh+f-9NKl^7)2;?Qend*UsLIhxSps zSJZtbnfiA9V!4z4+m+LQbbXlZ8Rf|nIZk%#!>m7;NmrQ-TeMQ&f zIoqt~)aPvW&n(yH?&OQryxEmI_(7CyIor|Wt^H|qrr7kC?dp2YLzP|f12*xP=LOw= zeIGNQtBmsGEjHuJ`nueis^W0+zOLi5Jue#VI8V0euZ|OcUsGP~##5J1Rpq)}JG*x0 zN+S+k?%=xCXzS11r%ivnKWRT*#%Jz}razWP{h9e^+Amh~*JZn>c41eg%G-?t^?Kae zm7C9JIzIiJXWpk+?mWt7zWE$yw&NUOW6$R`-T&lgRGw(rsoVPz_hGv{GN0RYKaA%* zz29j6W}L}}z25JV7pw7g_U?QgJCC>NC!Yh8^>d&IKJ?R4Dj`l;jL zcqbpM&foFcbrrAkL^Tf16KuwV&%1iQor`$>x7*LOy&fn1o~0{$oj1d5^24q^^~vV@ z1ih|U?&Q8^j+=hIH1)}wY~tYgL+{t^>KWz9e2>u1j?c+@{>^gdDK_(=pQH8pq=f5| z&q>ZIo4Ad7x?Mf5TGnV6w{wDuE1B&i^E{}}vl_J@vtP-4{?+BtbAa7`@v6=J*gRkA z`KI1E#Af_huKVZYI(05l>)L5PuNr=B=UumZZWryE&zq)yyYrHcoB40MU(imEZ@cl= ze)Rs$e2eb4TGshXIbMIsJ~fWE?LMT+^}37hPkNtNY_ooK+(ul<+q-B_+ta^YTn^p7 zj_+Z{8Si-O`no+mj&auSYCd&&m-E2!bLjTj54(OR>wVXJKW(l{ZP%6GNjCFGy>0wO zJU7_g-*(&hrCy&0+VxYHZ|S1GU0&+?c6n)(>pZfJgMMtsf&LsryNFk>GrM)I{jl8m zv0Bg0nS6i2b>jRh*STHZ&9&Ko_4_`~Tf6?U+_s;(zU~LtRXacW{oiCY9=7LWyZNJD zKNq+2ugkaCjJHv)?;Ey$^mB?`K52h8=XKpbeV(;#M~|CbJ4e{`hkD(Q=ss+>Z`(bW zQJ-w{{IB1;>HDQ_uU&t%AG`6;<>vb-y+5(sZoHi4=ajmh`JU0xxBJ{tmmBZ>Y}dDq zUG#ouytnAekCXT7cH_tQUUqu@UaVcYe$QyP?u~NW`O|iG+6g+UfqHSs5q4%jOn{m?bbM^hqZvWPHdcW$z&NlANDh}Omje5S@^~YxXbUo8v>yz!q z=T~Z@v)%9XdD><_*5}K1?b^I|a=xoRUvlmz{$1U-&H7Q9?@9IZmy_dVSFZcpuAJv= zJAJ!-R=3M~&i(ux-h6Ls*y;ODS8*isJl-yzNyfU={(0_cXHUKJXe0lOdd`uZm+Skp zo&R>{Khytr>bzxF-*!A0zwP+5yj?!%_RVvg)|>m8)^p#E#;Ko=k5%KNpD)bvcAxvO zp8k9#I`8H_VA?HazT4P2`J8R*?=0r)PgVXz<9tNP?cy}_?LK$V<>vY_^zG{D_jYineRNzoU+vCKTF-s8 z-TJnhXG5?1Z&zQhd%Z4g?fE^VWd6!?G=A!x2O0UV?alGk_T>(1q3ZXtPCh3)&$ID! zsIhNp|K@!|>&@?pX?>NAAM{)q2t6vB)NGSZ+ICMtSmd z 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 bool: ... +def check_ansix923_padding(data: bytes) -> bool: ... + +class ObjectIdentifier: + def __init__(self, val: str) -> None: ... + @property + def dotted_string(self) -> str: ... + @property + def _name(self) -> str: ... + +T = typing.TypeVar("T") diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/_openssl.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/_openssl.pyi new file mode 100644 index 00000000..80100082 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/_openssl.pyi @@ -0,0 +1,8 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import typing + +lib = typing.Any +ffi = typing.Any diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/asn1.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/asn1.pyi new file mode 100644 index 00000000..35652c6a --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/asn1.pyi @@ -0,0 +1,14 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +class TestCertificate: + not_after_tag: int + not_before_tag: int + issuer_value_tags: list[int] + subject_value_tags: list[int] + +def decode_dss_signature(signature: bytes) -> tuple[int, int]: ... +def encode_dss_signature(r: int, s: int) -> bytes: ... +def parse_spki_for_data(data: bytes) -> bytes: ... +def test_parse_certificate(data: bytes) -> TestCertificate: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/exceptions.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/exceptions.pyi new file mode 100644 index 00000000..09f46b1e --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/exceptions.pyi @@ -0,0 +1,17 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +class _Reasons: + BACKEND_MISSING_INTERFACE: _Reasons + UNSUPPORTED_HASH: _Reasons + UNSUPPORTED_CIPHER: _Reasons + UNSUPPORTED_PADDING: _Reasons + UNSUPPORTED_MGF: _Reasons + UNSUPPORTED_PUBLIC_KEY_ALGORITHM: _Reasons + UNSUPPORTED_ELLIPTIC_CURVE: _Reasons + UNSUPPORTED_SERIALIZATION: _Reasons + UNSUPPORTED_X509: _Reasons + UNSUPPORTED_EXCHANGE_ALGORITHM: _Reasons + UNSUPPORTED_DIFFIE_HELLMAN: _Reasons + UNSUPPORTED_MAC: _Reasons diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/ocsp.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/ocsp.pyi new file mode 100644 index 00000000..b15628f8 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/ocsp.pyi @@ -0,0 +1,23 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes +from cryptography.x509.ocsp import ( + OCSPRequest, + OCSPRequestBuilder, + OCSPResponse, + OCSPResponseBuilder, + OCSPResponseStatus, +) + +def load_der_ocsp_request(data: bytes) -> OCSPRequest: ... +def load_der_ocsp_response(data: bytes) -> OCSPResponse: ... +def create_ocsp_request(builder: OCSPRequestBuilder) -> OCSPRequest: ... +def create_ocsp_response( + status: OCSPResponseStatus, + builder: OCSPResponseBuilder | None, + private_key: PrivateKeyTypes | None, + hash_algorithm: hashes.HashAlgorithm | None, +) -> OCSPResponse: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi new file mode 100644 index 00000000..9cdb4d6a --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi @@ -0,0 +1,57 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import typing + +from cryptography.hazmat.bindings._rust.openssl import ( + aead, + cmac, + dh, + dsa, + ec, + ed448, + ed25519, + hashes, + hmac, + kdf, + keys, + poly1305, + rsa, + x448, + x25519, +) + +__all__ = [ + "openssl_version", + "raise_openssl_error", + "aead", + "cmac", + "dh", + "dsa", + "ec", + "hashes", + "hmac", + "kdf", + "keys", + "ed448", + "ed25519", + "rsa", + "poly1305", + "x448", + "x25519", +] + +def openssl_version() -> int: ... +def raise_openssl_error() -> typing.NoReturn: ... +def capture_error_stack() -> list[OpenSSLError]: ... +def is_fips_enabled() -> bool: ... + +class OpenSSLError: + @property + def lib(self) -> int: ... + @property + def reason(self) -> int: ... + @property + def reason_text(self) -> bytes: ... + def _lib_reason_match(self, lib: int, reason: int) -> bool: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/aead.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/aead.pyi new file mode 100644 index 00000000..81e801e3 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/aead.pyi @@ -0,0 +1,69 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +class ChaCha20Poly1305: + def __init__(self, key: bytes) -> None: ... + @staticmethod + def generate_key() -> bytes: ... + def encrypt( + self, + nonce: bytes, + data: bytes, + associated_data: bytes | None, + ) -> bytes: ... + def decrypt( + self, + nonce: bytes, + data: bytes, + associated_data: bytes | None, + ) -> bytes: ... + +class AESSIV: + def __init__(self, key: bytes) -> None: ... + @staticmethod + def generate_key(key_size: int) -> bytes: ... + def encrypt( + self, + data: bytes, + associated_data: list[bytes] | None, + ) -> bytes: ... + def decrypt( + self, + data: bytes, + associated_data: list[bytes] | None, + ) -> bytes: ... + +class AESOCB3: + def __init__(self, key: bytes) -> None: ... + @staticmethod + def generate_key(key_size: int) -> bytes: ... + def encrypt( + self, + nonce: bytes, + data: bytes, + associated_data: bytes | None, + ) -> bytes: ... + def decrypt( + self, + nonce: bytes, + data: bytes, + associated_data: bytes | None, + ) -> bytes: ... + +class AESGCMSIV: + def __init__(self, key: bytes) -> None: ... + @staticmethod + def generate_key(key_size: int) -> bytes: ... + def encrypt( + self, + nonce: bytes, + data: bytes, + associated_data: bytes | None, + ) -> bytes: ... + def decrypt( + self, + nonce: bytes, + data: bytes, + associated_data: bytes | None, + ) -> bytes: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/cmac.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/cmac.pyi new file mode 100644 index 00000000..9c03508b --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/cmac.pyi @@ -0,0 +1,18 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import typing + +from cryptography.hazmat.primitives import ciphers + +class CMAC: + def __init__( + self, + algorithm: ciphers.BlockCipherAlgorithm, + backend: typing.Any = None, + ) -> None: ... + def update(self, data: bytes) -> None: ... + def finalize(self) -> bytes: ... + def verify(self, signature: bytes) -> None: ... + def copy(self) -> CMAC: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/dh.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/dh.pyi new file mode 100644 index 00000000..08733d74 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/dh.pyi @@ -0,0 +1,51 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import typing + +from cryptography.hazmat.primitives.asymmetric import dh + +MIN_MODULUS_SIZE: int + +class DHPrivateKey: ... +class DHPublicKey: ... +class DHParameters: ... + +class DHPrivateNumbers: + def __init__(self, x: int, public_numbers: DHPublicNumbers) -> None: ... + def private_key(self, backend: typing.Any = None) -> dh.DHPrivateKey: ... + @property + def x(self) -> int: ... + @property + def public_numbers(self) -> DHPublicNumbers: ... + +class DHPublicNumbers: + def __init__( + self, y: int, parameter_numbers: DHParameterNumbers + ) -> None: ... + def public_key(self, backend: typing.Any = None) -> dh.DHPublicKey: ... + @property + def y(self) -> int: ... + @property + def parameter_numbers(self) -> DHParameterNumbers: ... + +class DHParameterNumbers: + def __init__(self, p: int, g: int, q: int | None = None) -> None: ... + def parameters(self, backend: typing.Any = None) -> dh.DHParameters: ... + @property + def p(self) -> int: ... + @property + def g(self) -> int: ... + @property + def q(self) -> int | None: ... + +def generate_parameters( + generator: int, key_size: int, backend: typing.Any = None +) -> dh.DHParameters: ... +def from_pem_parameters( + data: bytes, backend: typing.Any = None +) -> dh.DHParameters: ... +def from_der_parameters( + data: bytes, backend: typing.Any = None +) -> dh.DHParameters: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/dsa.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/dsa.pyi new file mode 100644 index 00000000..0922a4c4 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/dsa.pyi @@ -0,0 +1,41 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import typing + +from cryptography.hazmat.primitives.asymmetric import dsa + +class DSAPrivateKey: ... +class DSAPublicKey: ... +class DSAParameters: ... + +class DSAPrivateNumbers: + def __init__(self, x: int, public_numbers: DSAPublicNumbers) -> None: ... + @property + def x(self) -> int: ... + @property + def public_numbers(self) -> DSAPublicNumbers: ... + def private_key(self, backend: typing.Any = None) -> dsa.DSAPrivateKey: ... + +class DSAPublicNumbers: + def __init__( + self, y: int, parameter_numbers: DSAParameterNumbers + ) -> None: ... + @property + def y(self) -> int: ... + @property + def parameter_numbers(self) -> DSAParameterNumbers: ... + def public_key(self, backend: typing.Any = None) -> dsa.DSAPublicKey: ... + +class DSAParameterNumbers: + def __init__(self, p: int, q: int, g: int) -> None: ... + @property + def p(self) -> int: ... + @property + def q(self) -> int: ... + @property + def g(self) -> int: ... + def parameters(self, backend: typing.Any = None) -> dsa.DSAParameters: ... + +def generate_parameters(key_size: int) -> dsa.DSAParameters: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ec.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ec.pyi new file mode 100644 index 00000000..5c3b7bf6 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ec.pyi @@ -0,0 +1,52 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import typing + +from cryptography.hazmat.primitives.asymmetric import ec + +class ECPrivateKey: ... +class ECPublicKey: ... + +class EllipticCurvePrivateNumbers: + def __init__( + self, private_value: int, public_numbers: EllipticCurvePublicNumbers + ) -> None: ... + def private_key( + self, backend: typing.Any = None + ) -> ec.EllipticCurvePrivateKey: ... + @property + def private_value(self) -> int: ... + @property + def public_numbers(self) -> EllipticCurvePublicNumbers: ... + +class EllipticCurvePublicNumbers: + def __init__(self, x: int, y: int, curve: ec.EllipticCurve) -> None: ... + def public_key( + self, backend: typing.Any = None + ) -> ec.EllipticCurvePublicKey: ... + @property + def x(self) -> int: ... + @property + def y(self) -> int: ... + @property + def curve(self) -> ec.EllipticCurve: ... + def __eq__(self, other: object) -> bool: ... + +def curve_supported(curve: ec.EllipticCurve) -> bool: ... +def generate_private_key( + curve: ec.EllipticCurve, backend: typing.Any = None +) -> ec.EllipticCurvePrivateKey: ... +def from_private_numbers( + numbers: ec.EllipticCurvePrivateNumbers, +) -> ec.EllipticCurvePrivateKey: ... +def from_public_numbers( + numbers: ec.EllipticCurvePublicNumbers, +) -> ec.EllipticCurvePublicKey: ... +def from_public_bytes( + curve: ec.EllipticCurve, data: bytes +) -> ec.EllipticCurvePublicKey: ... +def derive_private_key( + private_value: int, curve: ec.EllipticCurve +) -> ec.EllipticCurvePrivateKey: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed25519.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed25519.pyi new file mode 100644 index 00000000..5233f9a1 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed25519.pyi @@ -0,0 +1,12 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from cryptography.hazmat.primitives.asymmetric import ed25519 + +class Ed25519PrivateKey: ... +class Ed25519PublicKey: ... + +def generate_key() -> ed25519.Ed25519PrivateKey: ... +def from_private_bytes(data: bytes) -> ed25519.Ed25519PrivateKey: ... +def from_public_bytes(data: bytes) -> ed25519.Ed25519PublicKey: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed448.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed448.pyi new file mode 100644 index 00000000..7a065203 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed448.pyi @@ -0,0 +1,12 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from cryptography.hazmat.primitives.asymmetric import ed448 + +class Ed448PrivateKey: ... +class Ed448PublicKey: ... + +def generate_key() -> ed448.Ed448PrivateKey: ... +def from_private_bytes(data: bytes) -> ed448.Ed448PrivateKey: ... +def from_public_bytes(data: bytes) -> ed448.Ed448PublicKey: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/hashes.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/hashes.pyi new file mode 100644 index 00000000..ca5f42a0 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/hashes.pyi @@ -0,0 +1,17 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import typing + +from cryptography.hazmat.primitives import hashes + +class Hash(hashes.HashContext): + def __init__( + self, algorithm: hashes.HashAlgorithm, backend: typing.Any = None + ) -> None: ... + @property + def algorithm(self) -> hashes.HashAlgorithm: ... + def update(self, data: bytes) -> None: ... + def finalize(self) -> bytes: ... + def copy(self) -> Hash: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/hmac.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/hmac.pyi new file mode 100644 index 00000000..e38d9b54 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/hmac.pyi @@ -0,0 +1,21 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import typing + +from cryptography.hazmat.primitives import hashes + +class HMAC(hashes.HashContext): + def __init__( + self, + key: bytes, + algorithm: hashes.HashAlgorithm, + backend: typing.Any = None, + ) -> None: ... + @property + def algorithm(self) -> hashes.HashAlgorithm: ... + def update(self, data: bytes) -> None: ... + def finalize(self) -> bytes: ... + def verify(self, signature: bytes) -> None: ... + def copy(self) -> HMAC: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/kdf.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/kdf.pyi new file mode 100644 index 00000000..034a8fed --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/kdf.pyi @@ -0,0 +1,22 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from cryptography.hazmat.primitives.hashes import HashAlgorithm + +def derive_pbkdf2_hmac( + key_material: bytes, + algorithm: HashAlgorithm, + salt: bytes, + iterations: int, + length: int, +) -> bytes: ... +def derive_scrypt( + key_material: bytes, + salt: bytes, + n: int, + r: int, + p: int, + max_mem: int, + length: int, +) -> bytes: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/keys.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/keys.pyi new file mode 100644 index 00000000..e312d51d --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/keys.pyi @@ -0,0 +1,37 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import typing + +from cryptography.hazmat.primitives.asymmetric.types import ( + PrivateKeyTypes, + PublicKeyTypes, +) + +def private_key_from_ptr( + ptr: int, + unsafe_skip_rsa_key_validation: bool, +) -> PrivateKeyTypes: ... +def load_der_private_key( + data: bytes, + password: bytes | None, + backend: typing.Any = None, + *, + unsafe_skip_rsa_key_validation: bool = False, +) -> PrivateKeyTypes: ... +def load_pem_private_key( + data: bytes, + password: bytes | None, + backend: typing.Any = None, + *, + unsafe_skip_rsa_key_validation: bool = False, +) -> PrivateKeyTypes: ... +def load_der_public_key( + data: bytes, + backend: typing.Any = None, +) -> PublicKeyTypes: ... +def load_pem_public_key( + data: bytes, + backend: typing.Any = None, +) -> PublicKeyTypes: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/poly1305.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/poly1305.pyi new file mode 100644 index 00000000..2e9b0a9e --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/poly1305.pyi @@ -0,0 +1,13 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +class Poly1305: + def __init__(self, key: bytes) -> None: ... + @staticmethod + def generate_tag(key: bytes, data: bytes) -> bytes: ... + @staticmethod + def verify_tag(key: bytes, data: bytes, tag: bytes) -> None: ... + def update(self, data: bytes) -> None: ... + def finalize(self) -> bytes: ... + def verify(self, tag: bytes) -> None: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/rsa.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/rsa.pyi new file mode 100644 index 00000000..ef7752dd --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/rsa.pyi @@ -0,0 +1,55 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import typing + +from cryptography.hazmat.primitives.asymmetric import rsa + +class RSAPrivateKey: ... +class RSAPublicKey: ... + +class RSAPrivateNumbers: + def __init__( + self, + p: int, + q: int, + d: int, + dmp1: int, + dmq1: int, + iqmp: int, + public_numbers: RSAPublicNumbers, + ) -> None: ... + @property + def p(self) -> int: ... + @property + def q(self) -> int: ... + @property + def d(self) -> int: ... + @property + def dmp1(self) -> int: ... + @property + def dmq1(self) -> int: ... + @property + def iqmp(self) -> int: ... + @property + def public_numbers(self) -> RSAPublicNumbers: ... + def private_key( + self, + backend: typing.Any = None, + *, + unsafe_skip_rsa_key_validation: bool = False, + ) -> rsa.RSAPrivateKey: ... + +class RSAPublicNumbers: + def __init__(self, e: int, n: int) -> None: ... + @property + def n(self) -> int: ... + @property + def e(self) -> int: ... + def public_key(self, backend: typing.Any = None) -> rsa.RSAPublicKey: ... + +def generate_private_key( + public_exponent: int, + key_size: int, +) -> rsa.RSAPrivateKey: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/x25519.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/x25519.pyi new file mode 100644 index 00000000..da0f3ec5 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/x25519.pyi @@ -0,0 +1,12 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from cryptography.hazmat.primitives.asymmetric import x25519 + +class X25519PrivateKey: ... +class X25519PublicKey: ... + +def generate_key() -> x25519.X25519PrivateKey: ... +def from_private_bytes(data: bytes) -> x25519.X25519PrivateKey: ... +def from_public_bytes(data: bytes) -> x25519.X25519PublicKey: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/x448.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/x448.pyi new file mode 100644 index 00000000..e51cfebe --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/x448.pyi @@ -0,0 +1,12 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from cryptography.hazmat.primitives.asymmetric import x448 + +class X448PrivateKey: ... +class X448PublicKey: ... + +def generate_key() -> x448.X448PrivateKey: ... +def from_private_bytes(data: bytes) -> x448.X448PrivateKey: ... +def from_public_bytes(data: bytes) -> x448.X448PublicKey: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/pkcs7.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/pkcs7.pyi new file mode 100644 index 00000000..a8497824 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/pkcs7.pyi @@ -0,0 +1,21 @@ +import typing + +from cryptography import x509 +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.serialization import pkcs7 + +def serialize_certificates( + certs: list[x509.Certificate], + encoding: serialization.Encoding, +) -> bytes: ... +def sign_and_serialize( + builder: pkcs7.PKCS7SignatureBuilder, + encoding: serialization.Encoding, + options: typing.Iterable[pkcs7.PKCS7Options], +) -> bytes: ... +def load_pem_pkcs7_certificates( + data: bytes, +) -> list[x509.Certificate]: ... +def load_der_pkcs7_certificates( + data: bytes, +) -> list[x509.Certificate]: ... diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/x509.pyi b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/x509.pyi new file mode 100644 index 00000000..418184f8 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/x509.pyi @@ -0,0 +1,88 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import datetime +import typing + +from cryptography import x509 +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric.padding import PSS, PKCS1v15 +from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes + +def load_pem_x509_certificate( + data: bytes, backend: typing.Any = None +) -> x509.Certificate: ... +def load_der_x509_certificate( + data: bytes, backend: typing.Any = None +) -> x509.Certificate: ... +def load_pem_x509_certificates( + data: bytes, +) -> list[x509.Certificate]: ... +def load_pem_x509_crl( + data: bytes, backend: typing.Any = None +) -> x509.CertificateRevocationList: ... +def load_der_x509_crl( + data: bytes, backend: typing.Any = None +) -> x509.CertificateRevocationList: ... +def load_pem_x509_csr( + data: bytes, backend: typing.Any = None +) -> x509.CertificateSigningRequest: ... +def load_der_x509_csr( + data: bytes, backend: typing.Any = None +) -> x509.CertificateSigningRequest: ... +def encode_name_bytes(name: x509.Name) -> bytes: ... +def encode_extension_value(extension: x509.ExtensionType) -> bytes: ... +def create_x509_certificate( + builder: x509.CertificateBuilder, + private_key: PrivateKeyTypes, + hash_algorithm: hashes.HashAlgorithm | None, + rsa_padding: PKCS1v15 | PSS | None, +) -> x509.Certificate: ... +def create_x509_csr( + builder: x509.CertificateSigningRequestBuilder, + private_key: PrivateKeyTypes, + hash_algorithm: hashes.HashAlgorithm | None, + rsa_padding: PKCS1v15 | PSS | None, +) -> x509.CertificateSigningRequest: ... +def create_x509_crl( + builder: x509.CertificateRevocationListBuilder, + private_key: PrivateKeyTypes, + hash_algorithm: hashes.HashAlgorithm | None, + rsa_padding: PKCS1v15 | PSS | None, +) -> x509.CertificateRevocationList: ... + +class Sct: ... +class Certificate: ... +class RevokedCertificate: ... +class CertificateRevocationList: ... +class CertificateSigningRequest: ... + +class PolicyBuilder: + def time(self, new_time: datetime.datetime) -> PolicyBuilder: ... + def store(self, new_store: Store) -> PolicyBuilder: ... + def max_chain_depth(self, new_max_chain_depth: int) -> PolicyBuilder: ... + def build_server_verifier( + self, subject: x509.verification.Subject + ) -> ServerVerifier: ... + +class ServerVerifier: + @property + def subject(self) -> x509.verification.Subject: ... + @property + def validation_time(self) -> datetime.datetime: ... + @property + def store(self) -> Store: ... + @property + def max_chain_depth(self) -> int: ... + def verify( + self, + leaf: x509.Certificate, + intermediates: list[x509.Certificate], + ) -> list[x509.Certificate]: ... + +class Store: + def __init__(self, certs: list[x509.Certificate]) -> None: ... + +class VerificationError(Exception): + pass diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__init__.py b/.venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__init__.py new file mode 100644 index 00000000..b5093362 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__init__.py @@ -0,0 +1,3 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d24749ae352cb8571758ddfd22d5ceae784aa446 GIT binary patch literal 217 zcmZ3^%ge<81i#(4rfvb!k3k$5V1zP0vjG{?8B!R688jLFRx%VZ0r{UnlD~3XtYVV$ zQ!?|?V?y)OLOc?avx{SbQgc&tlTwRPi<49Hl2c>!%2M;nVtg`_Vu~|MQgsV}iW1XP zi(`_DDho>T(~A-dGAi{m6033(OZ1a6^FXE*>*p7w<`oy`=*P!r=4F<|$LkeT{^GF7 h%}*)KNwq6t1zHYrUNJwA_`uA_$oPQ)Miemv#Q^4vJx~Au literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/_conditional.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/_conditional.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a60e57b9d4d1729c7c9128aaee48d98c2683a4ef GIT binary patch literal 7150 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 E3xQdnj{pDw literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/_conditional.py b/.venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/_conditional.py new file mode 100644 index 00000000..30cc3bfa --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/_conditional.py @@ -0,0 +1,233 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + + +def cryptography_has_set_cert_cb() -> list[str]: + return [ + "SSL_CTX_set_cert_cb", + "SSL_set_cert_cb", + ] + + +def cryptography_has_ssl_st() -> list[str]: + return [ + "SSL_ST_BEFORE", + "SSL_ST_OK", + "SSL_ST_INIT", + "SSL_ST_RENEGOTIATE", + ] + + +def cryptography_has_tls_st() -> list[str]: + return [ + "TLS_ST_BEFORE", + "TLS_ST_OK", + ] + + +def cryptography_has_mem_functions() -> list[str]: + return [ + "Cryptography_CRYPTO_set_mem_functions", + ] + + +def cryptography_has_ed448() -> list[str]: + return [ + "EVP_PKEY_ED448", + ] + + +def cryptography_has_ssl_sigalgs() -> list[str]: + return [ + "SSL_CTX_set1_sigalgs_list", + ] + + +def cryptography_has_psk() -> list[str]: + return [ + "SSL_CTX_use_psk_identity_hint", + "SSL_CTX_set_psk_server_callback", + "SSL_CTX_set_psk_client_callback", + ] + + +def cryptography_has_psk_tlsv13() -> list[str]: + return [ + "SSL_CTX_set_psk_find_session_callback", + "SSL_CTX_set_psk_use_session_callback", + "Cryptography_SSL_SESSION_new", + "SSL_CIPHER_find", + "SSL_SESSION_set1_master_key", + "SSL_SESSION_set_cipher", + "SSL_SESSION_set_protocol_version", + ] + + +def cryptography_has_custom_ext() -> list[str]: + return [ + "SSL_CTX_add_client_custom_ext", + "SSL_CTX_add_server_custom_ext", + "SSL_extension_supported", + ] + + +def cryptography_has_tlsv13_functions() -> list[str]: + return [ + "SSL_VERIFY_POST_HANDSHAKE", + "SSL_CTX_set_ciphersuites", + "SSL_verify_client_post_handshake", + "SSL_CTX_set_post_handshake_auth", + "SSL_set_post_handshake_auth", + "SSL_SESSION_get_max_early_data", + "SSL_write_early_data", + "SSL_read_early_data", + "SSL_CTX_set_max_early_data", + ] + + +def cryptography_has_engine() -> list[str]: + return [ + "ENGINE_by_id", + "ENGINE_init", + "ENGINE_finish", + "ENGINE_get_default_RAND", + "ENGINE_set_default_RAND", + "ENGINE_unregister_RAND", + "ENGINE_ctrl_cmd", + "ENGINE_free", + "ENGINE_get_name", + "ENGINE_ctrl_cmd_string", + "ENGINE_load_builtin_engines", + "ENGINE_load_private_key", + "ENGINE_load_public_key", + "SSL_CTX_set_client_cert_engine", + ] + + +def cryptography_has_verified_chain() -> list[str]: + return [ + "SSL_get0_verified_chain", + ] + + +def cryptography_has_srtp() -> list[str]: + return [ + "SSL_CTX_set_tlsext_use_srtp", + "SSL_set_tlsext_use_srtp", + "SSL_get_selected_srtp_profile", + ] + + +def cryptography_has_providers() -> list[str]: + return [ + "OSSL_PROVIDER_load", + "OSSL_PROVIDER_unload", + "ERR_LIB_PROV", + "PROV_R_WRONG_FINAL_BLOCK_LENGTH", + "PROV_R_BAD_DECRYPT", + ] + + +def cryptography_has_op_no_renegotiation() -> list[str]: + return [ + "SSL_OP_NO_RENEGOTIATION", + ] + + +def cryptography_has_dtls_get_data_mtu() -> list[str]: + return [ + "DTLS_get_data_mtu", + ] + + +def cryptography_has_300_fips() -> list[str]: + return [ + "EVP_default_properties_enable_fips", + ] + + +def cryptography_has_ssl_cookie() -> list[str]: + return [ + "SSL_OP_COOKIE_EXCHANGE", + "DTLSv1_listen", + "SSL_CTX_set_cookie_generate_cb", + "SSL_CTX_set_cookie_verify_cb", + ] + + +def cryptography_has_pkcs7_funcs() -> list[str]: + return [ + "PKCS7_verify", + "SMIME_read_PKCS7", + ] + + +def cryptography_has_prime_checks() -> list[str]: + return [ + "BN_prime_checks_for_size", + ] + + +def cryptography_has_300_evp_cipher() -> list[str]: + return ["EVP_CIPHER_fetch", "EVP_CIPHER_free"] + + +def cryptography_has_unexpected_eof_while_reading() -> list[str]: + return ["SSL_R_UNEXPECTED_EOF_WHILE_READING"] + + +def cryptography_has_pkcs12_set_mac() -> list[str]: + return ["PKCS12_set_mac"] + + +def cryptography_has_ssl_op_ignore_unexpected_eof() -> list[str]: + return [ + "SSL_OP_IGNORE_UNEXPECTED_EOF", + ] + + +def cryptography_has_get_extms_support() -> list[str]: + return ["SSL_get_extms_support"] + + +# This is a mapping of +# {condition: function-returning-names-dependent-on-that-condition} so we can +# loop over them and delete unsupported names at runtime. It will be removed +# when cffi supports #if in cdef. We use functions instead of just a dict of +# lists so we can use coverage to measure which are used. +CONDITIONAL_NAMES = { + "Cryptography_HAS_SET_CERT_CB": cryptography_has_set_cert_cb, + "Cryptography_HAS_SSL_ST": cryptography_has_ssl_st, + "Cryptography_HAS_TLS_ST": cryptography_has_tls_st, + "Cryptography_HAS_MEM_FUNCTIONS": cryptography_has_mem_functions, + "Cryptography_HAS_ED448": cryptography_has_ed448, + "Cryptography_HAS_SIGALGS": cryptography_has_ssl_sigalgs, + "Cryptography_HAS_PSK": cryptography_has_psk, + "Cryptography_HAS_PSK_TLSv1_3": cryptography_has_psk_tlsv13, + "Cryptography_HAS_CUSTOM_EXT": cryptography_has_custom_ext, + "Cryptography_HAS_TLSv1_3_FUNCTIONS": cryptography_has_tlsv13_functions, + "Cryptography_HAS_ENGINE": cryptography_has_engine, + "Cryptography_HAS_VERIFIED_CHAIN": cryptography_has_verified_chain, + "Cryptography_HAS_SRTP": cryptography_has_srtp, + "Cryptography_HAS_PROVIDERS": cryptography_has_providers, + "Cryptography_HAS_OP_NO_RENEGOTIATION": ( + cryptography_has_op_no_renegotiation + ), + "Cryptography_HAS_DTLS_GET_DATA_MTU": cryptography_has_dtls_get_data_mtu, + "Cryptography_HAS_300_FIPS": cryptography_has_300_fips, + "Cryptography_HAS_SSL_COOKIE": cryptography_has_ssl_cookie, + "Cryptography_HAS_PKCS7_FUNCS": cryptography_has_pkcs7_funcs, + "Cryptography_HAS_PRIME_CHECKS": cryptography_has_prime_checks, + "Cryptography_HAS_300_EVP_CIPHER": cryptography_has_300_evp_cipher, + "Cryptography_HAS_UNEXPECTED_EOF_WHILE_READING": ( + cryptography_has_unexpected_eof_while_reading + ), + "Cryptography_HAS_PKCS12_SET_MAC": cryptography_has_pkcs12_set_mac, + "Cryptography_HAS_SSL_OP_IGNORE_UNEXPECTED_EOF": ( + cryptography_has_ssl_op_ignore_unexpected_eof + ), + "Cryptography_HAS_GET_EXTMS_SUPPORT": cryptography_has_get_extms_support, +} diff --git a/.venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/binding.py b/.venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/binding.py new file mode 100644 index 00000000..40814f2a --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/binding.py @@ -0,0 +1,175 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import os +import sys +import threading +import types +import typing +import warnings + +import cryptography +from cryptography.exceptions import InternalError +from cryptography.hazmat.bindings._rust import _openssl, openssl +from cryptography.hazmat.bindings.openssl._conditional import CONDITIONAL_NAMES + + +def _openssl_assert( + ok: bool, + errors: list[openssl.OpenSSLError] | None = None, +) -> None: + if not ok: + if errors is None: + errors = openssl.capture_error_stack() + + raise InternalError( + "Unknown OpenSSL error. This error is commonly encountered when " + "another library is not cleaning up the OpenSSL error stack. If " + "you are using cryptography with another library that uses " + "OpenSSL try disabling it before reporting a bug. Otherwise " + "please file an issue at https://github.com/pyca/cryptography/" + "issues with information on how to reproduce " + f"this. ({errors!r})", + errors, + ) + + +def _legacy_provider_error(loaded: bool) -> None: + if not loaded: + raise RuntimeError( + "OpenSSL 3.0's legacy provider failed to load. This is a fatal " + "error by default, but cryptography supports running without " + "legacy algorithms by setting the environment variable " + "CRYPTOGRAPHY_OPENSSL_NO_LEGACY. If you did not expect this error," + " you have likely made a mistake with your OpenSSL configuration." + ) + + +def build_conditional_library( + lib: typing.Any, + conditional_names: dict[str, typing.Callable[[], list[str]]], +) -> typing.Any: + conditional_lib = types.ModuleType("lib") + conditional_lib._original_lib = lib # type: ignore[attr-defined] + excluded_names = set() + for condition, names_cb in conditional_names.items(): + if not getattr(lib, condition): + excluded_names.update(names_cb()) + + for attr in dir(lib): + if attr not in excluded_names: + setattr(conditional_lib, attr, getattr(lib, attr)) + + return conditional_lib + + +class Binding: + """ + OpenSSL API wrapper. + """ + + lib: typing.ClassVar = None + ffi = _openssl.ffi + _lib_loaded = False + _init_lock = threading.Lock() + _legacy_provider: typing.Any = ffi.NULL + _legacy_provider_loaded = False + _default_provider: typing.Any = ffi.NULL + + def __init__(self) -> None: + self._ensure_ffi_initialized() + + def _enable_fips(self) -> None: + # This function enables FIPS mode for OpenSSL 3.0.0 on installs that + # have the FIPS provider installed properly. + _openssl_assert(self.lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER) + self._base_provider = self.lib.OSSL_PROVIDER_load( + self.ffi.NULL, b"base" + ) + _openssl_assert(self._base_provider != self.ffi.NULL) + self.lib._fips_provider = self.lib.OSSL_PROVIDER_load( + self.ffi.NULL, b"fips" + ) + _openssl_assert(self.lib._fips_provider != self.ffi.NULL) + + res = self.lib.EVP_default_properties_enable_fips(self.ffi.NULL, 1) + _openssl_assert(res == 1) + + @classmethod + def _ensure_ffi_initialized(cls) -> None: + with cls._init_lock: + if not cls._lib_loaded: + cls.lib = build_conditional_library( + _openssl.lib, CONDITIONAL_NAMES + ) + cls._lib_loaded = True + # As of OpenSSL 3.0.0 we must register a legacy cipher provider + # to get RC2 (needed for junk asymmetric private key + # serialization), RC4, Blowfish, IDEA, SEED, etc. These things + # are ugly legacy, but we aren't going to get rid of them + # any time soon. + if cls.lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER: + if not os.environ.get("CRYPTOGRAPHY_OPENSSL_NO_LEGACY"): + cls._legacy_provider = cls.lib.OSSL_PROVIDER_load( + cls.ffi.NULL, b"legacy" + ) + cls._legacy_provider_loaded = ( + cls._legacy_provider != cls.ffi.NULL + ) + _legacy_provider_error(cls._legacy_provider_loaded) + + cls._default_provider = cls.lib.OSSL_PROVIDER_load( + cls.ffi.NULL, b"default" + ) + _openssl_assert(cls._default_provider != cls.ffi.NULL) + + @classmethod + def init_static_locks(cls) -> None: + cls._ensure_ffi_initialized() + + +def _verify_package_version(version: str) -> None: + # Occasionally we run into situations where the version of the Python + # package does not match the version of the shared object that is loaded. + # This may occur in environments where multiple versions of cryptography + # are installed and available in the python path. To avoid errors cropping + # up later this code checks that the currently imported package and the + # shared object that were loaded have the same version and raise an + # ImportError if they do not + so_package_version = _openssl.ffi.string( + _openssl.lib.CRYPTOGRAPHY_PACKAGE_VERSION + ) + if version.encode("ascii") != so_package_version: + raise ImportError( + "The version of cryptography does not match the loaded " + "shared object. This can happen if you have multiple copies of " + "cryptography installed in your Python path. Please try creating " + "a new virtual environment to resolve this issue. " + "Loaded python version: {}, shared object version: {}".format( + version, so_package_version + ) + ) + + _openssl_assert( + _openssl.lib.OpenSSL_version_num() == openssl.openssl_version(), + ) + + +_verify_package_version(cryptography.__version__) + +Binding.init_static_locks() + +if ( + sys.platform == "win32" + and os.environ.get("PROCESSOR_ARCHITEW6432") is not None +): + warnings.warn( + "You are using cryptography on a 32-bit Python on a 64-bit Windows " + "Operating System. Cryptography will be significantly faster if you " + "switch to using a 64-bit Python.", + UserWarning, + stacklevel=2, + ) diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/__init__.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/__init__.py new file mode 100644 index 00000000..b5093362 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/__init__.py @@ -0,0 +1,3 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4b78eb9542daca01def5a2ea2a2fa2a1b5314517 GIT binary patch literal 211 zcmZ3^%ge<81i#(4rfvb!k3k$5V1zP0vjG{?8B!R688jLFRx%VZ0r{UnlE2bitYVV$ zQ!?|?V?y)OLOc?avx{SbQgc&tlTwRPi<49Hl2c>!%2M;nVtg`_Vu~|MQgsV}iW1XP zi(`_DDho>T(~A-dGAi{m6033(OY{qhGIKLaGRsnn_2c6+^D;}~)be4*dfF-;Yi~I6sNfy@bau%@C-aKz1EVG zFyu=3?mqK8KN_S3!PQ7asVVVb%6Ko!VU(p6zz-*XoVc-u7p#+mJlyOFYNA@EY!1xBZky!EJyw8AFtH{D=8xGm-?xcp)4i3+A$L#QIGBjAJ10Yh>dAoqZHW>(M4 z(sy$+({!_vktLk#q;LzuIBp!h$&BT~T#_fpyl~rVa5QrRCS~132LD*wfw5 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/_cipheralgorithm.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/_cipheralgorithm.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9d8e820c21153d4cf267a6b3c9bf27a2124a5497 GIT binary patch literal 2124 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/cmac.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/cmac.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7cc769e94223886d629d6f9bd54cb6e61d87ea64 GIT binary patch literal 437 zcmY+Aze@u#6vva^)s+4a#Kpy>E_U#`OA$&%9n_)favX%*U3yKu%NrdK;0DPOGu+kRbx})I@gdl`5 zNT3U$;Zj^mEZ5d-MbIr%d$d=7R+me^HdSVQZ99g(u{H`EQ8(1kcjz(}X5I6;uY42h?*Wlux`{=6jMU zdX{MsiKz5;uW4_uX=j2ZOtA@-ZL`eDrkhG9NyBkWFT}oHsXrFTu1+fpLb$2|crpjg f-B^OF`Ttnf4qi`Z=nEY#(9r@N&urtOuBZF~1<8La literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/constant_time.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/constant_time.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ca56697e4828d5e5477380fbbbddc6f9680d4f57 GIT binary patch literal 783 zcmZ`%J#Q015S=}rjpHLW5;9PcOE8LDU}H*x5Ctd{C

    qb<%0?Zewra`^fIvk}Vez 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/hmac.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/hmac.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bf9eb42e7c6bfd08263a59e30fe3dced165375bf GIT binary patch literal 614 zcmZutziSjh6n>N2+r1wNXl#U_kl1*Id)NjMBq3g*7XE0Kg<)>*Wp~cq*=1(#$OVg( z`46;Al_1vsAEz7`wmPt~3#5yUGdUM8;N#8A_ujnszHjDiZLI~yen0<;X9VD<4JxZG z0J;2Nz(*LsfTWO-fDnsU(v_?hIM=wA)-yM74R&G@c<2lp)sSJcLO~PV;WeAhoV2U_ z@`=q;qvDHM3o{ezZ=mD;vSEjmZ6-vnndZ4rCiLs4E-^RarlDwL&Y^dDohcJQH9Hrx{H@||4Hgv4Sq4XYCOsE!6?P2 za@|ncPgSYeE^363ix!XvQ`lPeIqXeu`Z+wF-t>9<_VL3bZ|>chd3R^ty(8xw+!?I@ WfQ|34@oD!PY|dbFTDiPs2>$>wqOO?$ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/keywrap.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/keywrap.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b8cc21f6af847a1fab8be40eaa58ebac2e0d82f2 GIT binary patch literal 9140 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 TII0yQJ@O5v{-sJ5Jud$Zr~Yfu literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/padding.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/padding.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..772cfbeb0fbc49266cd87f082421207e1123cc47 GIT binary patch literal 10341 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/poly1305.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/poly1305.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..378ef337627b46bddf13e22b16662c47bfd84c8e GIT binary patch literal 449 zcmY+A%}T>S5XX1h)P$z>CSIkU0-7q~MMMxpJ&1@Omk?OC$u`}Z?1tSk}eXNRKh45TP31O z)I str: + """ + A string naming this padding (e.g. "PSS", "PKCS1"). + """ diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/_cipheralgorithm.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/_cipheralgorithm.py new file mode 100644 index 00000000..9d7f5bc7 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/_cipheralgorithm.py @@ -0,0 +1,44 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc + +# This exists to break an import cycle. It is normally accessible from the +# ciphers module. + + +class CipherAlgorithm(metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def name(self) -> str: + """ + A string naming this mode (e.g. "AES", "Camellia"). + """ + + @property + @abc.abstractmethod + def key_sizes(self) -> frozenset[int]: + """ + Valid key sizes for this algorithm in bits + """ + + @property + @abc.abstractmethod + def key_size(self) -> int: + """ + The size of the key being used as an integer in bits (e.g. 128, 256). + """ + + +class BlockCipherAlgorithm(CipherAlgorithm): + key: bytes + + @property + @abc.abstractmethod + def block_size(self) -> int: + """ + The size of a block as an integer in bits (e.g. 64, 128). + """ diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/_serialization.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/_serialization.py new file mode 100644 index 00000000..46157721 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/_serialization.py @@ -0,0 +1,169 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc + +from cryptography import utils +from cryptography.hazmat.primitives.hashes import HashAlgorithm + +# This exists to break an import cycle. These classes are normally accessible +# from the serialization module. + + +class PBES(utils.Enum): + PBESv1SHA1And3KeyTripleDESCBC = "PBESv1 using SHA1 and 3-Key TripleDES" + PBESv2SHA256AndAES256CBC = "PBESv2 using SHA256 PBKDF2 and AES256 CBC" + + +class Encoding(utils.Enum): + PEM = "PEM" + DER = "DER" + OpenSSH = "OpenSSH" + Raw = "Raw" + X962 = "ANSI X9.62" + SMIME = "S/MIME" + + +class PrivateFormat(utils.Enum): + PKCS8 = "PKCS8" + TraditionalOpenSSL = "TraditionalOpenSSL" + Raw = "Raw" + OpenSSH = "OpenSSH" + PKCS12 = "PKCS12" + + def encryption_builder(self) -> KeySerializationEncryptionBuilder: + if self not in (PrivateFormat.OpenSSH, PrivateFormat.PKCS12): + raise ValueError( + "encryption_builder only supported with PrivateFormat.OpenSSH" + " and PrivateFormat.PKCS12" + ) + return KeySerializationEncryptionBuilder(self) + + +class PublicFormat(utils.Enum): + SubjectPublicKeyInfo = "X.509 subjectPublicKeyInfo with PKCS#1" + PKCS1 = "Raw PKCS#1" + OpenSSH = "OpenSSH" + Raw = "Raw" + CompressedPoint = "X9.62 Compressed Point" + UncompressedPoint = "X9.62 Uncompressed Point" + + +class ParameterFormat(utils.Enum): + PKCS3 = "PKCS3" + + +class KeySerializationEncryption(metaclass=abc.ABCMeta): + pass + + +class BestAvailableEncryption(KeySerializationEncryption): + def __init__(self, password: bytes): + if not isinstance(password, bytes) or len(password) == 0: + raise ValueError("Password must be 1 or more bytes.") + + self.password = password + + +class NoEncryption(KeySerializationEncryption): + pass + + +class KeySerializationEncryptionBuilder: + def __init__( + self, + format: PrivateFormat, + *, + _kdf_rounds: int | None = None, + _hmac_hash: HashAlgorithm | None = None, + _key_cert_algorithm: PBES | None = None, + ) -> None: + self._format = format + + self._kdf_rounds = _kdf_rounds + self._hmac_hash = _hmac_hash + self._key_cert_algorithm = _key_cert_algorithm + + def kdf_rounds(self, rounds: int) -> KeySerializationEncryptionBuilder: + if self._kdf_rounds is not None: + raise ValueError("kdf_rounds already set") + + if not isinstance(rounds, int): + raise TypeError("kdf_rounds must be an integer") + + if rounds < 1: + raise ValueError("kdf_rounds must be a positive integer") + + return KeySerializationEncryptionBuilder( + self._format, + _kdf_rounds=rounds, + _hmac_hash=self._hmac_hash, + _key_cert_algorithm=self._key_cert_algorithm, + ) + + def hmac_hash( + self, algorithm: HashAlgorithm + ) -> KeySerializationEncryptionBuilder: + if self._format is not PrivateFormat.PKCS12: + raise TypeError( + "hmac_hash only supported with PrivateFormat.PKCS12" + ) + + if self._hmac_hash is not None: + raise ValueError("hmac_hash already set") + return KeySerializationEncryptionBuilder( + self._format, + _kdf_rounds=self._kdf_rounds, + _hmac_hash=algorithm, + _key_cert_algorithm=self._key_cert_algorithm, + ) + + def key_cert_algorithm( + self, algorithm: PBES + ) -> KeySerializationEncryptionBuilder: + if self._format is not PrivateFormat.PKCS12: + raise TypeError( + "key_cert_algorithm only supported with " + "PrivateFormat.PKCS12" + ) + if self._key_cert_algorithm is not None: + raise ValueError("key_cert_algorithm already set") + return KeySerializationEncryptionBuilder( + self._format, + _kdf_rounds=self._kdf_rounds, + _hmac_hash=self._hmac_hash, + _key_cert_algorithm=algorithm, + ) + + def build(self, password: bytes) -> KeySerializationEncryption: + if not isinstance(password, bytes) or len(password) == 0: + raise ValueError("Password must be 1 or more bytes.") + + return _KeySerializationEncryption( + self._format, + password, + kdf_rounds=self._kdf_rounds, + hmac_hash=self._hmac_hash, + key_cert_algorithm=self._key_cert_algorithm, + ) + + +class _KeySerializationEncryption(KeySerializationEncryption): + def __init__( + self, + format: PrivateFormat, + password: bytes, + *, + kdf_rounds: int | None, + hmac_hash: HashAlgorithm | None, + key_cert_algorithm: PBES | None, + ): + self._format = format + self.password = password + + self._kdf_rounds = kdf_rounds + self._hmac_hash = hmac_hash + self._key_cert_algorithm = key_cert_algorithm diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__init__.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__init__.py new file mode 100644 index 00000000..b5093362 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__init__.py @@ -0,0 +1,3 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..da3ec66790106219a86bb85cc62b1b30c07c9fb7 GIT binary patch literal 222 zcmXv|y$ZrG7)&gR2*u}cu-!$R1Rcb|pDj>g`dL3TZA@aJzKD+??)pT&K%rY*OhIqB z@9w@E?(X|N;_#Wh;OXwWF@MmXs5(yENKDpbK$j1qTh3R_vp!EpOk^>p3EO7-&76y) zVJnazcc8%tNCmJUhcssk+%ba|hRT(A0)`1)D4Qjkt3weU_*HTnDvc5?=3qi@3Ms*A m6k!x$iZ+S@Rn*B;#Mf)1Wj22i{2=jXEot{=DmNo(_j{D3#|O1cf@c%%^W6)}mav`Aa2Dhjq^tynb%|M6D5 zov0=SFVRZ1)77*>XmT$j)$Gm5R&_4G7b9a|H5=gPeED2}pZEFs7}+Lf@*y!(G`0tJ zyVpO`kK=?qfuDO-3$##OpoPDklbp%_fbN3qc?@%X0zdash!`mYBh9^Vq(!<|U80LK zjI=0qpE^<&M#{Z#q#`X=OSCw{NX4^8GGlkhM*iQ}y`eZcz0>L1x@~nkdBo@qEL?UhGVFu@%{LPPkuQR<(ZOXWlV$|-lj^HxuzHZaobYS><2_|40>{gCb z&;XBCKuc_RJ*#@xHtkRb&v8}nn5wG|+A0j=E3Ej^JNsl`aT1)ib~$QRPww9Qbyu16^N4jyB*FL3f+OAVZxj{PytyS*R&i&eNt$K}HHoejVA-zF)&0vF`-EA=Ap|o--;I>JK!^xpl^8mK+rNzcp6q#SXPk_tbs(rT&B95dmJrL<(GINkz zIf})T`6D99vp7ku`s^%8&54^d%1APnLC%ttkt&3;u}pyNnuZ1e)Xl*ZbfcwnZUDo- z5^hU5{ueYRQI00|y!=RrS&ZUb2=!6{`4Z%=FfOJ85@jxM5N7FC7Q z^!ZdT&j4g;+#1qhX~Lk2Re@qcL#nZFGf1u~gtWf@mSz&oHHNDm7 zGC1_KPc}l&+@^y&ljS~Ce%?by0tT1YDfy9M0uXV&kqFge>=tx!d>)E2uPU3DQ*$#n z9!jFqcKcAT4+T5yI^4s)i!6tz%zhLU8QAd!=wp@#C4 zaR&8BGS(wGqR*|fL>*ejigLFPuW6v7WLT<;rFGUPUw%~Fmmih7)xlROyrQu_l$q#5 zP9B?@_lC+@JMA%WF7KTQ!wSubnN6oSei7nhA4AVzc$Q*V_d4nKKe+KbC;~;9;amcz z^hN&w@e&9PC&OsN;_%u@c%6fhE6;QhVc`Knq3`8UnV{#KWPan;-S4u`!8Qyzeh=tT zTu~G_E-617k@d;%Q<8lkK2OQ5QSf_6-W~c9dF2jZyOTjc;xX{xj@+K9=}IA?oWRa`BMlz9*&cNa@QOns@bE kvUNbVMr7+K^%|;-64yxJKf})FV~MIV#Y!*~zQT9^3j!M?W&i*H literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/dsa.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/dsa.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cb30a6715152ceed18aafeaaa45b64d89672493b GIT binary patch literal 6759 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 K?iz%)8~+P9F2=I} literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ed25519.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ed25519.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d0d3e0a30971cd5ad1c524b3625a2bab45d60f65 GIT binary patch literal 5560 zcmdT|&2JmW6`$poNQ%;uvMkw>)2!t*5gnCsF`H4{rN%R!PAs=^tH1q~Zxy5nZ{Rt7wrWlJET|4(A1{SE zQ!&eW%~;4stik1)v01O{%%s|EWld*gbG>RMMg^MvvO!r{sgxUB zfa)%Zzm8Xgqrbw#SA>$HppjyPMzvE~>`Ck?^zI=azlt#$-$=Mm+Mt#Sar6W@PHX89 zM>4=Mr1gb3QUQ)(Ef?ZQYXjh&Ggfw9o0^_}@5+PCQl+eZOt-C=rkIKqFKwIDuo8@# zo2;frT$SNB1~(Wj9Q_#@kZuB`7^K@DA_Dm`veVA#O$s`}7%_XiAxKO!=|62a$xO&o zkhJGX`=elb=|sqeH-D#Xt}o?FA(#wHWH+|JP#DIwq^O_Mn$~!q+O|t&LxS9pynK*K z+mg8sy<3zSkT880M#y zbC#05H5j^)p|zH@ys)(V;KBXHhx0e(2g`H!?%t3;p8u^pd++xB#k&vhd}3wTreVsC zWUI#!X606yUX|-SbTSXvZq$mZ6@y{1;42%Lo{}UT*KdBfqUu_?wzjgYuRgp3J}_1m zX_Zz>lu<*aHI=RuwrFi@OaD=Ko<{x$znyOce;i0?!zw`7#{h9K`Pb)tEXtTVfRA|kVOx-cf&dTvc<%^FL}JviuUJvoR!So|Q7nYc&N57qwywdX1hS zUhjDJehQU-756`c%@xzBc0S70W^dz?xYvU5NkH8I8I9qP;`YD#!KJ5_)Na zs-_hy>3Stlal40T%v1TsI)&XV(MOwbM49cm#GRav*xFu1MX?AMi@8BKOZdew?z7*L1Sb&VGvE2@-Kt6wP@CR0?? z899%#dBWteRX~EN$Ww=>AUBH>#4^U;f!Lb|>GOED6-mWsTErzUqa=}g@|oQ`L=vfH ze7F_qiDz2GCCGBd>mG19GBT;lU!Px=Hr-c;K>9x%a5fiD#9E)|UP zE~l&sNB@AX0F)WfA|VJ7;}9nv>W|Zee?9}m=?QTp101Kd{t!nhz%itWA&zu_V_3_E zIC`}lhd4QR7cwYMCIyVcQ!7veV_+~Z;!nBd9;Oih(+K|?mFSk;Ksoe+_5TDw|J!g4*f`0~S^F4eL+E$hqyQ}JN`;YV zycLdAc=BDG`?I604-Ul-zBLcTnWi|ipPccFOkj6)Kfi8z=NCc@*9P}JMAG04-2%Xb zrr2P~_C*I;vTOHSXk8nKNIM_`QoV7`747Z+fwktCaiM*~-e zByw;-A7FVbjdq$f-t6MAc81STpa)-05NQ^$0`OV~nCzy02byeO--DAA(t_^0b37k{ zm#i}{asf*@y1eic)*{nt&|)l@?$teR=RJ#;07Du)fAPIK1SB13hJ`Kw&0>f>8$)5; zu)hl2egNR#3>z!`8oI+6jrTen{P<6HWI4Nz;xH}P91@PZI4+xn$FM*g%4gUmH`@D{4bkj%hsd=Dgqw=N^zvPm1>y4(W1l|$rp z4aaTLHhvAqZ9L{eC=RAxgQJp&wOr!!V9%f{$AxPgxcNLM#cUmTj0Y!+pmuc=-&bUr zVSVTBvxeJWy9@O9D&@7t@XvT_EWqOa6;ZC?d%jVS@oxi`K!Jz@tY38F_TS?f{;Oj3 z%+B5T1mGbDz*dscwX$JS#z6!RQb+WTlQT9T{|&nj^Km~INLx`s5CEeJ7xu|m`}YM& zKjxnoWNyFP_c^(>AN)QiSN4P7R$^R$V1>!fsc%Mk|4STv<#T*05Fz)BoINCGzn*B0 z6q+L+9gyoya($m%ZzZNtTA1uy_~u>S{}KmZ`5bkSHt>v$9Fmc*XPTpv&C%HdGS_S~ Iho6Q20h9L0mjD0& literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ed448.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ed448.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..71975c84edac0c2f13692b19f75ef330f5bcac1c GIT binary patch literal 5649 zcmdT|&rciK9e-nwjcp8L2mu;MGtf4R+tef*qAp~YECiBlmnA7bBGpBjjy(@BYkQnG z1G~6e2~|1tKiC|4$f2S|sj9u~Kd^_M4YCw8(n?W#>dg`9gAy-I9J4O2q&`wA)gbCXhM;cgsdQ7J5&s1 zL+~3ehD%~rEJd;r-Y*uTrH*Wjwk4qhJsbmCPkt?qek zV&a_#+qq&P{~_JAL`^kSE0WtasbNJKHMdzg?Ob&3{bGTJ>#;mdgc0hP;s7T#$3SvbhPpJCqraEV8~X--kq4US7zgE=X}DFmxe9OD%bIae4K@gZoP>^K;6B)!Bs) zZYv+o|5BM*xO;!;gOz(9SxL5Sm`Zb9E5etude)ghJ}tgY(nEBC;9V{M6+Xemb-HS)Bar)!xVTHaY(DCE|Rf=Pc`0VZ{W z8f)#wj@!nLS6HD`Fbg}>7*~zmQi+VGa>K9VjUN@I0ttU<(h_t(9bk5hABrv~e($(NDvx$aj4NP~pCy8o3Rso}ab z@?5%pBwhbv?ogVnOOv(OkQ&}I^<)px5XVkm~ZZL zT$5m(k;sHsAEzzLG zb#?)kWWzw55VApdu#)ZJt`7Me+&(x2>?f$$9{;fKK{M}GW_UPT`(L}-p!Q7tZRA1hYUZ0 z$!rt}8fV3g!bVwzQbjFsQ7_Xsh}B!JwGW}Puj8JFkU7ivl}?Ab((E#d#69MXO%!Sc ztWiDhQ`_#of|FXxMsyIxtf-#bqIuI2bGlyiRM@k_GwLdQdy~Q*mg%EyIFQWtEaDDM zhiqMcjA~-hlbddiDhhq1C;=_)?zcT!E~Z7hmLP6mSbJFn$7?8LG&Bf`m&zN2NRA3|7i&i7JYfP?VCcZ5OefR1`G0IntRg zs)hlzXH(aB$+5y}E^l?KIm2XX-fWJH;MzP{(%8x%!6f8q!;_Dj#R*~^<0~Ncwn2Iv zNi{<8$W((k zc(5n&20ZRm+dLjH!HR<~RPHX;2iE1`cCThl6HfjHT^{VxtAzrXLFAYw66lZ6XzNG@ zOw$qIh1tiNT8mw^^VO{po@(fZ>i-FE ze%oO6+5pMUSo;KJ{pfexpnxdsQuQ7@R7d@B3Qqkw&iu~7)x?oB@x{uaG*y?TYO$$S zjq&WPvk$LX_wYh&;XNf~4Gzy8KuKtbjgV|V_#l#9xPOSYwPA-u6FWeXS1o+|LTzu@ zDAei$G>dN_@MfZ@&TH#w+BXM^-g5g3D@tXG zAz5}C9u1TXx!gn}UGN@(_1Vt$>P5e!Ji|F$ZWPHIf?4LV0T81P%$}vZ56!l#=fc@5 z@}k~y=2$uaZ<#+qdpw44bUX4|Tal&Yu^0ZXumRFL&>aM3ytm20&-?&%L*SK;`4WxI zq7aM>n?u4O7>8)%$ev_ZvG*Dhjt#G4>n0McLu>-c4J5aa%pkdgD8F$7@_X|01jeU2;# z$8kj0;_-Cb1rm+6#82U$hI9|&+4XIFO;Hqvm7P1$8fbsZ&d^Wuly7gNb+%ih9v0_c zhe8=&>y3(a8{Gdig+rKYJVvm1bklET<-(zy8=KUU% z$(r}uh>i&mmmqm!{NXpe|0NE-YH>Uih}gOJv){k_WZ*D7QV)+bh#=fL7JHwILr3D! zlZE-}B*PJgpYDTbmd6N7G_AK9Q literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/padding.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/padding.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..682e0d94f9f9cdac94f9f2ca697c753c7231a6ef GIT binary patch literal 5598 zcmb_g%}*T36|er7VZH|j4Cc#j7CZJhW{}tGcuh8m$H3w*KIFlx4I*kc(+!M0Ut8TE zGh&m`$_FC(;FT=d7fX9tXNj{?4p}LGMo+|nv}6e>$-%cl;0w9rz3QG%aI%(C)BU>o zy*E{_UcL9Ls{TVT=p#`6J@JD!?kD6Q_);k@yTa|A=LmU5RHAZelHuk!4(oiHpX1>v zq=k$)Co-Oxc4gdiZdP}tTQZ(G4@Y=1K~(o6qPA%6mjWTL;I_-0m&rUJ^SPi~x0a^ZHMM*mn5ucl64?8-@kB!VHb7;=|-Q42r zbtU;gpTDDJw9JA=H9e_iliGZ2Rm-l<-%c&e>nTGU%7c=!r0MfXx|TO`OH|1(uMICN zg^Xeh=V>aFGE%FWKCDznJe;?O9Luj!4|K~&D^&D$AjRr$+uv6l!ygS*wBFM_K6z4k zcw5UZ8OsGJp=FI!R!d8(N_s_;7IRd(HyQt2zCAuQF?;=9Y-&@aUhD{Sf45LwI$3=rB@AstZBJAu?$E&jx;T=rj3`#lYJ$?+8<(Me8s)Hx5jqpv2|YMAFy_4*r;MH z_*!UgbDf9rRP9p<_*$GQT&weqlv&XYX+e{etOQQimNa@^swMP!sUZ%}OOWrFIuw_g z!l|PgDrhu^YD-j842{O3UQ3j5UVJG%mDLRe;Lj4EFBR|GP1^g)Jl7W86@>QCJ^@lDLNN5! zM*^Ks9(;STqwv3KU#{6ZAHe+z}QaTnGJEv(`~Yg zWnZ#7)nE_SS=b?9L)ek~@U%;UY;seZ9Q^=Z;lYN0>h?&P0}3rTNO0-Tfxm|#S0p>( z_Qz|c=Q!(YD(bd9)ekb}F4}{&lSm{Wo4j2|c{J1n*lb=bUo8k27Fr^kcQ#YOhM=GU zXvGT4a@|4=Xnz*Do;=OvHEOKc_B5>k-Jn8|NO0@xKx!*Mk!-j1KI!?o?`dE0=C;3e zmw*MHsiz6nxO5#XajJVF0Nh3K++##4xS2xU3oB~Hi3 zXAt$qhp<+gGRv!^mvS^^EN2cn?CnnMI_!Gl6|Ut|Zq zok5*i=Ks$0oOn-^VO`Rn9@Qa&Y{A1i1dy3Ul_4a!b!&tc=HbgILpReaK%x$`Fm4PP zo@RVOykPJ^FJg@~!hpRA9xkC2$yK=Z43HW;u-q?;epg?aG?E@C-%nz`+oUevPnO;9 zhX>ey67Fh&tirUQGkqhx5q2_xuQ>)5+{ROny}22N=Iuyt3hglz zAo&g4I;KHwmh0BNvM9PvmB~AZJ@wd%B|Om94o<<*H+ClxpP{K$*m~X4)?j6*@KzSm zsU)zh5F&03IVlTJwlg>dEj7$A0y>-Fzd)sFhRM-0+`x5Gg^)%5(Bgvba>@~l3%Ori zOjI6EC#q0@`TUZHg@(IdU0MnNfvSk~OJQA5T@Tp5bp9snr`ItF-BX3L;F|hfE;vZa zGjHH770%Y^D+!d|V6$&45g65F$?8uk>EucptdTRyLpiVO^=BJ;2b7oK)^Y0(%ajMV zqsbSeTYW>{>s!OWGJCI<{P8V+9C2@qdmZXBk6$Z=Mz=zvre|~~*!p<>dAtu(jhN(0{Z)2zTtCe0A!3H5U1aaqWFC&gNOM88$dlr0D9+8ubH6UIn;9mo_-EC*@ubg>)l26eoc0j>qOnd#Ps*= zB746k`;g;KWB1ME$>`HtjE{DlMmro0PYVa2d6;Zm+(qtwP1NDzy2|7oga!V804kiC A=Kufz literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/rsa.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/rsa.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cbb6e2146be7c806e7f5834dbdbfd3d3c19f1573 GIT binary patch literal 9363 zcmd5>TWlLwdOpMZO_Zz)C0n*M@>O(VI*KhXvbEPyd`Ys76~|VbT}JI-$T^Z|lN{>I zP_ejFstx=g83D>I3Pf9M0q;w?Y4*Vjbb;;LzV($hR74oSfPrFx%|0=3_C@VO|NqQ| z9FmURq6Io6f6koqpZ}cyT)zK1Xa2FLCqm%*k2ily|7IT{|Bes#yuq72;i zr}rsGm7%-7^r&)78G--(%A_(1{|A($asd9vl;g@6{EsW+X;FDeIRy6;isuGNzWg;B zObSL+E*4c?)^lo6n}uiZVpf5_pjx6uP0J@eMqJV;%gOm%g=-msC0Sdd8Yu0V(N+ru zs`S>+}j;H6qzuX^AqO-q8(zW>u$}5iFTK$3oz-5nxm=vtrhn%8-bY5}t*p z0l0zXC4gm5Pu8CF?A)UP(^IklyWp@zaUAk;nQe-fyKZWi-XXx zE-wVX~*lt4*d zq}n`hg1X4$($eb5CAm_N^^+x*E9CUt3e`@^&O|xMG&xmTHG+!S?8=aFCVcqE25SJbo48ikZDUGs&f@;%4lIp~p0P8ajExTr6Q>Vnxv#S)o+GT*i-wDUx8@a`zIdQSd zc4v}4J`{{M59cZqL1YuO^t)Zdv?ExcIVgLY8nb1b(%K7*%t@!E*ZIQK zM7bz-7;0~K#~}1tBPJEinkxsIHeiaR+Ol79w>$(ZkFU$!VK)?~E?F5yU_oWDDo zypKuJa#_w>IbJ!FHR5tc)0v#rA?z-x3PXltgaGwR5LQ;%C>kC^aR|jx6em$2vT<vrjBsdp>4P3(07+~2mxXXbT;4WkT zP3|)OT<#(&y&b&6&0Qvt9JVneH+MPMjk~zm%^@U|Z8l=ce&8U787>YZT*}K3mx0po zMbx&iUVzCoG1fvFGaxJiaVUz8@eZu;nz7+EXoHK#m{B2UL0x4K@xhM8DJ%6&EaZd+ zh710A!GIwHH+~9r zmAu&!&q}+RYJ@TD%Rr#13D_cLBSIU#S+z*B)I$D!*q zt3nN?L%{16b458Xq9fu0Qwy9KJAQVoHj9aI-=4+9MwwZKghnMa3Twa`kjkXX)$hx_{k(Pc?$8zVFECs@K6BP13ahS~^%6W|#VI-47u!}~znvSP2JMW;YA!gx<}gPi@g znHEvK$vrN@Be0ZanI^m8njG(%)_vStb_I>_)OWCa51Yb-S5cfoaT>)mioZa?*%T)j z=kf6k6qixFjbau>8_U4>z=H&;X(KRF|6f=}5Lt#Tnk)lT`fZjGMjcx;bucAi>)1qv zQmuHhcBO#gSCBgPy zD#;AUtPWsf#8_F=CF?NB@ItOJxJZkX!IoCCnLI>G2ng>&eI|ju26wK2z&^k{6q}fJ z0>nD`bAuv2Z#p6D%`$VV;iuX3?LxbF!zIIK8088@ECOuzcML7X> z!xgn{bj1SnkC>q%g^f04;wf+*S^r`Qq#F>0S zg>n=+eHCVjs4c1GJRJHgsj5azB@xWgi5wi6lFA{Qk2uxIcqk%+iRr0VPrwn0mI4YK zxhdz%^b%t#1GI9+qZJkzX9p<$7Jk|#5U^tiCbn+XgOl)m93N?Tgr4)?c)h)mZwUz4 zLxdx+2MG1m4t?_R`p2MA-}{4y@$=j9^YzgAhL?mA>mTzGG6ZS}1=kQcllc><2@k*K z!JjqHnir?ynt#n#^(&s+s0F*K)`6=+j(e)}l7Y2g)l&^ry%h+_6*$vg3swEqVAWd< zE%@fa&YBObqJ78igO{O%PzewmPH*L19$Bv9;gQV5tL40&E5UIR4ATk~-!5W^r76)q zF1RCVDv%CrgnOIYZJB1&yH?>2>Qb#TN7K? z@AucLn=#DY$kYxtf&|TAX)qm&*M!Y8>sPIzEHMQt?LL?XA*T(Qgeq|l7j(8zxy-xh z0xW~FPB}%naD7gkTo#WX7f(zj#Uo-#T)|0eav0zkcsN!7+E#*-8bw?-iA+-9T>+CC zJAyZ?by5RL0cvHLF6EXBC3XvR{t12>5(B^)aBZMARg*W*eR{6$8!`Rsv%$;8X_u!C zvY-h>7C;RFr<*m6Je9?+p0yhV2PaG72@zavaTAYJz*TOcqr{|=zVnj}=ki;cf1ZFm{GeGz4Y0S1*_H^h4O)zAS?HOIMghO3#DGBUrvL z#E21)W)3sphZnHPr+9F{Azz`Cq(Q>yv^ zy#TAM=bJiCGwT9O3&IkDl;(Rdz_ySg+~!*BbTxzl4kw|N@{+53Nb$6nhq7k76FPcp z*90~zaNoXQ*TRZ_&0maGgWxsH`_{HTxLFNADzI4YU$mQl4@%&9uO77Pfqo0Lhg2QW z&bnYxh24i2B_)19@#MZ-K+J+rTf~!cZmp;S{xhCj6!ni((K4G7=kR2I zpNNwug@r~m< zv7XwV&C44C@C}Svc6uXDdI#6v+zExDKzyh{;{M*PiGLeA{b=9m`o7apY(sbw@2wra zx3sbJcpy<*hA{Zv&(8kc*^P@&dIxID_f|Jnx90B4znb_Z{d;Lk`t87jx!+CwPX5jK zKac-@=F!xp`qZUA2guOKmTznM=b`%(4+jr#4<4=wJNw3J!JWP#yJa(t0n*!NRscCb0O?J%H>)uQA*n$G|GNUGQ&%6xXSd_C_0a4eqI)1{zqfhz)3ZOlxIVMK z41vBT+&iv4_!P+tFi|8g}4@9lhBN=v>%Pates2VcSz3J zdnowU5tkNhXS-?g{EKEjpBub9k{NSP!}Bo>%JaC)^AWK-^AYmQ)TU-@`DT8%@*#7A za{JAe;8bm?NyC;L!~^(+GM*tx5<}$V+h8ML?zjveyk%M9>%chJ`pz?DzVl3Faz%WD zs-+~{_%MV`_C5$>teZB@YV!>#gD^oDVxMvRyERi%^JS{}(m45?0xkLopGKtlHqQvo zym8?w9DMVa0mc{}(m1cHKY%TX>rIdmVstU5!N!i^j>$a#<*%~rqr{FP>@X_gnTNTD zMcmHowSp8gGH ze%sW@2;|_&IvIl|enk?GNTOEV9zM1`JpGWI*(PV|TQ`33Ay5AXGrw(W z+!4sci8?v3Ltmfubs-Ad zfX~tKMlc|}BQ(e}WPeC_9dbKlA|muRh+FLQ340sFE#iLRXoI*#pZk&LCdj_AI!QDF MlW6xDf)lm>0y9QxKmY&$ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/types.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/types.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a941d5bc0b8a0c055c1629f25cc73b2d1555ac0f GIT binary patch literal 2810 zcmcIlOK;mo5MELgMLj6VZ^@5Xj_la7UAs;lpecd^uC3HUjMVU>NC*J}Ev{{{q9iOS zBl5|I{)7O%^cb`#+GG1abkITIDL_xXsfbVMrL$B>O7iOvgc66dv%B+sv-@H9S5XWh zc>eqLFZ^d1p}%Rvd4e5>d1v|%`UxpWVM<76B!;0rTVf>^zP^%A=OoUKaV5XbOS~SC z0=ggxdQb}LAt|JXrLZ26BDyGv48p7ybs#XW#aut2#a%zF4Y0u*&IyU$w%>}yFY!NR?OMNVtfMv9Y zW$Y?Th22M)_&-z@8O93B<#NT8O|?=so^=Z-Wm(7P6ZR~kp2;S@GHqaYFZcb%LDrjhzD&n&Vq&VtY7yq-45Nn0?hOg1 zHnV#Nxu>~Jn&fJ-rR$SjUqiY(S8jj*FuPaiFYA1+FXIjCG1;A~KS^fU3Ka^+HM2%= zp+Mk-L>6z>t7`egiWEt`YF18&Ts^H5j&^0bLo289xh|V4Rif&ush(kDMKFz6*P$*Cx6$(~#%Z=vB z>z@PRZBG`~fJ4PqiWTc{@d6?(s;fyW_L^h8MS30a4>fp^s9l8Dj(KT1Wzd_+x>Lr4 zURu`lRkimBl+f$UN_LIvTQhpa{f6FwMeoa7U*(Gx1*DWetQ;R~%f%mz{2tb^euN1& zinv_F`IR$VKFjZ@M|ndv@n=;SB%fd--z~J&j?h-CuFzIJp{;^iL3!2sd*O**QEDap zHTeSI8F-Bri%{FgFibmym~;c(@BY6<;)VTti|#dg|7|wNux<2dO#%%jUQf0-{>SGn zF3{wL9m_YlsTLP*a?lxUa)}lfYI5T(PH1wY?O4E{xby`F*^6j<7!5;3@fM0-_?z&h zDIzT{^-*WVV3@JY1LtxHAs!Ux%6lffP(f~9KK=V%lDD45w+dyj$(8>)!Q|X^~ZU^ewJdvlHCrklo evOS1Wj~i&x!-Rc<;+7oD`D-!VeI#q3@c#jWRk@D< literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/utils.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/utils.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..595f90b44c7b859a89d3a02321bc84f8a3516810 GIT binary patch literal 1463 zcmZuw&2Jk;6o0e3UVr4n;JU3!BV-cwum>DcPDB-`fvP#62th$;Wog;$OzaKbkIsyv z+OkkUIrP9i`~w7`ocTXo$%kmAN|88ma}`eE!kgWAW4E21ee=Hdy*I!2_K&5d3gG(h z@n7tg4)C`Urpw3}a`6K)$3TISE(F9TMDbcz3v^pgdA(}{1-n3i>HFsNbK69zm`gffcJo zE}BS>fq_jZ*cvTS{m8I&X3#Pm zg+9QL>=&jPP@m&V0dJx04Ave!iKy|A2{gSM-B`N$z{=J?VEvGwvrP$MHj7I?kY$ce6RwRaIf1AvuJX)jPjgzkfHr z_sNUu=D4~!0aE^)ysX_Ftvq~D+ZxxlMvGhL@2x#IeyyIZ+#9cKJU7OrJEL@8U6ugnc}-g&iV07U9Z*$Gdn4<=)^mq+As^xOrXp47#_J z>jIKPIIrFqR~w^JgV#~sv9uI%UPb}=n|N^LZJ7#<&<&X5U<;ifqP?!-7aiwm&+TRw zegj>TQp}^6aoJBx_!H8|Sxss(xgyK>iftr^`7_Z9h5HkjC(B?iPc%~a05QEHuXNNM zegB#^OQJ&WSY=h=UJn7q3c31^lhxVwH?#IPcl}TelW01;CnPtNfIrF!VJHm!$_8exLGHG^n15pOH*-Ldc{7WNieiv-=!A n9?kDF*ci?4^V@gFw?7&|{cOri%nCu=-XyP-?%%f<(h~m%#6EGV literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/x25519.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/x25519.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..db83a638580ffb4d5bdfaf6f9a3f8e057d88f64e GIT binary patch literal 5346 zcmdT|&2JmW6`$pomK3F>KB5m>bvH^Io2^V$solVm?ZkEzJFP<-k_@D*fbDX3BvB!` z^vp_*h!ijiAA3(ug${vQ!9C>Cf1zheAYfyG07iT2jfUKddg*(!ALNpRn-)2=EAnx6 z=FQCen)iOAKMW0}2t5D1{bxEfM9AOp#ed>%Lpm9j2>F7T#FWaUA{8VF+mUjl5P{!l zIa-MoVwHFyF8X8TL}j2Li*~%6tfUGliA2b4VkVvtbAU#+2mKBHBp*Zxc?w_mDWqw7 zAEfAgsJuPw_im^C)&a=%6u$1`?UICDQm@@bp~|<|Me*0|-o=cplI-B$aX2eEgL<`U z*}7e_syv^KIO7khe5Y2km`%+aUHamj`}h z@CA*elRrWOVo8Gdfmr%YL?WL@_B%O)Nns878G9fYf~d3Q_S?1>se~NBN>78;ek<8Q ztPrvt%-`>r+g{~!DeUQ0au~}qTnwF7)QwMR)vW*2Rb4G{75uISzE+ESs=WohyOePV z2G!b7?}4LNSMTPsNoUSrdo|nIWO{9DFSn)FE4rQY*5o-aBK!`9vFBty6Gqm8Ef^Y+ zp{~xk2l>?p_wV0ZSzG=v`hKC&i5)6YO|6t?@E@d?Xfpt znWnRuq0KUU5kDcPoyZIM`V_?ywUpJ$f8$xJmf z@4k#j$A(`KAT1Id8vaL$WM-Pm>@(%kv2y9_wIgM*sVp|+#S>VcI5OxcEO0s*KBu{5 zZ@@`xSPVRQdbW$fRp3K0Xm}?X*Cd#usjist~%Q>1<+1tu5I+7?y)oIp(oDmYLW zN;dSnj#EFSd%1u=e@L=XC&p=cgPnmT*$fchiEIj9oOGwd>oeUJ?i@V}{3j^cWAVqP zp=ksO7GC;`|LZ^;6rbsj{=MAG4|httdYM*j)wVp%+>pGmqCc8bfn+3^cw73S6`hem(JipsKZgN>`g&!(yDreYMPVMw2Ec!l(C)GG}Oo& z88pf|=Wu4XEK{6RC#n|>XIL+Co9Tw_jl79#3j_ZMTj(@lW#KF#u^?E=`R{?aVTSa1 zJkyFK<4Y~#lb2DF74vIw}?-WWh&?%^?72*0N{^Y5p86Ss>OF48d-~%v(XLMB8|FX{ zhaBRV=vSLV9FwNfvqmb!F=dYQa15HGkdLOFj2Dv(&ZteHz>6>nWr7&!D-zj(P&_E; z5)^dlf1{wIWNnDFN*KmnHpw#ZBZ?gx!4_&Fswx}B))p%6@s0$U`kabH5n?Sqc5rx|7=AbL^Qh%$*QN43-;?(aPXIws3E`MzvDN9XdsUa`5 zGfe1g^)ERe1tn)i;A`Fm3RK9@mQjLuHPuIO>u}*Hz%D$)h#G?Vc{elv09EWLrYWzO z0&D$jkBQoYd6?HOOvZnjjqtk5H9LPAUofjj(TizrC zW7&WD+i5Y-^R-~AZI^DG0hLmPE!udBU4vJSJ3}0K<$K68tQ%?dbG`QJjKnouFR13< z!r3gO1i+RqNYzjJE=<+Ae*miH)V$TU=7nqz$YR}5F%nW#V655KD~mi@NMT2*QOf+A z2gFw>J@t3vF9QqQrwm~>S9OeHm40Sy>D5iD!u1BSGv2j!INVd*d>^c&G?=XwA z9|M5}QAQU&1w+|16AAXz}NgyelBnAF%Zk}hb5A~GaDgD?Lp zkS=H@$KPoYp9IhhJH`Q~AxOK5(9I>mICcckErhMYkSpcGG8ti+Pue`#1N*oT&_{Lx z=3L0O-rGUrWwr{O)E zC2&E+70$VS-0hn&!+%jY12=Bo`WVor@VFy0x>@2jWdf84Cv|!6RKDuM_Ur5}%*W%z zk+!0eB(+jRdaFTZJ3lW->aqBHL2fqseV&sK8{yA$a-|Xev=XxtIIEZJN52{r{V#Fw zRh#4I5|J{`$kZ{J`f{c@J=dJRdPJ@@$+ZT#)=FH$)q2VP*jHyo|4STv)#j+eY9r6c b^f8(Ka;|yiV)M-PBl2F8yw~tQqPqSIw0y2) literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/x448.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/x448.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5508d1156a8d5de692e97828d966fa4ccaf6c265 GIT binary patch literal 5430 zcmdT|K~o#a74DHnLJ|TA%z_QX9+P-&B_Oe9+E+N z>gj&n@4bGn-}{e0?-d%=V9k){6(+(*8EE&n+f-QGw!zbK;M_}b)LHP7)bAar}X4ENIy@L z-$HuQmDeiW2&}+vt&mjw@5qvp>~5`CG%d}_nMJ;s3fKdWihQe7GMPn7O7d=_}o%;}my{Pyu- ztIHdLIJF{;x6OKN6XK7w-%6GjMTBg6^ItU0ZLIQ{1|rvUcHyguJW8kCrZGity8|*Z0Mw8=wylI3OOsc zP5Gq8cM1h+v7A1MdZkM{>^%@$K8L&Ng;TmsTig=93gj7i9l2Zae_kgBUnMRaCN3N# zE>;s4YebIre%=56QF8w4a-OkDZu>Oo?v znwY9YrjB8KVn@I}Vg1RF|7@lg>H~Io&1B%glaUq%$AFK-pk6<{xF*5uC88e>C`Lb= zp+I>$2HP#3hZ|IJ^8hschVmJ;yy_QZJE>j8XJZs*(ea#f$TKA z*zsm(mxulP+dMV`+{dWbGx5jHKvVb9ExdGA{#Twds65l2{(G$#o^0i|wLC3aie=XA za)R;Fvi5Xb0g`I6k(~qK`w~;&hocgTV_C9Udle*?&wjIYIDP@J@vy4WC#qT= z@T=?ej-!5_l8Y(XIhj~p8746n1(FIo?na*ppR@0IqAQ(Q0U@7U&AaYs4kU za@ykrXzqa+#c8C`805g*53r*iD$7%~!VYs7pUr;WZgj&7qL($N{a zSA->lBWh8o=^~PRi9iNxMHbr=W_vYUf*LOUZ`5$qtbvJE2*c1zMH#|5QRP@4w$Kt$ zOj$p+P9Z@r+wpZ;qzpDdg?tMKc?d^D@o7HD5tpkxdFuZOZT+Xd>UU6r6R=JlVS~8ucs!x3I!S06UdrcN+|)kv zHctG`0mg@ii4VWJeUO;0CZ;Qq=|+O_ovY6E=3}qkEDJczThM?43EI?i5UYmr6s{N! z{sgRr=NI9EH-FJd%s)UAo9bw+UPpnoe5PfC8beDkt5KI)%FoGYD*|%FI}peo04RmP z7XY!Uxi_JcRLdO5H7m_`Ab?r*Njk={`*hx=8PCdhVyMQhv;qt$lM0Avz$kVDUO7sJ z7^+w9p8B>rQC1#p-L2*r{5h`X74mQ4Xy!8k@Jb7k>ZE%MlxmjmVX1Lt(QNGHrBoZX zVyzL;=QC44E9G6LB8TQP*G`luW$r}-BFmSSI=k=}p8ZRdA+qL*hViS=PxTG0xK0(g z%Ro-XYt))r+#T5P83&hp2VPx;?skAC zdg~klL_}In3!BB|Fud3t5&`Qlce5V>fdx@R2Q_&^sW=nJZ~}+YNG6e7LxQP|T}JW& zlIuu*g5(yG1tcwq3{_-Ea6bPlkTyhi84;O7nh@FL8X&Sh#AY)%?vSSO860;In-5a? zkygy*i69ztNrMM_23#H&&Ud}~dE^Qp*L zynz$!F&~S2gU=Q5n#|KGUb$Hq7ep*!pY6omxCS%)PlVld^Va-*0GYz$cGrf+HOpdl zgwgdJw+t6Dt-lMEhtG+Ek>m8SIAiN=QW8v6MwJCtxBiQ z5&5X%{~VF&ivLp!k4fOQcCxE~@mTb~!NIo;j-N_I?tXUdceA^L2SKG8RBA+$W{>2) zSMuLg+ANbY|nj~vP) dyZ5T26V=h#1NlZ(zEN>MxKDGa%bY04{{p=K#0UTY literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/dh.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/dh.py new file mode 100644 index 00000000..31c9748a --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/dh.py @@ -0,0 +1,135 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc + +from cryptography.hazmat.bindings._rust import openssl as rust_openssl +from cryptography.hazmat.primitives import _serialization + +generate_parameters = rust_openssl.dh.generate_parameters + + +DHPrivateNumbers = rust_openssl.dh.DHPrivateNumbers +DHPublicNumbers = rust_openssl.dh.DHPublicNumbers +DHParameterNumbers = rust_openssl.dh.DHParameterNumbers + + +class DHParameters(metaclass=abc.ABCMeta): + @abc.abstractmethod + def generate_private_key(self) -> DHPrivateKey: + """ + Generates and returns a DHPrivateKey. + """ + + @abc.abstractmethod + def parameter_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.ParameterFormat, + ) -> bytes: + """ + Returns the parameters serialized as bytes. + """ + + @abc.abstractmethod + def parameter_numbers(self) -> DHParameterNumbers: + """ + Returns a DHParameterNumbers. + """ + + +DHParametersWithSerialization = DHParameters +DHParameters.register(rust_openssl.dh.DHParameters) + + +class DHPublicKey(metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def key_size(self) -> int: + """ + The bit length of the prime modulus. + """ + + @abc.abstractmethod + def parameters(self) -> DHParameters: + """ + The DHParameters object associated with this public key. + """ + + @abc.abstractmethod + def public_numbers(self) -> DHPublicNumbers: + """ + Returns a DHPublicNumbers. + """ + + @abc.abstractmethod + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: + """ + Returns the key serialized as bytes. + """ + + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Checks equality. + """ + + +DHPublicKeyWithSerialization = DHPublicKey +DHPublicKey.register(rust_openssl.dh.DHPublicKey) + + +class DHPrivateKey(metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def key_size(self) -> int: + """ + The bit length of the prime modulus. + """ + + @abc.abstractmethod + def public_key(self) -> DHPublicKey: + """ + The DHPublicKey associated with this private key. + """ + + @abc.abstractmethod + def parameters(self) -> DHParameters: + """ + The DHParameters object associated with this private key. + """ + + @abc.abstractmethod + def exchange(self, peer_public_key: DHPublicKey) -> bytes: + """ + Given peer's DHPublicKey, carry out the key exchange and + return shared key as bytes. + """ + + @abc.abstractmethod + def private_numbers(self) -> DHPrivateNumbers: + """ + Returns a DHPrivateNumbers. + """ + + @abc.abstractmethod + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: + """ + Returns the key serialized as bytes. + """ + + +DHPrivateKeyWithSerialization = DHPrivateKey +DHPrivateKey.register(rust_openssl.dh.DHPrivateKey) diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py new file mode 100644 index 00000000..6dd34c0e --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py @@ -0,0 +1,154 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc +import typing + +from cryptography.hazmat.bindings._rust import openssl as rust_openssl +from cryptography.hazmat.primitives import _serialization, hashes +from cryptography.hazmat.primitives.asymmetric import utils as asym_utils + + +class DSAParameters(metaclass=abc.ABCMeta): + @abc.abstractmethod + def generate_private_key(self) -> DSAPrivateKey: + """ + Generates and returns a DSAPrivateKey. + """ + + @abc.abstractmethod + def parameter_numbers(self) -> DSAParameterNumbers: + """ + Returns a DSAParameterNumbers. + """ + + +DSAParametersWithNumbers = DSAParameters +DSAParameters.register(rust_openssl.dsa.DSAParameters) + + +class DSAPrivateKey(metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def key_size(self) -> int: + """ + The bit length of the prime modulus. + """ + + @abc.abstractmethod + def public_key(self) -> DSAPublicKey: + """ + The DSAPublicKey associated with this private key. + """ + + @abc.abstractmethod + def parameters(self) -> DSAParameters: + """ + The DSAParameters object associated with this private key. + """ + + @abc.abstractmethod + def sign( + self, + data: bytes, + algorithm: asym_utils.Prehashed | hashes.HashAlgorithm, + ) -> bytes: + """ + Signs the data + """ + + @abc.abstractmethod + def private_numbers(self) -> DSAPrivateNumbers: + """ + Returns a DSAPrivateNumbers. + """ + + @abc.abstractmethod + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: + """ + Returns the key serialized as bytes. + """ + + +DSAPrivateKeyWithSerialization = DSAPrivateKey +DSAPrivateKey.register(rust_openssl.dsa.DSAPrivateKey) + + +class DSAPublicKey(metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def key_size(self) -> int: + """ + The bit length of the prime modulus. + """ + + @abc.abstractmethod + def parameters(self) -> DSAParameters: + """ + The DSAParameters object associated with this public key. + """ + + @abc.abstractmethod + def public_numbers(self) -> DSAPublicNumbers: + """ + Returns a DSAPublicNumbers. + """ + + @abc.abstractmethod + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: + """ + Returns the key serialized as bytes. + """ + + @abc.abstractmethod + def verify( + self, + signature: bytes, + data: bytes, + algorithm: asym_utils.Prehashed | hashes.HashAlgorithm, + ) -> None: + """ + Verifies the signature of the data. + """ + + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Checks equality. + """ + + +DSAPublicKeyWithSerialization = DSAPublicKey +DSAPublicKey.register(rust_openssl.dsa.DSAPublicKey) + +DSAPrivateNumbers = rust_openssl.dsa.DSAPrivateNumbers +DSAPublicNumbers = rust_openssl.dsa.DSAPublicNumbers +DSAParameterNumbers = rust_openssl.dsa.DSAParameterNumbers + + +def generate_parameters( + key_size: int, backend: typing.Any = None +) -> DSAParameters: + if key_size not in (1024, 2048, 3072, 4096): + raise ValueError("Key size must be 1024, 2048, 3072, or 4096 bits.") + + return rust_openssl.dsa.generate_parameters(key_size) + + +def generate_private_key( + key_size: int, backend: typing.Any = None +) -> DSAPrivateKey: + parameters = generate_parameters(key_size) + return parameters.generate_private_key() diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ec.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ec.py new file mode 100644 index 00000000..b612b401 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ec.py @@ -0,0 +1,383 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc +import typing + +from cryptography import utils +from cryptography.hazmat._oid import ObjectIdentifier +from cryptography.hazmat.bindings._rust import openssl as rust_openssl +from cryptography.hazmat.primitives import _serialization, hashes +from cryptography.hazmat.primitives.asymmetric import utils as asym_utils + + +class EllipticCurveOID: + SECP192R1 = ObjectIdentifier("1.2.840.10045.3.1.1") + SECP224R1 = ObjectIdentifier("1.3.132.0.33") + SECP256K1 = ObjectIdentifier("1.3.132.0.10") + SECP256R1 = ObjectIdentifier("1.2.840.10045.3.1.7") + SECP384R1 = ObjectIdentifier("1.3.132.0.34") + SECP521R1 = ObjectIdentifier("1.3.132.0.35") + BRAINPOOLP256R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.7") + BRAINPOOLP384R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.11") + BRAINPOOLP512R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.13") + SECT163K1 = ObjectIdentifier("1.3.132.0.1") + SECT163R2 = ObjectIdentifier("1.3.132.0.15") + SECT233K1 = ObjectIdentifier("1.3.132.0.26") + SECT233R1 = ObjectIdentifier("1.3.132.0.27") + SECT283K1 = ObjectIdentifier("1.3.132.0.16") + SECT283R1 = ObjectIdentifier("1.3.132.0.17") + SECT409K1 = ObjectIdentifier("1.3.132.0.36") + SECT409R1 = ObjectIdentifier("1.3.132.0.37") + SECT571K1 = ObjectIdentifier("1.3.132.0.38") + SECT571R1 = ObjectIdentifier("1.3.132.0.39") + + +class EllipticCurve(metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def name(self) -> str: + """ + The name of the curve. e.g. secp256r1. + """ + + @property + @abc.abstractmethod + def key_size(self) -> int: + """ + Bit size of a secret scalar for the curve. + """ + + +class EllipticCurveSignatureAlgorithm(metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def algorithm( + self, + ) -> asym_utils.Prehashed | hashes.HashAlgorithm: + """ + The digest algorithm used with this signature. + """ + + +class EllipticCurvePrivateKey(metaclass=abc.ABCMeta): + @abc.abstractmethod + def exchange( + self, algorithm: ECDH, peer_public_key: EllipticCurvePublicKey + ) -> bytes: + """ + Performs a key exchange operation using the provided algorithm with the + provided peer's public key. + """ + + @abc.abstractmethod + def public_key(self) -> EllipticCurvePublicKey: + """ + The EllipticCurvePublicKey for this private key. + """ + + @property + @abc.abstractmethod + def curve(self) -> EllipticCurve: + """ + The EllipticCurve that this key is on. + """ + + @property + @abc.abstractmethod + def key_size(self) -> int: + """ + Bit size of a secret scalar for the curve. + """ + + @abc.abstractmethod + def sign( + self, + data: bytes, + signature_algorithm: EllipticCurveSignatureAlgorithm, + ) -> bytes: + """ + Signs the data + """ + + @abc.abstractmethod + def private_numbers(self) -> EllipticCurvePrivateNumbers: + """ + Returns an EllipticCurvePrivateNumbers. + """ + + @abc.abstractmethod + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: + """ + Returns the key serialized as bytes. + """ + + +EllipticCurvePrivateKeyWithSerialization = EllipticCurvePrivateKey +EllipticCurvePrivateKey.register(rust_openssl.ec.ECPrivateKey) + + +class EllipticCurvePublicKey(metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def curve(self) -> EllipticCurve: + """ + The EllipticCurve that this key is on. + """ + + @property + @abc.abstractmethod + def key_size(self) -> int: + """ + Bit size of a secret scalar for the curve. + """ + + @abc.abstractmethod + def public_numbers(self) -> EllipticCurvePublicNumbers: + """ + Returns an EllipticCurvePublicNumbers. + """ + + @abc.abstractmethod + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: + """ + Returns the key serialized as bytes. + """ + + @abc.abstractmethod + def verify( + self, + signature: bytes, + data: bytes, + signature_algorithm: EllipticCurveSignatureAlgorithm, + ) -> None: + """ + Verifies the signature of the data. + """ + + @classmethod + def from_encoded_point( + cls, curve: EllipticCurve, data: bytes + ) -> EllipticCurvePublicKey: + utils._check_bytes("data", data) + + if len(data) == 0: + raise ValueError("data must not be an empty byte string") + + if data[0] not in [0x02, 0x03, 0x04]: + raise ValueError("Unsupported elliptic curve point type") + + return rust_openssl.ec.from_public_bytes(curve, data) + + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Checks equality. + """ + + +EllipticCurvePublicKeyWithSerialization = EllipticCurvePublicKey +EllipticCurvePublicKey.register(rust_openssl.ec.ECPublicKey) + +EllipticCurvePrivateNumbers = rust_openssl.ec.EllipticCurvePrivateNumbers +EllipticCurvePublicNumbers = rust_openssl.ec.EllipticCurvePublicNumbers + + +class SECT571R1(EllipticCurve): + name = "sect571r1" + key_size = 570 + + +class SECT409R1(EllipticCurve): + name = "sect409r1" + key_size = 409 + + +class SECT283R1(EllipticCurve): + name = "sect283r1" + key_size = 283 + + +class SECT233R1(EllipticCurve): + name = "sect233r1" + key_size = 233 + + +class SECT163R2(EllipticCurve): + name = "sect163r2" + key_size = 163 + + +class SECT571K1(EllipticCurve): + name = "sect571k1" + key_size = 571 + + +class SECT409K1(EllipticCurve): + name = "sect409k1" + key_size = 409 + + +class SECT283K1(EllipticCurve): + name = "sect283k1" + key_size = 283 + + +class SECT233K1(EllipticCurve): + name = "sect233k1" + key_size = 233 + + +class SECT163K1(EllipticCurve): + name = "sect163k1" + key_size = 163 + + +class SECP521R1(EllipticCurve): + name = "secp521r1" + key_size = 521 + + +class SECP384R1(EllipticCurve): + name = "secp384r1" + key_size = 384 + + +class SECP256R1(EllipticCurve): + name = "secp256r1" + key_size = 256 + + +class SECP256K1(EllipticCurve): + name = "secp256k1" + key_size = 256 + + +class SECP224R1(EllipticCurve): + name = "secp224r1" + key_size = 224 + + +class SECP192R1(EllipticCurve): + name = "secp192r1" + key_size = 192 + + +class BrainpoolP256R1(EllipticCurve): + name = "brainpoolP256r1" + key_size = 256 + + +class BrainpoolP384R1(EllipticCurve): + name = "brainpoolP384r1" + key_size = 384 + + +class BrainpoolP512R1(EllipticCurve): + name = "brainpoolP512r1" + key_size = 512 + + +_CURVE_TYPES: dict[str, EllipticCurve] = { + "prime192v1": SECP192R1(), + "prime256v1": SECP256R1(), + "secp192r1": SECP192R1(), + "secp224r1": SECP224R1(), + "secp256r1": SECP256R1(), + "secp384r1": SECP384R1(), + "secp521r1": SECP521R1(), + "secp256k1": SECP256K1(), + "sect163k1": SECT163K1(), + "sect233k1": SECT233K1(), + "sect283k1": SECT283K1(), + "sect409k1": SECT409K1(), + "sect571k1": SECT571K1(), + "sect163r2": SECT163R2(), + "sect233r1": SECT233R1(), + "sect283r1": SECT283R1(), + "sect409r1": SECT409R1(), + "sect571r1": SECT571R1(), + "brainpoolP256r1": BrainpoolP256R1(), + "brainpoolP384r1": BrainpoolP384R1(), + "brainpoolP512r1": BrainpoolP512R1(), +} + + +class ECDSA(EllipticCurveSignatureAlgorithm): + def __init__( + self, + algorithm: asym_utils.Prehashed | hashes.HashAlgorithm, + ): + self._algorithm = algorithm + + @property + def algorithm( + self, + ) -> asym_utils.Prehashed | hashes.HashAlgorithm: + return self._algorithm + + +generate_private_key = rust_openssl.ec.generate_private_key + + +def derive_private_key( + private_value: int, + curve: EllipticCurve, + backend: typing.Any = None, +) -> EllipticCurvePrivateKey: + if not isinstance(private_value, int): + raise TypeError("private_value must be an integer type.") + + if private_value <= 0: + raise ValueError("private_value must be a positive integer.") + + return rust_openssl.ec.derive_private_key(private_value, curve) + + +class ECDH: + pass + + +_OID_TO_CURVE = { + EllipticCurveOID.SECP192R1: SECP192R1, + EllipticCurveOID.SECP224R1: SECP224R1, + EllipticCurveOID.SECP256K1: SECP256K1, + EllipticCurveOID.SECP256R1: SECP256R1, + EllipticCurveOID.SECP384R1: SECP384R1, + EllipticCurveOID.SECP521R1: SECP521R1, + EllipticCurveOID.BRAINPOOLP256R1: BrainpoolP256R1, + EllipticCurveOID.BRAINPOOLP384R1: BrainpoolP384R1, + EllipticCurveOID.BRAINPOOLP512R1: BrainpoolP512R1, + EllipticCurveOID.SECT163K1: SECT163K1, + EllipticCurveOID.SECT163R2: SECT163R2, + EllipticCurveOID.SECT233K1: SECT233K1, + EllipticCurveOID.SECT233R1: SECT233R1, + EllipticCurveOID.SECT283K1: SECT283K1, + EllipticCurveOID.SECT283R1: SECT283R1, + EllipticCurveOID.SECT409K1: SECT409K1, + EllipticCurveOID.SECT409R1: SECT409R1, + EllipticCurveOID.SECT571K1: SECT571K1, + EllipticCurveOID.SECT571R1: SECT571R1, +} + + +def get_curve_for_oid(oid: ObjectIdentifier) -> type[EllipticCurve]: + try: + return _OID_TO_CURVE[oid] + except KeyError: + raise LookupError( + "The provided object identifier has no matching elliptic " + "curve class" + ) diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ed25519.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ed25519.py new file mode 100644 index 00000000..3a26185d --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ed25519.py @@ -0,0 +1,116 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc + +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.bindings._rust import openssl as rust_openssl +from cryptography.hazmat.primitives import _serialization + + +class Ed25519PublicKey(metaclass=abc.ABCMeta): + @classmethod + def from_public_bytes(cls, data: bytes) -> Ed25519PublicKey: + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.ed25519_supported(): + raise UnsupportedAlgorithm( + "ed25519 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, + ) + + return rust_openssl.ed25519.from_public_bytes(data) + + @abc.abstractmethod + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: + """ + The serialized bytes of the public key. + """ + + @abc.abstractmethod + def public_bytes_raw(self) -> bytes: + """ + The raw bytes of the public key. + Equivalent to public_bytes(Raw, Raw). + """ + + @abc.abstractmethod + def verify(self, signature: bytes, data: bytes) -> None: + """ + Verify the signature. + """ + + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Checks equality. + """ + + +Ed25519PublicKey.register(rust_openssl.ed25519.Ed25519PublicKey) + + +class Ed25519PrivateKey(metaclass=abc.ABCMeta): + @classmethod + def generate(cls) -> Ed25519PrivateKey: + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.ed25519_supported(): + raise UnsupportedAlgorithm( + "ed25519 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, + ) + + return rust_openssl.ed25519.generate_key() + + @classmethod + def from_private_bytes(cls, data: bytes) -> Ed25519PrivateKey: + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.ed25519_supported(): + raise UnsupportedAlgorithm( + "ed25519 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, + ) + + return rust_openssl.ed25519.from_private_bytes(data) + + @abc.abstractmethod + def public_key(self) -> Ed25519PublicKey: + """ + The Ed25519PublicKey derived from the private key. + """ + + @abc.abstractmethod + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: + """ + The serialized bytes of the private key. + """ + + @abc.abstractmethod + def private_bytes_raw(self) -> bytes: + """ + The raw bytes of the private key. + Equivalent to private_bytes(Raw, Raw, NoEncryption()). + """ + + @abc.abstractmethod + def sign(self, data: bytes) -> bytes: + """ + Signs the data. + """ + + +Ed25519PrivateKey.register(rust_openssl.ed25519.Ed25519PrivateKey) diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ed448.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ed448.py new file mode 100644 index 00000000..78c82c4a --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ed448.py @@ -0,0 +1,118 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc + +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.bindings._rust import openssl as rust_openssl +from cryptography.hazmat.primitives import _serialization + + +class Ed448PublicKey(metaclass=abc.ABCMeta): + @classmethod + def from_public_bytes(cls, data: bytes) -> Ed448PublicKey: + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.ed448_supported(): + raise UnsupportedAlgorithm( + "ed448 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, + ) + + return rust_openssl.ed448.from_public_bytes(data) + + @abc.abstractmethod + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: + """ + The serialized bytes of the public key. + """ + + @abc.abstractmethod + def public_bytes_raw(self) -> bytes: + """ + The raw bytes of the public key. + Equivalent to public_bytes(Raw, Raw). + """ + + @abc.abstractmethod + def verify(self, signature: bytes, data: bytes) -> None: + """ + Verify the signature. + """ + + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Checks equality. + """ + + +if hasattr(rust_openssl, "ed448"): + Ed448PublicKey.register(rust_openssl.ed448.Ed448PublicKey) + + +class Ed448PrivateKey(metaclass=abc.ABCMeta): + @classmethod + def generate(cls) -> Ed448PrivateKey: + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.ed448_supported(): + raise UnsupportedAlgorithm( + "ed448 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, + ) + + return rust_openssl.ed448.generate_key() + + @classmethod + def from_private_bytes(cls, data: bytes) -> Ed448PrivateKey: + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.ed448_supported(): + raise UnsupportedAlgorithm( + "ed448 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, + ) + + return rust_openssl.ed448.from_private_bytes(data) + + @abc.abstractmethod + def public_key(self) -> Ed448PublicKey: + """ + The Ed448PublicKey derived from the private key. + """ + + @abc.abstractmethod + def sign(self, data: bytes) -> bytes: + """ + Signs the data. + """ + + @abc.abstractmethod + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: + """ + The serialized bytes of the private key. + """ + + @abc.abstractmethod + def private_bytes_raw(self) -> bytes: + """ + The raw bytes of the private key. + Equivalent to private_bytes(Raw, Raw, NoEncryption()). + """ + + +if hasattr(rust_openssl, "x448"): + Ed448PrivateKey.register(rust_openssl.ed448.Ed448PrivateKey) diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/padding.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/padding.py new file mode 100644 index 00000000..b4babf44 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/padding.py @@ -0,0 +1,113 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc + +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives._asymmetric import ( + AsymmetricPadding as AsymmetricPadding, +) +from cryptography.hazmat.primitives.asymmetric import rsa + + +class PKCS1v15(AsymmetricPadding): + name = "EMSA-PKCS1-v1_5" + + +class _MaxLength: + "Sentinel value for `MAX_LENGTH`." + + +class _Auto: + "Sentinel value for `AUTO`." + + +class _DigestLength: + "Sentinel value for `DIGEST_LENGTH`." + + +class PSS(AsymmetricPadding): + MAX_LENGTH = _MaxLength() + AUTO = _Auto() + DIGEST_LENGTH = _DigestLength() + name = "EMSA-PSS" + _salt_length: int | _MaxLength | _Auto | _DigestLength + + def __init__( + self, + mgf: MGF, + salt_length: int | _MaxLength | _Auto | _DigestLength, + ) -> None: + self._mgf = mgf + + if not isinstance( + salt_length, (int, _MaxLength, _Auto, _DigestLength) + ): + raise TypeError( + "salt_length must be an integer, MAX_LENGTH, " + "DIGEST_LENGTH, or AUTO" + ) + + if isinstance(salt_length, int) and salt_length < 0: + raise ValueError("salt_length must be zero or greater.") + + self._salt_length = salt_length + + @property + def mgf(self) -> MGF: + return self._mgf + + +class OAEP(AsymmetricPadding): + name = "EME-OAEP" + + def __init__( + self, + mgf: MGF, + algorithm: hashes.HashAlgorithm, + label: bytes | None, + ): + if not isinstance(algorithm, hashes.HashAlgorithm): + raise TypeError("Expected instance of hashes.HashAlgorithm.") + + self._mgf = mgf + self._algorithm = algorithm + self._label = label + + @property + def algorithm(self) -> hashes.HashAlgorithm: + return self._algorithm + + @property + def mgf(self) -> MGF: + return self._mgf + + +class MGF(metaclass=abc.ABCMeta): + _algorithm: hashes.HashAlgorithm + + +class MGF1(MGF): + MAX_LENGTH = _MaxLength() + + def __init__(self, algorithm: hashes.HashAlgorithm): + if not isinstance(algorithm, hashes.HashAlgorithm): + raise TypeError("Expected instance of hashes.HashAlgorithm.") + + self._algorithm = algorithm + + +def calculate_max_pss_salt_length( + key: rsa.RSAPrivateKey | rsa.RSAPublicKey, + hash_algorithm: hashes.HashAlgorithm, +) -> int: + if not isinstance(key, (rsa.RSAPrivateKey, rsa.RSAPublicKey)): + raise TypeError("key must be an RSA public or private key") + # bit length - 1 per RFC 3447 + emlen = (key.key_size + 6) // 8 + salt_length = emlen - hash_algorithm.digest_size - 2 + assert salt_length >= 0 + return salt_length diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/rsa.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/rsa.py new file mode 100644 index 00000000..6420434d --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -0,0 +1,239 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc +import typing +from math import gcd + +from cryptography.hazmat.bindings._rust import openssl as rust_openssl +from cryptography.hazmat.primitives import _serialization, hashes +from cryptography.hazmat.primitives._asymmetric import AsymmetricPadding +from cryptography.hazmat.primitives.asymmetric import utils as asym_utils + + +class RSAPrivateKey(metaclass=abc.ABCMeta): + @abc.abstractmethod + def decrypt(self, ciphertext: bytes, padding: AsymmetricPadding) -> bytes: + """ + Decrypts the provided ciphertext. + """ + + @property + @abc.abstractmethod + def key_size(self) -> int: + """ + The bit length of the public modulus. + """ + + @abc.abstractmethod + def public_key(self) -> RSAPublicKey: + """ + The RSAPublicKey associated with this private key. + """ + + @abc.abstractmethod + def sign( + self, + data: bytes, + padding: AsymmetricPadding, + algorithm: asym_utils.Prehashed | hashes.HashAlgorithm, + ) -> bytes: + """ + Signs the data. + """ + + @abc.abstractmethod + def private_numbers(self) -> RSAPrivateNumbers: + """ + Returns an RSAPrivateNumbers. + """ + + @abc.abstractmethod + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: + """ + Returns the key serialized as bytes. + """ + + +RSAPrivateKeyWithSerialization = RSAPrivateKey +RSAPrivateKey.register(rust_openssl.rsa.RSAPrivateKey) + + +class RSAPublicKey(metaclass=abc.ABCMeta): + @abc.abstractmethod + def encrypt(self, plaintext: bytes, padding: AsymmetricPadding) -> bytes: + """ + Encrypts the given plaintext. + """ + + @property + @abc.abstractmethod + def key_size(self) -> int: + """ + The bit length of the public modulus. + """ + + @abc.abstractmethod + def public_numbers(self) -> RSAPublicNumbers: + """ + Returns an RSAPublicNumbers + """ + + @abc.abstractmethod + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: + """ + Returns the key serialized as bytes. + """ + + @abc.abstractmethod + def verify( + self, + signature: bytes, + data: bytes, + padding: AsymmetricPadding, + algorithm: asym_utils.Prehashed | hashes.HashAlgorithm, + ) -> None: + """ + Verifies the signature of the data. + """ + + @abc.abstractmethod + def recover_data_from_signature( + self, + signature: bytes, + padding: AsymmetricPadding, + algorithm: hashes.HashAlgorithm | None, + ) -> bytes: + """ + Recovers the original data from the signature. + """ + + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Checks equality. + """ + + +RSAPublicKeyWithSerialization = RSAPublicKey +RSAPublicKey.register(rust_openssl.rsa.RSAPublicKey) + +RSAPrivateNumbers = rust_openssl.rsa.RSAPrivateNumbers +RSAPublicNumbers = rust_openssl.rsa.RSAPublicNumbers + + +def generate_private_key( + public_exponent: int, + key_size: int, + backend: typing.Any = None, +) -> RSAPrivateKey: + _verify_rsa_parameters(public_exponent, key_size) + return rust_openssl.rsa.generate_private_key(public_exponent, key_size) + + +def _verify_rsa_parameters(public_exponent: int, key_size: int) -> None: + if public_exponent not in (3, 65537): + raise ValueError( + "public_exponent must be either 3 (for legacy compatibility) or " + "65537. Almost everyone should choose 65537 here!" + ) + + if key_size < 512: + raise ValueError("key_size must be at least 512-bits.") + + +def _modinv(e: int, m: int) -> int: + """ + Modular Multiplicative Inverse. Returns x such that: (x*e) mod m == 1 + """ + x1, x2 = 1, 0 + a, b = e, m + while b > 0: + q, r = divmod(a, b) + xn = x1 - q * x2 + a, b, x1, x2 = b, r, x2, xn + return x1 % m + + +def rsa_crt_iqmp(p: int, q: int) -> int: + """ + Compute the CRT (q ** -1) % p value from RSA primes p and q. + """ + return _modinv(q, p) + + +def rsa_crt_dmp1(private_exponent: int, p: int) -> int: + """ + Compute the CRT private_exponent % (p - 1) value from the RSA + private_exponent (d) and p. + """ + return private_exponent % (p - 1) + + +def rsa_crt_dmq1(private_exponent: int, q: int) -> int: + """ + Compute the CRT private_exponent % (q - 1) value from the RSA + private_exponent (d) and q. + """ + return private_exponent % (q - 1) + + +# Controls the number of iterations rsa_recover_prime_factors will perform +# to obtain the prime factors. Each iteration increments by 2 so the actual +# maximum attempts is half this number. +_MAX_RECOVERY_ATTEMPTS = 1000 + + +def rsa_recover_prime_factors(n: int, e: int, d: int) -> tuple[int, int]: + """ + Compute factors p and q from the private exponent d. We assume that n has + no more than two factors. This function is adapted from code in PyCrypto. + """ + # See 8.2.2(i) in Handbook of Applied Cryptography. + ktot = d * e - 1 + # The quantity d*e-1 is a multiple of phi(n), even, + # and can be represented as t*2^s. + t = ktot + while t % 2 == 0: + t = t // 2 + # Cycle through all multiplicative inverses in Zn. + # The algorithm is non-deterministic, but there is a 50% chance + # any candidate a leads to successful factoring. + # See "Digitalized Signatures and Public Key Functions as Intractable + # as Factorization", M. Rabin, 1979 + spotted = False + a = 2 + while not spotted and a < _MAX_RECOVERY_ATTEMPTS: + k = t + # Cycle through all values a^{t*2^i}=a^k + while k < ktot: + cand = pow(a, k, n) + # Check if a^k is a non-trivial root of unity (mod n) + if cand != 1 and cand != (n - 1) and pow(cand, 2, n) == 1: + # We have found a number such that (cand-1)(cand+1)=0 (mod n). + # Either of the terms divides n. + p = gcd(cand + 1, n) + spotted = True + break + k *= 2 + # This value was not any good... let's try another! + a += 2 + if not spotted: + raise ValueError("Unable to compute factors p and q from exponent d.") + # Found ! + q, r = divmod(n, p) + assert r == 0 + p, q = sorted((p, q), reverse=True) + return (p, q) diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/types.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/types.py new file mode 100644 index 00000000..1fe4eaf5 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/types.py @@ -0,0 +1,111 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import typing + +from cryptography import utils +from cryptography.hazmat.primitives.asymmetric import ( + dh, + dsa, + ec, + ed448, + ed25519, + rsa, + x448, + x25519, +) + +# Every asymmetric key type +PublicKeyTypes = typing.Union[ + dh.DHPublicKey, + dsa.DSAPublicKey, + rsa.RSAPublicKey, + ec.EllipticCurvePublicKey, + ed25519.Ed25519PublicKey, + ed448.Ed448PublicKey, + x25519.X25519PublicKey, + x448.X448PublicKey, +] +PUBLIC_KEY_TYPES = PublicKeyTypes +utils.deprecated( + PUBLIC_KEY_TYPES, + __name__, + "Use PublicKeyTypes instead", + utils.DeprecatedIn40, + name="PUBLIC_KEY_TYPES", +) +# Every asymmetric key type +PrivateKeyTypes = typing.Union[ + dh.DHPrivateKey, + ed25519.Ed25519PrivateKey, + ed448.Ed448PrivateKey, + rsa.RSAPrivateKey, + dsa.DSAPrivateKey, + ec.EllipticCurvePrivateKey, + x25519.X25519PrivateKey, + x448.X448PrivateKey, +] +PRIVATE_KEY_TYPES = PrivateKeyTypes +utils.deprecated( + PRIVATE_KEY_TYPES, + __name__, + "Use PrivateKeyTypes instead", + utils.DeprecatedIn40, + name="PRIVATE_KEY_TYPES", +) +# Just the key types we allow to be used for x509 signing. This mirrors +# the certificate public key types +CertificateIssuerPrivateKeyTypes = typing.Union[ + ed25519.Ed25519PrivateKey, + ed448.Ed448PrivateKey, + rsa.RSAPrivateKey, + dsa.DSAPrivateKey, + ec.EllipticCurvePrivateKey, +] +CERTIFICATE_PRIVATE_KEY_TYPES = CertificateIssuerPrivateKeyTypes +utils.deprecated( + CERTIFICATE_PRIVATE_KEY_TYPES, + __name__, + "Use CertificateIssuerPrivateKeyTypes instead", + utils.DeprecatedIn40, + name="CERTIFICATE_PRIVATE_KEY_TYPES", +) +# Just the key types we allow to be used for x509 signing. This mirrors +# the certificate private key types +CertificateIssuerPublicKeyTypes = typing.Union[ + dsa.DSAPublicKey, + rsa.RSAPublicKey, + ec.EllipticCurvePublicKey, + ed25519.Ed25519PublicKey, + ed448.Ed448PublicKey, +] +CERTIFICATE_ISSUER_PUBLIC_KEY_TYPES = CertificateIssuerPublicKeyTypes +utils.deprecated( + CERTIFICATE_ISSUER_PUBLIC_KEY_TYPES, + __name__, + "Use CertificateIssuerPublicKeyTypes instead", + utils.DeprecatedIn40, + name="CERTIFICATE_ISSUER_PUBLIC_KEY_TYPES", +) +# This type removes DHPublicKey. x448/x25519 can be a public key +# but cannot be used in signing so they are allowed here. +CertificatePublicKeyTypes = typing.Union[ + dsa.DSAPublicKey, + rsa.RSAPublicKey, + ec.EllipticCurvePublicKey, + ed25519.Ed25519PublicKey, + ed448.Ed448PublicKey, + x25519.X25519PublicKey, + x448.X448PublicKey, +] +CERTIFICATE_PUBLIC_KEY_TYPES = CertificatePublicKeyTypes +utils.deprecated( + CERTIFICATE_PUBLIC_KEY_TYPES, + __name__, + "Use CertificatePublicKeyTypes instead", + utils.DeprecatedIn40, + name="CERTIFICATE_PUBLIC_KEY_TYPES", +) diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/utils.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/utils.py new file mode 100644 index 00000000..826b9567 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/utils.py @@ -0,0 +1,24 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +from cryptography.hazmat.bindings._rust import asn1 +from cryptography.hazmat.primitives import hashes + +decode_dss_signature = asn1.decode_dss_signature +encode_dss_signature = asn1.encode_dss_signature + + +class Prehashed: + def __init__(self, algorithm: hashes.HashAlgorithm): + if not isinstance(algorithm, hashes.HashAlgorithm): + raise TypeError("Expected instance of HashAlgorithm.") + + self._algorithm = algorithm + self._digest_size = algorithm.digest_size + + @property + def digest_size(self) -> int: + return self._digest_size diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/x25519.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/x25519.py new file mode 100644 index 00000000..0cfa36e3 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/x25519.py @@ -0,0 +1,109 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc + +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.bindings._rust import openssl as rust_openssl +from cryptography.hazmat.primitives import _serialization + + +class X25519PublicKey(metaclass=abc.ABCMeta): + @classmethod + def from_public_bytes(cls, data: bytes) -> X25519PublicKey: + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.x25519_supported(): + raise UnsupportedAlgorithm( + "X25519 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, + ) + + return rust_openssl.x25519.from_public_bytes(data) + + @abc.abstractmethod + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: + """ + The serialized bytes of the public key. + """ + + @abc.abstractmethod + def public_bytes_raw(self) -> bytes: + """ + The raw bytes of the public key. + Equivalent to public_bytes(Raw, Raw). + """ + + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Checks equality. + """ + + +X25519PublicKey.register(rust_openssl.x25519.X25519PublicKey) + + +class X25519PrivateKey(metaclass=abc.ABCMeta): + @classmethod + def generate(cls) -> X25519PrivateKey: + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.x25519_supported(): + raise UnsupportedAlgorithm( + "X25519 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, + ) + return rust_openssl.x25519.generate_key() + + @classmethod + def from_private_bytes(cls, data: bytes) -> X25519PrivateKey: + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.x25519_supported(): + raise UnsupportedAlgorithm( + "X25519 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, + ) + + return rust_openssl.x25519.from_private_bytes(data) + + @abc.abstractmethod + def public_key(self) -> X25519PublicKey: + """ + Returns the public key associated with this private key + """ + + @abc.abstractmethod + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: + """ + The serialized bytes of the private key. + """ + + @abc.abstractmethod + def private_bytes_raw(self) -> bytes: + """ + The raw bytes of the private key. + Equivalent to private_bytes(Raw, Raw, NoEncryption()). + """ + + @abc.abstractmethod + def exchange(self, peer_public_key: X25519PublicKey) -> bytes: + """ + Performs a key exchange operation using the provided peer's public key. + """ + + +X25519PrivateKey.register(rust_openssl.x25519.X25519PrivateKey) diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/x448.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/x448.py new file mode 100644 index 00000000..86086ab4 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/x448.py @@ -0,0 +1,112 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc + +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.bindings._rust import openssl as rust_openssl +from cryptography.hazmat.primitives import _serialization + + +class X448PublicKey(metaclass=abc.ABCMeta): + @classmethod + def from_public_bytes(cls, data: bytes) -> X448PublicKey: + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.x448_supported(): + raise UnsupportedAlgorithm( + "X448 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, + ) + + return rust_openssl.x448.from_public_bytes(data) + + @abc.abstractmethod + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: + """ + The serialized bytes of the public key. + """ + + @abc.abstractmethod + def public_bytes_raw(self) -> bytes: + """ + The raw bytes of the public key. + Equivalent to public_bytes(Raw, Raw). + """ + + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Checks equality. + """ + + +if hasattr(rust_openssl, "x448"): + X448PublicKey.register(rust_openssl.x448.X448PublicKey) + + +class X448PrivateKey(metaclass=abc.ABCMeta): + @classmethod + def generate(cls) -> X448PrivateKey: + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.x448_supported(): + raise UnsupportedAlgorithm( + "X448 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, + ) + + return rust_openssl.x448.generate_key() + + @classmethod + def from_private_bytes(cls, data: bytes) -> X448PrivateKey: + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.x448_supported(): + raise UnsupportedAlgorithm( + "X448 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, + ) + + return rust_openssl.x448.from_private_bytes(data) + + @abc.abstractmethod + def public_key(self) -> X448PublicKey: + """ + Returns the public key associated with this private key + """ + + @abc.abstractmethod + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: + """ + The serialized bytes of the private key. + """ + + @abc.abstractmethod + def private_bytes_raw(self) -> bytes: + """ + The raw bytes of the private key. + Equivalent to private_bytes(Raw, Raw, NoEncryption()). + """ + + @abc.abstractmethod + def exchange(self, peer_public_key: X448PublicKey) -> bytes: + """ + Performs a key exchange operation using the provided peer's public key. + """ + + +if hasattr(rust_openssl, "x448"): + X448PrivateKey.register(rust_openssl.x448.X448PrivateKey) diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__init__.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__init__.py new file mode 100644 index 00000000..cc88fbf2 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__init__.py @@ -0,0 +1,27 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +from cryptography.hazmat.primitives._cipheralgorithm import ( + BlockCipherAlgorithm, + CipherAlgorithm, +) +from cryptography.hazmat.primitives.ciphers.base import ( + AEADCipherContext, + AEADDecryptionContext, + AEADEncryptionContext, + Cipher, + CipherContext, +) + +__all__ = [ + "Cipher", + "CipherAlgorithm", + "BlockCipherAlgorithm", + "CipherContext", + "AEADCipherContext", + "AEADDecryptionContext", + "AEADEncryptionContext", +] diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..edac06b57e1e778bab612d724e14174d8a8ff5e2 GIT binary patch literal 764 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 iE^r)zdO|C+pnn0qa4x3+ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/algorithms.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/algorithms.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ab81c9e793e71f1cfa315db4e75885639f640f0a GIT binary patch literal 10491 zcmc&)O>7&-6`m!R)bgLAtXP(0XJy%r89P*BJBefD$Eu{nGEy~-oFFCC5EOSM(c+Ih zODPenv`pauav-285Wp80<@a+h50 z%0H+Q4Y`lA^Jd??o%!a?n>YM@AmAmC{`?+eCXtB5Wk{Bb za~$R!8AsL`ce1=Q!)IM_SJoYO!~IFgbDfX3ImjDC@?IyBPj=mQ5^@(VEyV@K^8+tn z;dvM@2)vMm=ViPw@Y*drALB)U*J0uL8Sen_IxW0_9Eb-UM0Q>c>H5h5IV?Q^CGC2N z)cM81+b(zqxU|F(CbJ7<9^8|fw2RChkl8D{Tl(w(Yws}dj#%33 zlsn^3w6xa=?LBE~@5nCgi6FDjBJ-epFy7T7^B~APYLeNvi_CtIdCc+-huAwD2i^%w zd)?Ag<0Km0#O{r9sxO(#BU}ic`(}kI= z8fq=@By}EjgFw|eD=(_9$;E=KsBS73=4mbks5TN}9q`F*{~0njNr5vsfUYCcNBrUM6MdhU*PDef~O%{az6a|UlNH28AdyB@A|dN+|o}$ zGw40{7!^SHCX!-gG`EnnVMB5-j=g+c2cIYl9F>Nc_OwT=N2a3OixZI>4N;s98^k9%gRKGF3uJ5(=<6Z zvp6u5EM}91fjOGarVHr>Ss6&N!Bz&0Ayr~?i=g;|Ow&_~30+eP_KO7JQmz6ik*|19 zmG3S;f2)6;KT+jRRQMDBaTCF}eD>oHuYb7O_wiEsrD{*C(uUuA!LAMe>%Z%`HU4?m zZ@cace%@R0zYgCofAGimwH(kbrz7OuAwX)x;qlho#2+eM-iFpl3W=VuV2J|;AaEZGmujE40DGQQM60Y;N;rY8Lilw+m^1vYbRp;Qy z_+|;pqCD+_pUuA@A%MFySS4*>D5A^+any=I{8`ADA-;srH355xBpNU#<7AB+TXV1; zX2ZVbPs^bRm%_`a#Q>ekTHN`yh}Kx!2KuYxqw8dPl6<5nJY0 zgk|{9PT)~oi&SSiS4bI+LkZ5FT@`Q4PV%ov_FdDSqfbI!!A8Wo z+B%9fwe`DxsIiTz0h~gS)pMVnzwyz^N9AklA+aKeOlj;FoNuhdA&>7sj{;fqVrSrl zNhDNnB9YBY^BK(h6Nzi{$&ALK5vZzqC()|038#9dXuc@t6uCgdC`-f&!W_-d$+WOY zpMu*pqV*T{IK^INq#H8I43LuX+3YQ*apx#|sj-eF10_{5gQXLxaEMn6`r75pR>) z*aQ$HHvnBw-2kEI&Yag?5s}{L>AizC?M1hevxLQlPP)w=#=1C;0^aWKK->X#iv!VO%_VLY9YYYZ z1fJ;sTP%DX_of$;^Gl^f?*&aYnk^p)jTHvFO0v*nJT zzqIb}T^?EM)8KrZw>%p~}Dz6Z8znn1WQfy8Z3 z0&Vg=np|&izul5Ua!R~;hi&#BVV(0!ZMe?K9w`8Ej8>EFm3)A%pen$I^nn(|H?rRqSv`E%V4{%kpbQWs?vvqEo+90`t8B2p_7g>93Weit@$48N~tcI%uUM; z=a@c+qL^>hV%#qw14$e%B@e`6+zo6VFCV|shlf)0wnG7&QDrfTxP?pY#NpWf(Vij1Hk&}uX<=B2< zpCRuW8XUj!yoUFa@NSzQ1KB^k2bnqs*cVWleFb}6Asy+9s1Wv(#UXhU3tKSzJuE|V z4K532BPM(L4Pq8GC=Rlo{eJ*!LMjh3A#vOI-c80Cyk{`VylqUxRga0d?5*y2mu`LrBVV+noQhej*{sDpvAU%-R=j4`H< zjzZ{$*2W#5OAOn2{}PwRjPA-!l{VDA?m{;w~PEuLp*` z=#^T+2Lkw_K9wII85!30ar**0Y~Fy~mpE|yYucDTI_&;{`aCl1l2{uF#^3E>2T@f^ zL~bu&hpiSbqV9VSJL|RxS6;~qITx(9cou={F53vTKu&=2z^;)j*cJ`VB;kAJ*_LpX z>dNKeEGSi<2=JcTM=0$0jRx`Q5E49VR^16E1L72TK%wm(u>l1Y6h-Z@LW@eb>m6)NxW8k??*p+p zW4R{;s=|@-2X|cSLaZvpDnjfl2xH9OxUh1e9QmiOr{e3m7wN4WzPKJ4tVRYa{=xfC z^uXziZy7#~ZKG+&2)(F{TNpAo@t_lawNziEV81d01(whqzEd%1ya9XZe?XanThkJ` zAL>~7QAOz1+C2(orgpJ27+&la&xaidJv^XT2X0I^9RGsmnhXaVx*5h*8-2u9w0`n~ zc@}MqdTqC{sB-Jpl|jgE|BBHRisWx_DL)2MGCmtV3{JM52-NsCS8t7&Nu(ZB>A?dX zjWiwT^uRghV;%UQLMgb6gyR9}few|`!nmbJThyH6-#xc~YnmTgH)hy9c+34=(wI6r zFz=%}kG!H~ur`tnxGXE0eoknEDD&wcJ6U>6#9*sq@Q(wG&awYvG|eCujAApW2Tw`0 zct;{Z5mc(b`L6-m9~MqD7sa%H3&a}#7KqjVEkIpHTP)hkPD$|?jGgnah(8^~+e_F^ zdqR)SjOGe5%_TFcw-KFT6Il%o8{wMK+}Rh|9$gJ4*cMrTin4tU`i*KJfsUiWz(pO( za8)yy z4<~*P7pf66>GE-K>}w?z?~yGm-f8f9+c=2fT1h3)w}r(!4c-B3E%u~cRWB-FC6!SB z78dU`c-=v)Y9*EMu`Mj#Y4DC(1+qr$q>|3V71F*z!X;Oggg1CU`(EC_|CDrXcsgo6 zH|N+QKz5MS7>VrGfM2wzO(F+N!G?SflmCV;KWs1GgYRl3%dc%==}v>ywVNisC#{;a wca{PTO$4UN>$)Z(driJ+`5pMCRuuku$31Ss^O;9mF!`zDh0m=l2VE_OC literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/base.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/base.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ab7a686321655a9f373420ec89a5add4d727354e GIT binary patch literal 13988 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/modes.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/modes.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b2c209c1ac749a8b849cbd5771ba0267013b9b2b GIT binary patch literal 13368 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 bytes: + if not isinstance(bit_length, int): + raise TypeError("bit_length must be an integer") + + if bit_length not in (128, 192, 256): + raise ValueError("bit_length must be 128, 192, or 256") + + return os.urandom(bit_length // 8) + + def encrypt( + self, + nonce: bytes, + data: bytes, + associated_data: bytes | None, + ) -> bytes: + if associated_data is None: + associated_data = b"" + + if len(data) > self._MAX_SIZE or len(associated_data) > self._MAX_SIZE: + # This is OverflowError to match what cffi would raise + raise OverflowError( + "Data or associated data too long. Max 2**31 - 1 bytes" + ) + + self._check_params(nonce, data, associated_data) + self._validate_lengths(nonce, len(data)) + return aead._encrypt( + backend, self, nonce, data, [associated_data], self._tag_length + ) + + def decrypt( + self, + nonce: bytes, + data: bytes, + associated_data: bytes | None, + ) -> bytes: + if associated_data is None: + associated_data = b"" + + self._check_params(nonce, data, associated_data) + return aead._decrypt( + backend, self, nonce, data, [associated_data], self._tag_length + ) + + def _validate_lengths(self, nonce: bytes, data_len: int) -> None: + # For information about computing this, see + # https://tools.ietf.org/html/rfc3610#section-2.1 + l_val = 15 - len(nonce) + if 2 ** (8 * l_val) < data_len: + raise ValueError("Data too long for nonce") + + def _check_params( + self, nonce: bytes, data: bytes, associated_data: bytes + ) -> None: + utils._check_byteslike("nonce", nonce) + utils._check_byteslike("data", data) + utils._check_byteslike("associated_data", associated_data) + if not 7 <= len(nonce) <= 13: + raise ValueError("Nonce must be between 7 and 13 bytes") + + +class AESGCM: + _MAX_SIZE = 2**31 - 1 + + def __init__(self, key: bytes): + utils._check_byteslike("key", key) + if len(key) not in (16, 24, 32): + raise ValueError("AESGCM key must be 128, 192, or 256 bits.") + + self._key = key + + @classmethod + def generate_key(cls, bit_length: int) -> bytes: + if not isinstance(bit_length, int): + raise TypeError("bit_length must be an integer") + + if bit_length not in (128, 192, 256): + raise ValueError("bit_length must be 128, 192, or 256") + + return os.urandom(bit_length // 8) + + def encrypt( + self, + nonce: bytes, + data: bytes, + associated_data: bytes | None, + ) -> bytes: + if associated_data is None: + associated_data = b"" + + if len(data) > self._MAX_SIZE or len(associated_data) > self._MAX_SIZE: + # This is OverflowError to match what cffi would raise + raise OverflowError( + "Data or associated data too long. Max 2**31 - 1 bytes" + ) + + self._check_params(nonce, data, associated_data) + return aead._encrypt(backend, self, nonce, data, [associated_data], 16) + + def decrypt( + self, + nonce: bytes, + data: bytes, + associated_data: bytes | None, + ) -> bytes: + if associated_data is None: + associated_data = b"" + + self._check_params(nonce, data, associated_data) + return aead._decrypt(backend, self, nonce, data, [associated_data], 16) + + def _check_params( + self, + nonce: bytes, + data: bytes, + associated_data: bytes, + ) -> None: + utils._check_byteslike("nonce", nonce) + utils._check_byteslike("data", data) + utils._check_byteslike("associated_data", associated_data) + if len(nonce) < 8 or len(nonce) > 128: + raise ValueError("Nonce must be between 8 and 128 bytes") diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/algorithms.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/algorithms.py new file mode 100644 index 00000000..000bdcba --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/algorithms.py @@ -0,0 +1,226 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +from cryptography import utils +from cryptography.hazmat.primitives.ciphers import ( + BlockCipherAlgorithm, + CipherAlgorithm, +) + + +def _verify_key_size(algorithm: CipherAlgorithm, key: bytes) -> bytes: + # Verify that the key is instance of bytes + utils._check_byteslike("key", key) + + # Verify that the key size matches the expected key size + if len(key) * 8 not in algorithm.key_sizes: + raise ValueError( + f"Invalid key size ({len(key) * 8}) for {algorithm.name}." + ) + return key + + +class AES(BlockCipherAlgorithm): + name = "AES" + block_size = 128 + # 512 added to support AES-256-XTS, which uses 512-bit keys + key_sizes = frozenset([128, 192, 256, 512]) + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 + + +class AES128(BlockCipherAlgorithm): + name = "AES" + block_size = 128 + key_sizes = frozenset([128]) + key_size = 128 + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + +class AES256(BlockCipherAlgorithm): + name = "AES" + block_size = 128 + key_sizes = frozenset([256]) + key_size = 256 + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + +class Camellia(BlockCipherAlgorithm): + name = "camellia" + block_size = 128 + key_sizes = frozenset([128, 192, 256]) + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 + + +class TripleDES(BlockCipherAlgorithm): + name = "3DES" + block_size = 64 + key_sizes = frozenset([64, 128, 192]) + + def __init__(self, key: bytes): + if len(key) == 8: + key += key + key + elif len(key) == 16: + key += key[:8] + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 + + +class Blowfish(BlockCipherAlgorithm): + name = "Blowfish" + block_size = 64 + key_sizes = frozenset(range(32, 449, 8)) + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 + + +_BlowfishInternal = Blowfish +utils.deprecated( + Blowfish, + __name__, + "Blowfish has been deprecated and will be removed in a future release", + utils.DeprecatedIn37, + name="Blowfish", +) + + +class CAST5(BlockCipherAlgorithm): + name = "CAST5" + block_size = 64 + key_sizes = frozenset(range(40, 129, 8)) + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 + + +_CAST5Internal = CAST5 +utils.deprecated( + CAST5, + __name__, + "CAST5 has been deprecated and will be removed in a future release", + utils.DeprecatedIn37, + name="CAST5", +) + + +class ARC4(CipherAlgorithm): + name = "RC4" + key_sizes = frozenset([40, 56, 64, 80, 128, 160, 192, 256]) + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 + + +class IDEA(BlockCipherAlgorithm): + name = "IDEA" + block_size = 64 + key_sizes = frozenset([128]) + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 + + +_IDEAInternal = IDEA +utils.deprecated( + IDEA, + __name__, + "IDEA has been deprecated and will be removed in a future release", + utils.DeprecatedIn37, + name="IDEA", +) + + +class SEED(BlockCipherAlgorithm): + name = "SEED" + block_size = 128 + key_sizes = frozenset([128]) + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 + + +_SEEDInternal = SEED +utils.deprecated( + SEED, + __name__, + "SEED has been deprecated and will be removed in a future release", + utils.DeprecatedIn37, + name="SEED", +) + + +class ChaCha20(CipherAlgorithm): + name = "ChaCha20" + key_sizes = frozenset([256]) + + def __init__(self, key: bytes, nonce: bytes): + self.key = _verify_key_size(self, key) + utils._check_byteslike("nonce", nonce) + + if len(nonce) != 16: + raise ValueError("nonce must be 128-bits (16 bytes)") + + self._nonce = nonce + + @property + def nonce(self) -> bytes: + return self._nonce + + @property + def key_size(self) -> int: + return len(self.key) * 8 + + +class SM4(BlockCipherAlgorithm): + name = "SM4" + block_size = 128 + key_sizes = frozenset([128]) + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/base.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/base.py new file mode 100644 index 00000000..2082df66 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/base.py @@ -0,0 +1,272 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc +import typing + +from cryptography.exceptions import ( + AlreadyFinalized, + AlreadyUpdated, + NotYetFinalized, +) +from cryptography.hazmat.primitives._cipheralgorithm import CipherAlgorithm +from cryptography.hazmat.primitives.ciphers import modes + +if typing.TYPE_CHECKING: + from cryptography.hazmat.backends.openssl.ciphers import ( + _CipherContext as _BackendCipherContext, + ) + + +class CipherContext(metaclass=abc.ABCMeta): + @abc.abstractmethod + def update(self, data: bytes) -> bytes: + """ + Processes the provided bytes through the cipher and returns the results + as bytes. + """ + + @abc.abstractmethod + def update_into(self, data: bytes, buf: bytes) -> int: + """ + Processes the provided bytes and writes the resulting data into the + provided buffer. Returns the number of bytes written. + """ + + @abc.abstractmethod + def finalize(self) -> bytes: + """ + Returns the results of processing the final block as bytes. + """ + + +class AEADCipherContext(CipherContext, metaclass=abc.ABCMeta): + @abc.abstractmethod + def authenticate_additional_data(self, data: bytes) -> None: + """ + Authenticates the provided bytes. + """ + + +class AEADDecryptionContext(AEADCipherContext, metaclass=abc.ABCMeta): + @abc.abstractmethod + def finalize_with_tag(self, tag: bytes) -> bytes: + """ + Returns the results of processing the final block as bytes and allows + delayed passing of the authentication tag. + """ + + +class AEADEncryptionContext(AEADCipherContext, metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def tag(self) -> bytes: + """ + Returns tag bytes. This is only available after encryption is + finalized. + """ + + +Mode = typing.TypeVar( + "Mode", bound=typing.Optional[modes.Mode], covariant=True +) + + +class Cipher(typing.Generic[Mode]): + def __init__( + self, + algorithm: CipherAlgorithm, + mode: Mode, + backend: typing.Any = None, + ) -> None: + if not isinstance(algorithm, CipherAlgorithm): + raise TypeError("Expected interface of CipherAlgorithm.") + + if mode is not None: + # mypy needs this assert to narrow the type from our generic + # type. Maybe it won't some time in the future. + assert isinstance(mode, modes.Mode) + mode.validate_for_algorithm(algorithm) + + self.algorithm = algorithm + self.mode = mode + + @typing.overload + def encryptor( + self: Cipher[modes.ModeWithAuthenticationTag], + ) -> AEADEncryptionContext: + ... + + @typing.overload + def encryptor( + self: _CIPHER_TYPE, + ) -> CipherContext: + ... + + def encryptor(self): + if isinstance(self.mode, modes.ModeWithAuthenticationTag): + if self.mode.tag is not None: + raise ValueError( + "Authentication tag must be None when encrypting." + ) + from cryptography.hazmat.backends.openssl.backend import backend + + ctx = backend.create_symmetric_encryption_ctx( + self.algorithm, self.mode + ) + return self._wrap_ctx(ctx, encrypt=True) + + @typing.overload + def decryptor( + self: Cipher[modes.ModeWithAuthenticationTag], + ) -> AEADDecryptionContext: + ... + + @typing.overload + def decryptor( + self: _CIPHER_TYPE, + ) -> CipherContext: + ... + + def decryptor(self): + from cryptography.hazmat.backends.openssl.backend import backend + + ctx = backend.create_symmetric_decryption_ctx( + self.algorithm, self.mode + ) + return self._wrap_ctx(ctx, encrypt=False) + + def _wrap_ctx( + self, ctx: _BackendCipherContext, encrypt: bool + ) -> AEADEncryptionContext | AEADDecryptionContext | CipherContext: + if isinstance(self.mode, modes.ModeWithAuthenticationTag): + if encrypt: + return _AEADEncryptionContext(ctx) + else: + return _AEADDecryptionContext(ctx) + else: + return _CipherContext(ctx) + + +_CIPHER_TYPE = Cipher[ + typing.Union[ + modes.ModeWithNonce, + modes.ModeWithTweak, + None, + modes.ECB, + modes.ModeWithInitializationVector, + ] +] + + +class _CipherContext(CipherContext): + _ctx: _BackendCipherContext | None + + def __init__(self, ctx: _BackendCipherContext) -> None: + self._ctx = ctx + + def update(self, data: bytes) -> bytes: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + return self._ctx.update(data) + + def update_into(self, data: bytes, buf: bytes) -> int: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + return self._ctx.update_into(data, buf) + + def finalize(self) -> bytes: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + data = self._ctx.finalize() + self._ctx = None + return data + + +class _AEADCipherContext(AEADCipherContext): + _ctx: _BackendCipherContext | None + _tag: bytes | None + + def __init__(self, ctx: _BackendCipherContext) -> None: + self._ctx = ctx + self._bytes_processed = 0 + self._aad_bytes_processed = 0 + self._tag = None + self._updated = False + + def _check_limit(self, data_size: int) -> None: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + self._updated = True + self._bytes_processed += data_size + if self._bytes_processed > self._ctx._mode._MAX_ENCRYPTED_BYTES: + raise ValueError( + "{} has a maximum encrypted byte limit of {}".format( + self._ctx._mode.name, self._ctx._mode._MAX_ENCRYPTED_BYTES + ) + ) + + def update(self, data: bytes) -> bytes: + self._check_limit(len(data)) + # mypy needs this assert even though _check_limit already checked + assert self._ctx is not None + return self._ctx.update(data) + + def update_into(self, data: bytes, buf: bytes) -> int: + self._check_limit(len(data)) + # mypy needs this assert even though _check_limit already checked + assert self._ctx is not None + return self._ctx.update_into(data, buf) + + def finalize(self) -> bytes: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + data = self._ctx.finalize() + self._tag = self._ctx.tag + self._ctx = None + return data + + def authenticate_additional_data(self, data: bytes) -> None: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + if self._updated: + raise AlreadyUpdated("Update has been called on this context.") + + self._aad_bytes_processed += len(data) + if self._aad_bytes_processed > self._ctx._mode._MAX_AAD_BYTES: + raise ValueError( + "{} has a maximum AAD byte limit of {}".format( + self._ctx._mode.name, self._ctx._mode._MAX_AAD_BYTES + ) + ) + + self._ctx.authenticate_additional_data(data) + + +class _AEADDecryptionContext(_AEADCipherContext, AEADDecryptionContext): + def finalize_with_tag(self, tag: bytes) -> bytes: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + if self._ctx._tag is not None: + raise ValueError( + "tag provided both in mode and in call with finalize_with_tag:" + " tag should only be provided once" + ) + data = self._ctx.finalize_with_tag(tag) + self._tag = self._ctx.tag + self._ctx = None + return data + + +class _AEADEncryptionContext(_AEADCipherContext, AEADEncryptionContext): + @property + def tag(self) -> bytes: + if self._ctx is not None: + raise NotYetFinalized( + "You must finalize encryption before " "getting the tag." + ) + assert self._tag is not None + return self._tag diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/modes.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/modes.py new file mode 100644 index 00000000..712ccd3f --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/modes.py @@ -0,0 +1,273 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc + +from cryptography import utils +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.primitives._cipheralgorithm import ( + BlockCipherAlgorithm, + CipherAlgorithm, +) +from cryptography.hazmat.primitives.ciphers import algorithms + + +class Mode(metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def name(self) -> str: + """ + A string naming this mode (e.g. "ECB", "CBC"). + """ + + @abc.abstractmethod + def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: + """ + Checks that all the necessary invariants of this (mode, algorithm) + combination are met. + """ + + +class ModeWithInitializationVector(Mode, metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def initialization_vector(self) -> bytes: + """ + The value of the initialization vector for this mode as bytes. + """ + + +class ModeWithTweak(Mode, metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def tweak(self) -> bytes: + """ + The value of the tweak for this mode as bytes. + """ + + +class ModeWithNonce(Mode, metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def nonce(self) -> bytes: + """ + The value of the nonce for this mode as bytes. + """ + + +class ModeWithAuthenticationTag(Mode, metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def tag(self) -> bytes | None: + """ + The value of the tag supplied to the constructor of this mode. + """ + + +def _check_aes_key_length(self: Mode, algorithm: CipherAlgorithm) -> None: + if algorithm.key_size > 256 and algorithm.name == "AES": + raise ValueError( + "Only 128, 192, and 256 bit keys are allowed for this AES mode" + ) + + +def _check_iv_length( + self: ModeWithInitializationVector, algorithm: BlockCipherAlgorithm +) -> None: + if len(self.initialization_vector) * 8 != algorithm.block_size: + raise ValueError( + "Invalid IV size ({}) for {}.".format( + len(self.initialization_vector), self.name + ) + ) + + +def _check_nonce_length( + nonce: bytes, name: str, algorithm: CipherAlgorithm +) -> None: + if not isinstance(algorithm, BlockCipherAlgorithm): + raise UnsupportedAlgorithm( + f"{name} requires a block cipher algorithm", + _Reasons.UNSUPPORTED_CIPHER, + ) + if len(nonce) * 8 != algorithm.block_size: + raise ValueError(f"Invalid nonce size ({len(nonce)}) for {name}.") + + +def _check_iv_and_key_length( + self: ModeWithInitializationVector, algorithm: CipherAlgorithm +) -> None: + if not isinstance(algorithm, BlockCipherAlgorithm): + raise UnsupportedAlgorithm( + f"{self} requires a block cipher algorithm", + _Reasons.UNSUPPORTED_CIPHER, + ) + _check_aes_key_length(self, algorithm) + _check_iv_length(self, algorithm) + + +class CBC(ModeWithInitializationVector): + name = "CBC" + + def __init__(self, initialization_vector: bytes): + utils._check_byteslike("initialization_vector", initialization_vector) + self._initialization_vector = initialization_vector + + @property + def initialization_vector(self) -> bytes: + return self._initialization_vector + + validate_for_algorithm = _check_iv_and_key_length + + +class XTS(ModeWithTweak): + name = "XTS" + + def __init__(self, tweak: bytes): + utils._check_byteslike("tweak", tweak) + + if len(tweak) != 16: + raise ValueError("tweak must be 128-bits (16 bytes)") + + self._tweak = tweak + + @property + def tweak(self) -> bytes: + return self._tweak + + def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: + if isinstance(algorithm, (algorithms.AES128, algorithms.AES256)): + raise TypeError( + "The AES128 and AES256 classes do not support XTS, please use " + "the standard AES class instead." + ) + + if algorithm.key_size not in (256, 512): + raise ValueError( + "The XTS specification requires a 256-bit key for AES-128-XTS" + " and 512-bit key for AES-256-XTS" + ) + + +class ECB(Mode): + name = "ECB" + + validate_for_algorithm = _check_aes_key_length + + +class OFB(ModeWithInitializationVector): + name = "OFB" + + def __init__(self, initialization_vector: bytes): + utils._check_byteslike("initialization_vector", initialization_vector) + self._initialization_vector = initialization_vector + + @property + def initialization_vector(self) -> bytes: + return self._initialization_vector + + validate_for_algorithm = _check_iv_and_key_length + + +class CFB(ModeWithInitializationVector): + name = "CFB" + + def __init__(self, initialization_vector: bytes): + utils._check_byteslike("initialization_vector", initialization_vector) + self._initialization_vector = initialization_vector + + @property + def initialization_vector(self) -> bytes: + return self._initialization_vector + + validate_for_algorithm = _check_iv_and_key_length + + +class CFB8(ModeWithInitializationVector): + name = "CFB8" + + def __init__(self, initialization_vector: bytes): + utils._check_byteslike("initialization_vector", initialization_vector) + self._initialization_vector = initialization_vector + + @property + def initialization_vector(self) -> bytes: + return self._initialization_vector + + validate_for_algorithm = _check_iv_and_key_length + + +class CTR(ModeWithNonce): + name = "CTR" + + def __init__(self, nonce: bytes): + utils._check_byteslike("nonce", nonce) + self._nonce = nonce + + @property + def nonce(self) -> bytes: + return self._nonce + + def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: + _check_aes_key_length(self, algorithm) + _check_nonce_length(self.nonce, self.name, algorithm) + + +class GCM(ModeWithInitializationVector, ModeWithAuthenticationTag): + name = "GCM" + _MAX_ENCRYPTED_BYTES = (2**39 - 256) // 8 + _MAX_AAD_BYTES = (2**64) // 8 + + def __init__( + self, + initialization_vector: bytes, + tag: bytes | None = None, + min_tag_length: int = 16, + ): + # OpenSSL 3.0.0 constrains GCM IVs to [64, 1024] bits inclusive + # This is a sane limit anyway so we'll enforce it here. + utils._check_byteslike("initialization_vector", initialization_vector) + if len(initialization_vector) < 8 or len(initialization_vector) > 128: + raise ValueError( + "initialization_vector must be between 8 and 128 bytes (64 " + "and 1024 bits)." + ) + self._initialization_vector = initialization_vector + if tag is not None: + utils._check_bytes("tag", tag) + if min_tag_length < 4: + raise ValueError("min_tag_length must be >= 4") + if len(tag) < min_tag_length: + raise ValueError( + "Authentication tag must be {} bytes or longer.".format( + min_tag_length + ) + ) + self._tag = tag + self._min_tag_length = min_tag_length + + @property + def tag(self) -> bytes | None: + return self._tag + + @property + def initialization_vector(self) -> bytes: + return self._initialization_vector + + def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: + _check_aes_key_length(self, algorithm) + if not isinstance(algorithm, BlockCipherAlgorithm): + raise UnsupportedAlgorithm( + "GCM requires a block cipher algorithm", + _Reasons.UNSUPPORTED_CIPHER, + ) + block_size_bytes = algorithm.block_size // 8 + if self._tag is not None and len(self._tag) > block_size_bytes: + raise ValueError( + "Authentication tag cannot be more than {} bytes.".format( + block_size_bytes + ) + ) diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/cmac.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/cmac.py new file mode 100644 index 00000000..2c67ce22 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/cmac.py @@ -0,0 +1,10 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +from cryptography.hazmat.bindings._rust import openssl as rust_openssl + +__all__ = ["CMAC"] +CMAC = rust_openssl.cmac.CMAC diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/constant_time.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/constant_time.py new file mode 100644 index 00000000..3975c714 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/constant_time.py @@ -0,0 +1,14 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import hmac + + +def bytes_eq(a: bytes, b: bytes) -> bool: + if not isinstance(a, bytes) or not isinstance(b, bytes): + raise TypeError("a and b must be bytes.") + + return hmac.compare_digest(a, b) diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/hashes.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/hashes.py new file mode 100644 index 00000000..c5be0c8e --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/hashes.py @@ -0,0 +1,242 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc + +from cryptography.hazmat.bindings._rust import openssl as rust_openssl + +__all__ = [ + "HashAlgorithm", + "HashContext", + "Hash", + "ExtendableOutputFunction", + "SHA1", + "SHA512_224", + "SHA512_256", + "SHA224", + "SHA256", + "SHA384", + "SHA512", + "SHA3_224", + "SHA3_256", + "SHA3_384", + "SHA3_512", + "SHAKE128", + "SHAKE256", + "MD5", + "BLAKE2b", + "BLAKE2s", + "SM3", +] + + +class HashAlgorithm(metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def name(self) -> str: + """ + A string naming this algorithm (e.g. "sha256", "md5"). + """ + + @property + @abc.abstractmethod + def digest_size(self) -> int: + """ + The size of the resulting digest in bytes. + """ + + @property + @abc.abstractmethod + def block_size(self) -> int | None: + """ + The internal block size of the hash function, or None if the hash + function does not use blocks internally (e.g. SHA3). + """ + + +class HashContext(metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def algorithm(self) -> HashAlgorithm: + """ + A HashAlgorithm that will be used by this context. + """ + + @abc.abstractmethod + def update(self, data: bytes) -> None: + """ + Processes the provided bytes through the hash. + """ + + @abc.abstractmethod + def finalize(self) -> bytes: + """ + Finalizes the hash context and returns the hash digest as bytes. + """ + + @abc.abstractmethod + def copy(self) -> HashContext: + """ + Return a HashContext that is a copy of the current context. + """ + + +Hash = rust_openssl.hashes.Hash +HashContext.register(Hash) + + +class ExtendableOutputFunction(metaclass=abc.ABCMeta): + """ + An interface for extendable output functions. + """ + + +class SHA1(HashAlgorithm): + name = "sha1" + digest_size = 20 + block_size = 64 + + +class SHA512_224(HashAlgorithm): # noqa: N801 + name = "sha512-224" + digest_size = 28 + block_size = 128 + + +class SHA512_256(HashAlgorithm): # noqa: N801 + name = "sha512-256" + digest_size = 32 + block_size = 128 + + +class SHA224(HashAlgorithm): + name = "sha224" + digest_size = 28 + block_size = 64 + + +class SHA256(HashAlgorithm): + name = "sha256" + digest_size = 32 + block_size = 64 + + +class SHA384(HashAlgorithm): + name = "sha384" + digest_size = 48 + block_size = 128 + + +class SHA512(HashAlgorithm): + name = "sha512" + digest_size = 64 + block_size = 128 + + +class SHA3_224(HashAlgorithm): # noqa: N801 + name = "sha3-224" + digest_size = 28 + block_size = None + + +class SHA3_256(HashAlgorithm): # noqa: N801 + name = "sha3-256" + digest_size = 32 + block_size = None + + +class SHA3_384(HashAlgorithm): # noqa: N801 + name = "sha3-384" + digest_size = 48 + block_size = None + + +class SHA3_512(HashAlgorithm): # noqa: N801 + name = "sha3-512" + digest_size = 64 + block_size = None + + +class SHAKE128(HashAlgorithm, ExtendableOutputFunction): + name = "shake128" + block_size = None + + def __init__(self, digest_size: int): + if not isinstance(digest_size, int): + raise TypeError("digest_size must be an integer") + + if digest_size < 1: + raise ValueError("digest_size must be a positive integer") + + self._digest_size = digest_size + + @property + def digest_size(self) -> int: + return self._digest_size + + +class SHAKE256(HashAlgorithm, ExtendableOutputFunction): + name = "shake256" + block_size = None + + def __init__(self, digest_size: int): + if not isinstance(digest_size, int): + raise TypeError("digest_size must be an integer") + + if digest_size < 1: + raise ValueError("digest_size must be a positive integer") + + self._digest_size = digest_size + + @property + def digest_size(self) -> int: + return self._digest_size + + +class MD5(HashAlgorithm): + name = "md5" + digest_size = 16 + block_size = 64 + + +class BLAKE2b(HashAlgorithm): + name = "blake2b" + _max_digest_size = 64 + _min_digest_size = 1 + block_size = 128 + + def __init__(self, digest_size: int): + if digest_size != 64: + raise ValueError("Digest size must be 64") + + self._digest_size = digest_size + + @property + def digest_size(self) -> int: + return self._digest_size + + +class BLAKE2s(HashAlgorithm): + name = "blake2s" + block_size = 64 + _max_digest_size = 32 + _min_digest_size = 1 + + def __init__(self, digest_size: int): + if digest_size != 32: + raise ValueError("Digest size must be 32") + + self._digest_size = digest_size + + @property + def digest_size(self) -> int: + return self._digest_size + + +class SM3(HashAlgorithm): + name = "sm3" + digest_size = 32 + block_size = 64 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/hmac.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/hmac.py new file mode 100644 index 00000000..a9442d59 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/hmac.py @@ -0,0 +1,13 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +from cryptography.hazmat.bindings._rust import openssl as rust_openssl +from cryptography.hazmat.primitives import hashes + +__all__ = ["HMAC"] + +HMAC = rust_openssl.hmac.HMAC +hashes.HashContext.register(HMAC) diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__init__.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__init__.py new file mode 100644 index 00000000..79bb459f --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__init__.py @@ -0,0 +1,23 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc + + +class KeyDerivationFunction(metaclass=abc.ABCMeta): + @abc.abstractmethod + def derive(self, key_material: bytes) -> bytes: + """ + Deterministically generates and returns a new key based on the existing + key material. + """ + + @abc.abstractmethod + def verify(self, key_material: bytes, expected_key: bytes) -> None: + """ + Checks whether the key generated by the key material matches the + expected derived key. Raises an exception if they do not match. + """ diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1358ce1da599076695ddbcae62edb23356cf87c4 GIT binary patch literal 1373 zcmZ`(J8u&~5Z*hVFOK8z6beO(6;v*8dW4V&5kUf61ZXUy(|UItUvdw#dp5aLDe@nX zs3;H!g_i$8L4mG9qM|{LOa%=ycezs#VQtOL&dkny^UdD9TV8H5T)#Iz!VjCVZ?q{_ zy-=+AIw~)jV#*3wX!R_MbUUznw#_z~svR=rfW1>I4}Pe>Mg6GS_Z($EW^MO71+=Yf zNkmbch{TU0)0O2ZdY&Ay=3BUV$$<4N#dcAPRyEh^{Gd5hbl(!_f8zapAy;hzXs zH4ws5cI5%28=(DZUjE)Bk_01b?Lz8>B0-M`vicxRz+|q5WTGR9#8k^d4N+Qi7ZoJM z!mRdw+~g-~129MEN4`mXDS{y7+Yo`q%!Z3d@ggPaJc1V-tMY*`pm-edWCR@c=wP&6 z<)eraSEsUe-(%IxF%S$j0Wk!T^Itm~H~TVHn4teO9zMA*P5miES`_snc;1Z)-6grE4Rxk7d`!+7JE2pMqK2Rl_yU!_E@V>x|RP zRYW7~ub#QzuAHg^M!z|3S=NHRF~|gzhuvjPH;zD_OrHGgY>r=5-QOJn_QhX} z04dWsZ$wi`wBm!bGM3yCiE@NPz#~q}*zexUttl@c)2*LBRrssvRngpb`Jn#8L1Sg)F7|86L7??y0nS@AYtn@Oa zyG(*w%2DL-HGK_oL3YzaQH+%2mwMxKePw1l_127);<(1#tChLM+{J41pP0&Al%Jd!l(k|-@t!0ZWaCC)~gsxcgs9OF{@dY oHES~K`X_en^#3bs9^}87yKG@U|BBc0&2DZ#Cg;yHBJu|Q0GOIrwEzGB literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/concatkdf.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/concatkdf.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9c2540f3cf47e69e6d707fa79e265bb90fa98aa3 GIT binary patch literal 6058 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/kbkdf.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/kbkdf.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0c13596c2a4f7022918467fd6897afc2567b711c GIT binary patch literal 12053 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/pbkdf2.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/pbkdf2.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d8319a19849f03034da8083af277ce8c1fa5bf7c GIT binary patch literal 3069 zcmbVO&2Jk;6rc6S#-CZ+`Dp2<)j;W%;?Pi#r~ow((g3Zg`oY19wA$=W;!SqfW_BIb zA(g7ChaP%DNadJQ`RIiU|A$jqsx=}K5^&(=D&_{a7ebkORu}VzHVs_k- zE3z|E8F3Pogp;f!g*&`5jFJ}4poV#b=R%=x^LB7uMFdO!?$ctjq%*9&8TiR=Pg&atqp4O)Tiz` zu;%Bq$;WTFUZY;GF`t^V_DYRee%0X#?JCthSP2#ysnx0LdA1tiSp!7A?)sWdHr-&&|&)T%P^7%#(WG$miq1_N4`|V$XEhrtXSgT{fV~)JFj?BoNg~b?#1`UwOP0u{ zycHSH4B1WTA?QAWf6%-cAJEfpW^^mo=Lh>uX|;zbLWbx2nLWMLaHWT^_oHzCJCYgO zBwC`cxhcUY8IB?_5?Drwf1ocXWHnsdjBiGV*Mt*BVP3Ycy@@-F_D3dxpvYy0Ca4md zgl=Q{>sv+3D+2zCA()EGHC7BFS6pfq{VFK*oL-t|V>nykXAIV?`?VFO*Q?D^Ro`%Q zztq$6N*c&r8qIB(yh1gSrM?EUi;_eesgD zwCKTZZ`MIcU!mUOpqHitFHP5(F@Hn^789(}M`Drwg zFFYea{+3Dpm3B^jnv9Q)J|jT7B%U4ZX2|5>d$Iee&Y>yjl+J;p&}DWK*>>X4ckgbU z+fJNnCr-5zr#cg_2))Cv-HWvo2V3IV1!Ey7YqY6BY@x{LHkTRo8_YGrJOCB+w#e9@ zfO$YR$tv_gV~XD^KR7o3lc$hFm?u45$diFQT@B~GEPG*}Fn@s$YY6aR&H^81=tIzc z6wZKLik3HC@8yXls;fc0qM^IRnrk&oivy`C2bYcoa~; z3nms}stx1_JB|}hAell^1foXRtH`TBJoI6)$WB7X2%M+q@X!I+Fcz{=- zyBRu?rvs;ob9#6xtP;HttV0Nwn?oT8L?3{jHwy$pFnQ>~+Ba)kXSOG&+mqAx(mTqL zw({E6+RyKAD;L_z1q{#IJB1^yqi44ZGws4mD>KuLf=s*+-d3funhHu-4i*jSSOGav z%*K%u6-~&nZZNz+;4laqCf=X!bE-Tb#Ul>9KZ~vyH4RFy=G4rFjeJJazG~=p z@P@sPGld)90q#d43>AK1cmWB5HhC2wx5Hm|lpLSxW)H?scF8{ETsjUY8zzUMaqz`U zNU$yLsE(nv%MGYDU@b#1ayj^9;F-a)99$g-21O-$)1Y#`6p^M{-=LoT%T ddpcyUHT-ntHzWw}i=>r5`4q*^_IW3~@Gmb3=EDF0 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/scrypt.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/scrypt.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..26cff8004b123d7b6d8631632aa16e236221a293 GIT binary patch literal 3436 zcmb7G&2JmW6`x&xEh$nNeB(Au- zq-U3^Nic;F_#hNMv^~`7O(&&=F1_^sAPoW`77$<{2vDOv(2!5=rSHv>E6S3AcDQ`= z=FOY$-}}vclgXqAr2pLc2c1t6@*NfiDHbTg$)7=aN(^EM7O{n*AfPT8>|`;?Z80llj}+5fk6Rggv^dK3geBYAVpbqj+`cpz+K?I| zA;p|X?hqsSm>4OVJ&X`?1pgov#|-fv$&b9iVqWk^G{>oUnrBuVcMZz1nrB*WKH_H= zEk-q?e%o|3%WP1?Pu+EPKs7$6b$|Rz$E{VX73NW6(b}po(<|A~JW;7q$8{}GGdgtX zX^y9QrcJ>x0S%WZGk5rCw`-1$qrQL%6Frz*Ap3I_PJRgGr-YKCV34AiBu35{Ge#cA zVBf}#(Z|tZ)R-_XK^`*%Skt5*zo)Z$)m!tUu4Z|DY@_Z`*N@&B?t{_ zZ3bJEg5)is^f))u%`U!- zh-0I#2ncAN8STZ%J5zhnC+TA;(~&Oke|qqfwsgHCU2jR(yCdnnhrj=1?~^}#vH#(| z_Lpmad~oo^v+yNZ=Ks*9(kDC`u1L^@xyM6OMD!t*fUv>jUO{ z#Ol=k@BZ3sOA8%op(QPRFTdB3uY4=td?w%Qrr+tNvrm4B;?Ai!PETTC<)tiTQ?Ce! z9+8qM_AyQ>O&?XM4!5}qX!E0M6^H5}0Kfqm2g<_9BTx`x2aumn02JWd(_8MV$T0l2 zL(syFAfCO~-ncE_=;v#A0>E*LYmFSdB3z(;PW%uRda00)vLC@z7(&UHI323=Aww)e zRd@(&4(msP?dI!raaG80{eyu!#@wuj2NM)m!N*+$0S7aA`Dyu2<%1jT$=S~2?B2++ z{C-Eic2NHNLRV&gq>fmjmc7=Z1pn2y9? zTizmqadEW#I8Jx72BZhmWr#^X;@06=7rfj2^ziKxg!B)FO$GW$r&a#I4Wb@#5!|QK zXZ!{?v+3Y9=N43?0ft<~Zs4d>7kQsvV*&gw?DEv90A#|D=KO@MJ#yh)&1P``zPYzh z!)W9i{#sfH4(aD?32gY3asLGZ@FWPm6cMhr$n@~{oTPU7uS+t!{P&zpwa$J$F)D~X z^8W}J>5kAMw}-zj`C04i*Ck7>vtLglqnDmM*k5dCKG;q5;y)GOxX+7LX8I+XUtLhg GH{-viqd&m_ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/x963kdf.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/x963kdf.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6bc21210d3514a46b01b9075cd32d03c3786f3c4 GIT binary patch literal 3451 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/concatkdf.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/concatkdf.py new file mode 100644 index 00000000..96d9d4c0 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/concatkdf.py @@ -0,0 +1,124 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import typing + +from cryptography import utils +from cryptography.exceptions import AlreadyFinalized, InvalidKey +from cryptography.hazmat.primitives import constant_time, hashes, hmac +from cryptography.hazmat.primitives.kdf import KeyDerivationFunction + + +def _int_to_u32be(n: int) -> bytes: + return n.to_bytes(length=4, byteorder="big") + + +def _common_args_checks( + algorithm: hashes.HashAlgorithm, + length: int, + otherinfo: bytes | None, +) -> None: + max_length = algorithm.digest_size * (2**32 - 1) + if length > max_length: + raise ValueError(f"Cannot derive keys larger than {max_length} bits.") + if otherinfo is not None: + utils._check_bytes("otherinfo", otherinfo) + + +def _concatkdf_derive( + key_material: bytes, + length: int, + auxfn: typing.Callable[[], hashes.HashContext], + otherinfo: bytes, +) -> bytes: + utils._check_byteslike("key_material", key_material) + output = [b""] + outlen = 0 + counter = 1 + + while length > outlen: + h = auxfn() + h.update(_int_to_u32be(counter)) + h.update(key_material) + h.update(otherinfo) + output.append(h.finalize()) + outlen += len(output[-1]) + counter += 1 + + return b"".join(output)[:length] + + +class ConcatKDFHash(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + length: int, + otherinfo: bytes | None, + backend: typing.Any = None, + ): + _common_args_checks(algorithm, length, otherinfo) + self._algorithm = algorithm + self._length = length + self._otherinfo: bytes = otherinfo if otherinfo is not None else b"" + + self._used = False + + def _hash(self) -> hashes.Hash: + return hashes.Hash(self._algorithm) + + def derive(self, key_material: bytes) -> bytes: + if self._used: + raise AlreadyFinalized + self._used = True + return _concatkdf_derive( + key_material, self._length, self._hash, self._otherinfo + ) + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey + + +class ConcatKDFHMAC(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + length: int, + salt: bytes | None, + otherinfo: bytes | None, + backend: typing.Any = None, + ): + _common_args_checks(algorithm, length, otherinfo) + self._algorithm = algorithm + self._length = length + self._otherinfo: bytes = otherinfo if otherinfo is not None else b"" + + if algorithm.block_size is None: + raise TypeError(f"{algorithm.name} is unsupported for ConcatKDF") + + if salt is None: + salt = b"\x00" * algorithm.block_size + else: + utils._check_bytes("salt", salt) + + self._salt = salt + + self._used = False + + def _hmac(self) -> hmac.HMAC: + return hmac.HMAC(self._salt, self._algorithm) + + def derive(self, key_material: bytes) -> bytes: + if self._used: + raise AlreadyFinalized + self._used = True + return _concatkdf_derive( + key_material, self._length, self._hmac, self._otherinfo + ) + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/hkdf.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/hkdf.py new file mode 100644 index 00000000..ee562d2f --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/hkdf.py @@ -0,0 +1,101 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import typing + +from cryptography import utils +from cryptography.exceptions import AlreadyFinalized, InvalidKey +from cryptography.hazmat.primitives import constant_time, hashes, hmac +from cryptography.hazmat.primitives.kdf import KeyDerivationFunction + + +class HKDF(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + length: int, + salt: bytes | None, + info: bytes | None, + backend: typing.Any = None, + ): + self._algorithm = algorithm + + if salt is None: + salt = b"\x00" * self._algorithm.digest_size + else: + utils._check_bytes("salt", salt) + + self._salt = salt + + self._hkdf_expand = HKDFExpand(self._algorithm, length, info) + + def _extract(self, key_material: bytes) -> bytes: + h = hmac.HMAC(self._salt, self._algorithm) + h.update(key_material) + return h.finalize() + + def derive(self, key_material: bytes) -> bytes: + utils._check_byteslike("key_material", key_material) + return self._hkdf_expand.derive(self._extract(key_material)) + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey + + +class HKDFExpand(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + length: int, + info: bytes | None, + backend: typing.Any = None, + ): + self._algorithm = algorithm + + max_length = 255 * algorithm.digest_size + + if length > max_length: + raise ValueError( + f"Cannot derive keys larger than {max_length} octets." + ) + + self._length = length + + if info is None: + info = b"" + else: + utils._check_bytes("info", info) + + self._info = info + + self._used = False + + def _expand(self, key_material: bytes) -> bytes: + output = [b""] + counter = 1 + + while self._algorithm.digest_size * (len(output) - 1) < self._length: + h = hmac.HMAC(key_material, self._algorithm) + h.update(output[-1]) + h.update(self._info) + h.update(bytes([counter])) + output.append(h.finalize()) + counter += 1 + + return b"".join(output)[: self._length] + + def derive(self, key_material: bytes) -> bytes: + utils._check_byteslike("key_material", key_material) + if self._used: + raise AlreadyFinalized + + self._used = True + return self._expand(key_material) + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/kbkdf.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/kbkdf.py new file mode 100644 index 00000000..2f41db92 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/kbkdf.py @@ -0,0 +1,299 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import typing + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, + InvalidKey, + UnsupportedAlgorithm, + _Reasons, +) +from cryptography.hazmat.primitives import ( + ciphers, + cmac, + constant_time, + hashes, + hmac, +) +from cryptography.hazmat.primitives.kdf import KeyDerivationFunction + + +class Mode(utils.Enum): + CounterMode = "ctr" + + +class CounterLocation(utils.Enum): + BeforeFixed = "before_fixed" + AfterFixed = "after_fixed" + MiddleFixed = "middle_fixed" + + +class _KBKDFDeriver: + def __init__( + self, + prf: typing.Callable, + mode: Mode, + length: int, + rlen: int, + llen: int | None, + location: CounterLocation, + break_location: int | None, + label: bytes | None, + context: bytes | None, + fixed: bytes | None, + ): + assert callable(prf) + + if not isinstance(mode, Mode): + raise TypeError("mode must be of type Mode") + + if not isinstance(location, CounterLocation): + raise TypeError("location must be of type CounterLocation") + + if break_location is None and location is CounterLocation.MiddleFixed: + raise ValueError("Please specify a break_location") + + if ( + break_location is not None + and location != CounterLocation.MiddleFixed + ): + raise ValueError( + "break_location is ignored when location is not" + " CounterLocation.MiddleFixed" + ) + + if break_location is not None and not isinstance(break_location, int): + raise TypeError("break_location must be an integer") + + if break_location is not None and break_location < 0: + raise ValueError("break_location must be a positive integer") + + if (label or context) and fixed: + raise ValueError( + "When supplying fixed data, " "label and context are ignored." + ) + + if rlen is None or not self._valid_byte_length(rlen): + raise ValueError("rlen must be between 1 and 4") + + if llen is None and fixed is None: + raise ValueError("Please specify an llen") + + if llen is not None and not isinstance(llen, int): + raise TypeError("llen must be an integer") + + if label is None: + label = b"" + + if context is None: + context = b"" + + utils._check_bytes("label", label) + utils._check_bytes("context", context) + self._prf = prf + self._mode = mode + self._length = length + self._rlen = rlen + self._llen = llen + self._location = location + self._break_location = break_location + self._label = label + self._context = context + self._used = False + self._fixed_data = fixed + + @staticmethod + def _valid_byte_length(value: int) -> bool: + if not isinstance(value, int): + raise TypeError("value must be of type int") + + value_bin = utils.int_to_bytes(1, value) + if not 1 <= len(value_bin) <= 4: + return False + return True + + def derive(self, key_material: bytes, prf_output_size: int) -> bytes: + if self._used: + raise AlreadyFinalized + + utils._check_byteslike("key_material", key_material) + self._used = True + + # inverse floor division (equivalent to ceiling) + rounds = -(-self._length // prf_output_size) + + output = [b""] + + # For counter mode, the number of iterations shall not be + # larger than 2^r-1, where r <= 32 is the binary length of the counter + # This ensures that the counter values used as an input to the + # PRF will not repeat during a particular call to the KDF function. + r_bin = utils.int_to_bytes(1, self._rlen) + if rounds > pow(2, len(r_bin) * 8) - 1: + raise ValueError("There are too many iterations.") + + fixed = self._generate_fixed_input() + + if self._location == CounterLocation.BeforeFixed: + data_before_ctr = b"" + data_after_ctr = fixed + elif self._location == CounterLocation.AfterFixed: + data_before_ctr = fixed + data_after_ctr = b"" + else: + if isinstance( + self._break_location, int + ) and self._break_location > len(fixed): + raise ValueError("break_location offset > len(fixed)") + data_before_ctr = fixed[: self._break_location] + data_after_ctr = fixed[self._break_location :] + + for i in range(1, rounds + 1): + h = self._prf(key_material) + + counter = utils.int_to_bytes(i, self._rlen) + input_data = data_before_ctr + counter + data_after_ctr + + h.update(input_data) + + output.append(h.finalize()) + + return b"".join(output)[: self._length] + + def _generate_fixed_input(self) -> bytes: + if self._fixed_data and isinstance(self._fixed_data, bytes): + return self._fixed_data + + l_val = utils.int_to_bytes(self._length * 8, self._llen) + + return b"".join([self._label, b"\x00", self._context, l_val]) + + +class KBKDFHMAC(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + mode: Mode, + length: int, + rlen: int, + llen: int | None, + location: CounterLocation, + label: bytes | None, + context: bytes | None, + fixed: bytes | None, + backend: typing.Any = None, + *, + break_location: int | None = None, + ): + if not isinstance(algorithm, hashes.HashAlgorithm): + raise UnsupportedAlgorithm( + "Algorithm supplied is not a supported hash algorithm.", + _Reasons.UNSUPPORTED_HASH, + ) + + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + if not ossl.hmac_supported(algorithm): + raise UnsupportedAlgorithm( + "Algorithm supplied is not a supported hmac algorithm.", + _Reasons.UNSUPPORTED_HASH, + ) + + self._algorithm = algorithm + + self._deriver = _KBKDFDeriver( + self._prf, + mode, + length, + rlen, + llen, + location, + break_location, + label, + context, + fixed, + ) + + def _prf(self, key_material: bytes) -> hmac.HMAC: + return hmac.HMAC(key_material, self._algorithm) + + def derive(self, key_material: bytes) -> bytes: + return self._deriver.derive(key_material, self._algorithm.digest_size) + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey + + +class KBKDFCMAC(KeyDerivationFunction): + def __init__( + self, + algorithm, + mode: Mode, + length: int, + rlen: int, + llen: int | None, + location: CounterLocation, + label: bytes | None, + context: bytes | None, + fixed: bytes | None, + backend: typing.Any = None, + *, + break_location: int | None = None, + ): + if not issubclass( + algorithm, ciphers.BlockCipherAlgorithm + ) or not issubclass(algorithm, ciphers.CipherAlgorithm): + raise UnsupportedAlgorithm( + "Algorithm supplied is not a supported cipher algorithm.", + _Reasons.UNSUPPORTED_CIPHER, + ) + + self._algorithm = algorithm + self._cipher: ciphers.BlockCipherAlgorithm | None = None + + self._deriver = _KBKDFDeriver( + self._prf, + mode, + length, + rlen, + llen, + location, + break_location, + label, + context, + fixed, + ) + + def _prf(self, _: bytes) -> cmac.CMAC: + assert self._cipher is not None + + return cmac.CMAC(self._cipher) + + def derive(self, key_material: bytes) -> bytes: + self._cipher = self._algorithm(key_material) + + assert self._cipher is not None + + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + if not ossl.cmac_algorithm_supported(self._cipher): + raise UnsupportedAlgorithm( + "Algorithm supplied is not a supported cipher algorithm.", + _Reasons.UNSUPPORTED_CIPHER, + ) + + return self._deriver.derive(key_material, self._cipher.block_size // 8) + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/pbkdf2.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/pbkdf2.py new file mode 100644 index 00000000..623e1ca7 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/pbkdf2.py @@ -0,0 +1,64 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import typing + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, + InvalidKey, + UnsupportedAlgorithm, + _Reasons, +) +from cryptography.hazmat.bindings._rust import openssl as rust_openssl +from cryptography.hazmat.primitives import constant_time, hashes +from cryptography.hazmat.primitives.kdf import KeyDerivationFunction + + +class PBKDF2HMAC(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + length: int, + salt: bytes, + iterations: int, + backend: typing.Any = None, + ): + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + if not ossl.pbkdf2_hmac_supported(algorithm): + raise UnsupportedAlgorithm( + "{} is not supported for PBKDF2 by this backend.".format( + algorithm.name + ), + _Reasons.UNSUPPORTED_HASH, + ) + self._used = False + self._algorithm = algorithm + self._length = length + utils._check_bytes("salt", salt) + self._salt = salt + self._iterations = iterations + + def derive(self, key_material: bytes) -> bytes: + if self._used: + raise AlreadyFinalized("PBKDF2 instances can only be used once.") + self._used = True + + return rust_openssl.kdf.derive_pbkdf2_hmac( + key_material, + self._algorithm, + self._salt, + self._iterations, + self._length, + ) + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + derived_key = self.derive(key_material) + if not constant_time.bytes_eq(derived_key, expected_key): + raise InvalidKey("Keys do not match.") diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/scrypt.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/scrypt.py new file mode 100644 index 00000000..05a4f675 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/scrypt.py @@ -0,0 +1,80 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import sys +import typing + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, + InvalidKey, + UnsupportedAlgorithm, +) +from cryptography.hazmat.bindings._rust import openssl as rust_openssl +from cryptography.hazmat.primitives import constant_time +from cryptography.hazmat.primitives.kdf import KeyDerivationFunction + +# This is used by the scrypt tests to skip tests that require more memory +# than the MEM_LIMIT +_MEM_LIMIT = sys.maxsize // 2 + + +class Scrypt(KeyDerivationFunction): + def __init__( + self, + salt: bytes, + length: int, + n: int, + r: int, + p: int, + backend: typing.Any = None, + ): + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + if not ossl.scrypt_supported(): + raise UnsupportedAlgorithm( + "This version of OpenSSL does not support scrypt" + ) + self._length = length + utils._check_bytes("salt", salt) + if n < 2 or (n & (n - 1)) != 0: + raise ValueError("n must be greater than 1 and be a power of 2.") + + if r < 1: + raise ValueError("r must be greater than or equal to 1.") + + if p < 1: + raise ValueError("p must be greater than or equal to 1.") + + self._used = False + self._salt = salt + self._n = n + self._r = r + self._p = p + + def derive(self, key_material: bytes) -> bytes: + if self._used: + raise AlreadyFinalized("Scrypt instances can only be used once.") + self._used = True + + utils._check_byteslike("key_material", key_material) + + return rust_openssl.kdf.derive_scrypt( + key_material, + self._salt, + self._n, + self._r, + self._p, + _MEM_LIMIT, + self._length, + ) + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + derived_key = self.derive(key_material) + if not constant_time.bytes_eq(derived_key, expected_key): + raise InvalidKey("Keys do not match.") diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/x963kdf.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/x963kdf.py new file mode 100644 index 00000000..6e38366a --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/x963kdf.py @@ -0,0 +1,61 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import typing + +from cryptography import utils +from cryptography.exceptions import AlreadyFinalized, InvalidKey +from cryptography.hazmat.primitives import constant_time, hashes +from cryptography.hazmat.primitives.kdf import KeyDerivationFunction + + +def _int_to_u32be(n: int) -> bytes: + return n.to_bytes(length=4, byteorder="big") + + +class X963KDF(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + length: int, + sharedinfo: bytes | None, + backend: typing.Any = None, + ): + max_len = algorithm.digest_size * (2**32 - 1) + if length > max_len: + raise ValueError(f"Cannot derive keys larger than {max_len} bits.") + if sharedinfo is not None: + utils._check_bytes("sharedinfo", sharedinfo) + + self._algorithm = algorithm + self._length = length + self._sharedinfo = sharedinfo + self._used = False + + def derive(self, key_material: bytes) -> bytes: + if self._used: + raise AlreadyFinalized + self._used = True + utils._check_byteslike("key_material", key_material) + output = [b""] + outlen = 0 + counter = 1 + + while self._length > outlen: + h = hashes.Hash(self._algorithm) + h.update(key_material) + h.update(_int_to_u32be(counter)) + if self._sharedinfo is not None: + h.update(self._sharedinfo) + output.append(h.finalize()) + outlen += len(output[-1]) + counter += 1 + + return b"".join(output)[: self._length] + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/keywrap.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/keywrap.py new file mode 100644 index 00000000..3ee152b7 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/keywrap.py @@ -0,0 +1,177 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import typing + +from cryptography.hazmat.primitives.ciphers import Cipher +from cryptography.hazmat.primitives.ciphers.algorithms import AES +from cryptography.hazmat.primitives.ciphers.modes import ECB +from cryptography.hazmat.primitives.constant_time import bytes_eq + + +def _wrap_core( + wrapping_key: bytes, + a: bytes, + r: list[bytes], +) -> bytes: + # RFC 3394 Key Wrap - 2.2.1 (index method) + encryptor = Cipher(AES(wrapping_key), ECB()).encryptor() + n = len(r) + for j in range(6): + for i in range(n): + # every encryption operation is a discrete 16 byte chunk (because + # AES has a 128-bit block size) and since we're using ECB it is + # safe to reuse the encryptor for the entire operation + b = encryptor.update(a + r[i]) + a = ( + int.from_bytes(b[:8], byteorder="big") ^ ((n * j) + i + 1) + ).to_bytes(length=8, byteorder="big") + r[i] = b[-8:] + + assert encryptor.finalize() == b"" + + return a + b"".join(r) + + +def aes_key_wrap( + wrapping_key: bytes, + key_to_wrap: bytes, + backend: typing.Any = None, +) -> bytes: + if len(wrapping_key) not in [16, 24, 32]: + raise ValueError("The wrapping key must be a valid AES key length") + + if len(key_to_wrap) < 16: + raise ValueError("The key to wrap must be at least 16 bytes") + + if len(key_to_wrap) % 8 != 0: + raise ValueError("The key to wrap must be a multiple of 8 bytes") + + a = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6" + r = [key_to_wrap[i : i + 8] for i in range(0, len(key_to_wrap), 8)] + return _wrap_core(wrapping_key, a, r) + + +def _unwrap_core( + wrapping_key: bytes, + a: bytes, + r: list[bytes], +) -> tuple[bytes, list[bytes]]: + # Implement RFC 3394 Key Unwrap - 2.2.2 (index method) + decryptor = Cipher(AES(wrapping_key), ECB()).decryptor() + n = len(r) + for j in reversed(range(6)): + for i in reversed(range(n)): + atr = ( + int.from_bytes(a, byteorder="big") ^ ((n * j) + i + 1) + ).to_bytes(length=8, byteorder="big") + r[i] + # every decryption operation is a discrete 16 byte chunk so + # it is safe to reuse the decryptor for the entire operation + b = decryptor.update(atr) + a = b[:8] + r[i] = b[-8:] + + assert decryptor.finalize() == b"" + return a, r + + +def aes_key_wrap_with_padding( + wrapping_key: bytes, + key_to_wrap: bytes, + backend: typing.Any = None, +) -> bytes: + if len(wrapping_key) not in [16, 24, 32]: + raise ValueError("The wrapping key must be a valid AES key length") + + aiv = b"\xA6\x59\x59\xA6" + len(key_to_wrap).to_bytes( + length=4, byteorder="big" + ) + # pad the key to wrap if necessary + pad = (8 - (len(key_to_wrap) % 8)) % 8 + key_to_wrap = key_to_wrap + b"\x00" * pad + if len(key_to_wrap) == 8: + # RFC 5649 - 4.1 - exactly 8 octets after padding + encryptor = Cipher(AES(wrapping_key), ECB()).encryptor() + b = encryptor.update(aiv + key_to_wrap) + assert encryptor.finalize() == b"" + return b + else: + r = [key_to_wrap[i : i + 8] for i in range(0, len(key_to_wrap), 8)] + return _wrap_core(wrapping_key, aiv, r) + + +def aes_key_unwrap_with_padding( + wrapping_key: bytes, + wrapped_key: bytes, + backend: typing.Any = None, +) -> bytes: + if len(wrapped_key) < 16: + raise InvalidUnwrap("Must be at least 16 bytes") + + if len(wrapping_key) not in [16, 24, 32]: + raise ValueError("The wrapping key must be a valid AES key length") + + if len(wrapped_key) == 16: + # RFC 5649 - 4.2 - exactly two 64-bit blocks + decryptor = Cipher(AES(wrapping_key), ECB()).decryptor() + out = decryptor.update(wrapped_key) + assert decryptor.finalize() == b"" + a = out[:8] + data = out[8:] + n = 1 + else: + r = [wrapped_key[i : i + 8] for i in range(0, len(wrapped_key), 8)] + encrypted_aiv = r.pop(0) + n = len(r) + a, r = _unwrap_core(wrapping_key, encrypted_aiv, r) + data = b"".join(r) + + # 1) Check that MSB(32,A) = A65959A6. + # 2) Check that 8*(n-1) < LSB(32,A) <= 8*n. If so, let + # MLI = LSB(32,A). + # 3) Let b = (8*n)-MLI, and then check that the rightmost b octets of + # the output data are zero. + mli = int.from_bytes(a[4:], byteorder="big") + b = (8 * n) - mli + if ( + not bytes_eq(a[:4], b"\xa6\x59\x59\xa6") + or not 8 * (n - 1) < mli <= 8 * n + or (b != 0 and not bytes_eq(data[-b:], b"\x00" * b)) + ): + raise InvalidUnwrap() + + if b == 0: + return data + else: + return data[:-b] + + +def aes_key_unwrap( + wrapping_key: bytes, + wrapped_key: bytes, + backend: typing.Any = None, +) -> bytes: + if len(wrapped_key) < 24: + raise InvalidUnwrap("Must be at least 24 bytes") + + if len(wrapped_key) % 8 != 0: + raise InvalidUnwrap("The wrapped key must be a multiple of 8 bytes") + + if len(wrapping_key) not in [16, 24, 32]: + raise ValueError("The wrapping key must be a valid AES key length") + + aiv = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6" + r = [wrapped_key[i : i + 8] for i in range(0, len(wrapped_key), 8)] + a = r.pop(0) + a, r = _unwrap_core(wrapping_key, a, r) + if not bytes_eq(a, aiv): + raise InvalidUnwrap() + + return b"".join(r) + + +class InvalidUnwrap(Exception): + pass diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/padding.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/padding.py new file mode 100644 index 00000000..baceaf38 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/padding.py @@ -0,0 +1,225 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc +import typing + +from cryptography import utils +from cryptography.exceptions import AlreadyFinalized +from cryptography.hazmat.bindings._rust import ( + check_ansix923_padding, + check_pkcs7_padding, +) + + +class PaddingContext(metaclass=abc.ABCMeta): + @abc.abstractmethod + def update(self, data: bytes) -> bytes: + """ + Pads the provided bytes and returns any available data as bytes. + """ + + @abc.abstractmethod + def finalize(self) -> bytes: + """ + Finalize the padding, returns bytes. + """ + + +def _byte_padding_check(block_size: int) -> None: + if not (0 <= block_size <= 2040): + raise ValueError("block_size must be in range(0, 2041).") + + if block_size % 8 != 0: + raise ValueError("block_size must be a multiple of 8.") + + +def _byte_padding_update( + buffer_: bytes | None, data: bytes, block_size: int +) -> tuple[bytes, bytes]: + if buffer_ is None: + raise AlreadyFinalized("Context was already finalized.") + + utils._check_byteslike("data", data) + + buffer_ += bytes(data) + + finished_blocks = len(buffer_) // (block_size // 8) + + result = buffer_[: finished_blocks * (block_size // 8)] + buffer_ = buffer_[finished_blocks * (block_size // 8) :] + + return buffer_, result + + +def _byte_padding_pad( + buffer_: bytes | None, + block_size: int, + paddingfn: typing.Callable[[int], bytes], +) -> bytes: + if buffer_ is None: + raise AlreadyFinalized("Context was already finalized.") + + pad_size = block_size // 8 - len(buffer_) + return buffer_ + paddingfn(pad_size) + + +def _byte_unpadding_update( + buffer_: bytes | None, data: bytes, block_size: int +) -> tuple[bytes, bytes]: + if buffer_ is None: + raise AlreadyFinalized("Context was already finalized.") + + utils._check_byteslike("data", data) + + buffer_ += bytes(data) + + finished_blocks = max(len(buffer_) // (block_size // 8) - 1, 0) + + result = buffer_[: finished_blocks * (block_size // 8)] + buffer_ = buffer_[finished_blocks * (block_size // 8) :] + + return buffer_, result + + +def _byte_unpadding_check( + buffer_: bytes | None, + block_size: int, + checkfn: typing.Callable[[bytes], int], +) -> bytes: + if buffer_ is None: + raise AlreadyFinalized("Context was already finalized.") + + if len(buffer_) != block_size // 8: + raise ValueError("Invalid padding bytes.") + + valid = checkfn(buffer_) + + if not valid: + raise ValueError("Invalid padding bytes.") + + pad_size = buffer_[-1] + return buffer_[:-pad_size] + + +class PKCS7: + def __init__(self, block_size: int): + _byte_padding_check(block_size) + self.block_size = block_size + + def padder(self) -> PaddingContext: + return _PKCS7PaddingContext(self.block_size) + + def unpadder(self) -> PaddingContext: + return _PKCS7UnpaddingContext(self.block_size) + + +class _PKCS7PaddingContext(PaddingContext): + _buffer: bytes | None + + def __init__(self, block_size: int): + self.block_size = block_size + # TODO: more copies than necessary, we should use zero-buffer (#193) + self._buffer = b"" + + def update(self, data: bytes) -> bytes: + self._buffer, result = _byte_padding_update( + self._buffer, data, self.block_size + ) + return result + + def _padding(self, size: int) -> bytes: + return bytes([size]) * size + + def finalize(self) -> bytes: + result = _byte_padding_pad( + self._buffer, self.block_size, self._padding + ) + self._buffer = None + return result + + +class _PKCS7UnpaddingContext(PaddingContext): + _buffer: bytes | None + + def __init__(self, block_size: int): + self.block_size = block_size + # TODO: more copies than necessary, we should use zero-buffer (#193) + self._buffer = b"" + + def update(self, data: bytes) -> bytes: + self._buffer, result = _byte_unpadding_update( + self._buffer, data, self.block_size + ) + return result + + def finalize(self) -> bytes: + result = _byte_unpadding_check( + self._buffer, self.block_size, check_pkcs7_padding + ) + self._buffer = None + return result + + +class ANSIX923: + def __init__(self, block_size: int): + _byte_padding_check(block_size) + self.block_size = block_size + + def padder(self) -> PaddingContext: + return _ANSIX923PaddingContext(self.block_size) + + def unpadder(self) -> PaddingContext: + return _ANSIX923UnpaddingContext(self.block_size) + + +class _ANSIX923PaddingContext(PaddingContext): + _buffer: bytes | None + + def __init__(self, block_size: int): + self.block_size = block_size + # TODO: more copies than necessary, we should use zero-buffer (#193) + self._buffer = b"" + + def update(self, data: bytes) -> bytes: + self._buffer, result = _byte_padding_update( + self._buffer, data, self.block_size + ) + return result + + def _padding(self, size: int) -> bytes: + return bytes([0]) * (size - 1) + bytes([size]) + + def finalize(self) -> bytes: + result = _byte_padding_pad( + self._buffer, self.block_size, self._padding + ) + self._buffer = None + return result + + +class _ANSIX923UnpaddingContext(PaddingContext): + _buffer: bytes | None + + def __init__(self, block_size: int): + self.block_size = block_size + # TODO: more copies than necessary, we should use zero-buffer (#193) + self._buffer = b"" + + def update(self, data: bytes) -> bytes: + self._buffer, result = _byte_unpadding_update( + self._buffer, data, self.block_size + ) + return result + + def finalize(self) -> bytes: + result = _byte_unpadding_check( + self._buffer, + self.block_size, + check_ansix923_padding, + ) + self._buffer = None + return result diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/poly1305.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/poly1305.py new file mode 100644 index 00000000..7f5a77a5 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/poly1305.py @@ -0,0 +1,11 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +from cryptography.hazmat.bindings._rust import openssl as rust_openssl + +__all__ = ["Poly1305"] + +Poly1305 = rust_openssl.poly1305.Poly1305 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__init__.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__init__.py new file mode 100644 index 00000000..b6c9a5cd --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__init__.py @@ -0,0 +1,63 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +from cryptography.hazmat.primitives._serialization import ( + BestAvailableEncryption, + Encoding, + KeySerializationEncryption, + NoEncryption, + ParameterFormat, + PrivateFormat, + PublicFormat, + _KeySerializationEncryption, +) +from cryptography.hazmat.primitives.serialization.base import ( + load_der_parameters, + load_der_private_key, + load_der_public_key, + load_pem_parameters, + load_pem_private_key, + load_pem_public_key, +) +from cryptography.hazmat.primitives.serialization.ssh import ( + SSHCertificate, + SSHCertificateBuilder, + SSHCertificateType, + SSHCertPrivateKeyTypes, + SSHCertPublicKeyTypes, + SSHPrivateKeyTypes, + SSHPublicKeyTypes, + load_ssh_private_key, + load_ssh_public_identity, + load_ssh_public_key, +) + +__all__ = [ + "load_der_parameters", + "load_der_private_key", + "load_der_public_key", + "load_pem_parameters", + "load_pem_private_key", + "load_pem_public_key", + "load_ssh_private_key", + "load_ssh_public_identity", + "load_ssh_public_key", + "Encoding", + "PrivateFormat", + "PublicFormat", + "ParameterFormat", + "KeySerializationEncryption", + "BestAvailableEncryption", + "NoEncryption", + "_KeySerializationEncryption", + "SSHCertificateBuilder", + "SSHCertificate", + "SSHCertificateType", + "SSHCertPublicKeyTypes", + "SSHCertPrivateKeyTypes", + "SSHPrivateKeyTypes", + "SSHPublicKeyTypes", +] diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..100e8090267056e92b0d7a769f6fa98d6ea3ab7c GIT binary patch literal 1629 zcmchWyKWOf6oz->``wQ3cAy9}E@DHA5E9`Q2^2**G$Tu+v3KH(va@T=t}Qtg&p<;@ zgLnYmgL+yjI!oz7!<<>$StkO71gz~(GiT47`OmN8kGWjhP|x=lpXoGi7++ztdbWav zdGSsy-W!%-nYO`AWSX$vvbT5yMR*iNc?`vP9L0G8C3q4gc?zX?8l`n!#Ln<6%JLk_ z@jS}&0xIw#D)JI4>Gx54o0n0US5SplQI*$Fjn`3~H&BB&QIoe&i?>mm@1Pyi7#mjX zgNbfg@xIYXd;@_UQ)Yv)}{tnX9Le>@}1CPSM(b4Fr5fp;>g)~>~zv24Ah z^F9@f*z8=N3uR>w-O#RZL2jMrnhtF?TJGBT=Y>0QS+-qb zVT%epSylC9_zLS>ue*fSJ6+Sy*Bh`egZtnM| z%vSQ`_Gb8aKB2OLk|ry;Ux5=0J=2NVEBKnc(Uv;b{D43GlA@QWls4Zk6xfCL}|CQ4p5SVUAz?&*PZ$AU~w=iO6suEwUTy5r1eGwOA*7oNP}QY}eq z(AR58R|-Lmy#JfB8&$hQqV~UZMc(_Pg39v13+;+FM0=rKSsQZAYMH>8*fz$Wj0@F+ zap^yOFbMvGgE#KU@c|i~d4t!KQ$D1EdL!zL=%72J&TR0C4F?|c>E1*okumiKVZFV; z*WQ({y$u6;7&C|Y7^;3IaG$3FlaM$$|G literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/base.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/base.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e8c94182c3fd404be8059153148024fec729bd80 GIT binary patch literal 712 zcmY+AzfZzI6vyuh3Ze`K0y_@MV43|n8F4TU{#Zzp=Gs2sug#`W%6L%NmAK?GN z(1CO!adIPJ)5U9{*uGq^-}kw1-}Sxsa=CVh<$gNM&AfKpCKEt;*d@IAZH+(z83maaLyqIKzokVp?8NR#WdzSKmnz`=?G;vs9 z9=Jl-cg=FxF!|W?S&tL1KUVu>;t*dosB2NTCsdseh0mi_!o5i9>o3FnGmJ%8wHdK= z4;tmk9T#dnJns0dt%+k8)7~S?H(L(4B#M4a81zE5x67mmKvI%J{)_}M0y~! z^t4*5X|-hU4)y5>L`wjt#HJJCQ|7h|B0%-VKgDy0SwkBxc}4yJmXGMlZIQzmFG>iv x@f2OB*SvlZ)Q^Jt#S~R%DLt<>g4$tFJDZ})ETtuXVL|O=g%c?=x%j@k>JK(w(31cF literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/pkcs12.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/pkcs12.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..93d099c348ae42820b530932b92e7d90728ec9f2 GIT binary patch literal 9851 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 H%)$QwSX4Vg literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/ssh.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/ssh.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3eaae811cb88ef1c701fb3f25e0647ccdba9d3f7 GIT binary patch literal 68621 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 TyD-?xJ?<^rFO>Yj!UO&XVc^6Q literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/base.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/base.py new file mode 100644 index 00000000..e7c998b7 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/base.py @@ -0,0 +1,14 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from cryptography.hazmat.bindings._rust import openssl as rust_openssl + +load_pem_private_key = rust_openssl.keys.load_pem_private_key +load_der_private_key = rust_openssl.keys.load_der_private_key + +load_pem_public_key = rust_openssl.keys.load_pem_public_key +load_der_public_key = rust_openssl.keys.load_der_public_key + +load_pem_parameters = rust_openssl.dh.from_pem_parameters +load_der_parameters = rust_openssl.dh.from_der_parameters diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/pkcs12.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/pkcs12.py new file mode 100644 index 00000000..006a248b --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/pkcs12.py @@ -0,0 +1,229 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import typing + +from cryptography import x509 +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives._serialization import PBES as PBES +from cryptography.hazmat.primitives.asymmetric import ( + dsa, + ec, + ed448, + ed25519, + rsa, +) +from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes + +__all__ = [ + "PBES", + "PKCS12PrivateKeyTypes", + "PKCS12Certificate", + "PKCS12KeyAndCertificates", + "load_key_and_certificates", + "load_pkcs12", + "serialize_key_and_certificates", +] + +PKCS12PrivateKeyTypes = typing.Union[ + rsa.RSAPrivateKey, + dsa.DSAPrivateKey, + ec.EllipticCurvePrivateKey, + ed25519.Ed25519PrivateKey, + ed448.Ed448PrivateKey, +] + + +class PKCS12Certificate: + def __init__( + self, + cert: x509.Certificate, + friendly_name: bytes | None, + ): + if not isinstance(cert, x509.Certificate): + raise TypeError("Expecting x509.Certificate object") + if friendly_name is not None and not isinstance(friendly_name, bytes): + raise TypeError("friendly_name must be bytes or None") + self._cert = cert + self._friendly_name = friendly_name + + @property + def friendly_name(self) -> bytes | None: + return self._friendly_name + + @property + def certificate(self) -> x509.Certificate: + return self._cert + + def __eq__(self, other: object) -> bool: + if not isinstance(other, PKCS12Certificate): + return NotImplemented + + return ( + self.certificate == other.certificate + and self.friendly_name == other.friendly_name + ) + + def __hash__(self) -> int: + return hash((self.certificate, self.friendly_name)) + + def __repr__(self) -> str: + return "".format( + self.certificate, self.friendly_name + ) + + +class PKCS12KeyAndCertificates: + def __init__( + self, + key: PrivateKeyTypes | None, + cert: PKCS12Certificate | None, + additional_certs: list[PKCS12Certificate], + ): + if key is not None and not isinstance( + key, + ( + rsa.RSAPrivateKey, + dsa.DSAPrivateKey, + ec.EllipticCurvePrivateKey, + ed25519.Ed25519PrivateKey, + ed448.Ed448PrivateKey, + ), + ): + raise TypeError( + "Key must be RSA, DSA, EllipticCurve, ED25519, or ED448" + " private key, or None." + ) + if cert is not None and not isinstance(cert, PKCS12Certificate): + raise TypeError("cert must be a PKCS12Certificate object or None") + if not all( + isinstance(add_cert, PKCS12Certificate) + for add_cert in additional_certs + ): + raise TypeError( + "all values in additional_certs must be PKCS12Certificate" + " objects" + ) + self._key = key + self._cert = cert + self._additional_certs = additional_certs + + @property + def key(self) -> PrivateKeyTypes | None: + return self._key + + @property + def cert(self) -> PKCS12Certificate | None: + return self._cert + + @property + def additional_certs(self) -> list[PKCS12Certificate]: + return self._additional_certs + + def __eq__(self, other: object) -> bool: + if not isinstance(other, PKCS12KeyAndCertificates): + return NotImplemented + + return ( + self.key == other.key + and self.cert == other.cert + and self.additional_certs == other.additional_certs + ) + + def __hash__(self) -> int: + return hash((self.key, self.cert, tuple(self.additional_certs))) + + def __repr__(self) -> str: + fmt = ( + "" + ) + return fmt.format(self.key, self.cert, self.additional_certs) + + +def load_key_and_certificates( + data: bytes, + password: bytes | None, + backend: typing.Any = None, +) -> tuple[ + PrivateKeyTypes | None, + x509.Certificate | None, + list[x509.Certificate], +]: + from cryptography.hazmat.backends.openssl.backend import backend as ossl + + return ossl.load_key_and_certificates_from_pkcs12(data, password) + + +def load_pkcs12( + data: bytes, + password: bytes | None, + backend: typing.Any = None, +) -> PKCS12KeyAndCertificates: + from cryptography.hazmat.backends.openssl.backend import backend as ossl + + return ossl.load_pkcs12(data, password) + + +_PKCS12CATypes = typing.Union[ + x509.Certificate, + PKCS12Certificate, +] + + +def serialize_key_and_certificates( + name: bytes | None, + key: PKCS12PrivateKeyTypes | None, + cert: x509.Certificate | None, + cas: typing.Iterable[_PKCS12CATypes] | None, + encryption_algorithm: serialization.KeySerializationEncryption, +) -> bytes: + if key is not None and not isinstance( + key, + ( + rsa.RSAPrivateKey, + dsa.DSAPrivateKey, + ec.EllipticCurvePrivateKey, + ed25519.Ed25519PrivateKey, + ed448.Ed448PrivateKey, + ), + ): + raise TypeError( + "Key must be RSA, DSA, EllipticCurve, ED25519, or ED448" + " private key, or None." + ) + if cert is not None and not isinstance(cert, x509.Certificate): + raise TypeError("cert must be a certificate or None") + + if cas is not None: + cas = list(cas) + if not all( + isinstance( + val, + ( + x509.Certificate, + PKCS12Certificate, + ), + ) + for val in cas + ): + raise TypeError("all values in cas must be certificates") + + if not isinstance( + encryption_algorithm, serialization.KeySerializationEncryption + ): + raise TypeError( + "Key encryption algorithm must be a " + "KeySerializationEncryption instance" + ) + + if key is None and cert is None and not cas: + raise ValueError("You must supply at least one of key, cert, or cas") + + from cryptography.hazmat.backends.openssl.backend import backend + + return backend.serialize_key_and_certificates_to_pkcs12( + name, key, cert, cas, encryption_algorithm + ) diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/pkcs7.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/pkcs7.py new file mode 100644 index 00000000..bae35c5f --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/pkcs7.py @@ -0,0 +1,233 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import email.base64mime +import email.generator +import email.message +import email.policy +import io +import typing + +from cryptography import utils, x509 +from cryptography.hazmat.bindings._rust import pkcs7 as rust_pkcs7 +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import ec, padding, rsa +from cryptography.utils import _check_byteslike + +load_pem_pkcs7_certificates = rust_pkcs7.load_pem_pkcs7_certificates + +load_der_pkcs7_certificates = rust_pkcs7.load_der_pkcs7_certificates + +serialize_certificates = rust_pkcs7.serialize_certificates + +PKCS7HashTypes = typing.Union[ + hashes.SHA224, + hashes.SHA256, + hashes.SHA384, + hashes.SHA512, +] + +PKCS7PrivateKeyTypes = typing.Union[ + rsa.RSAPrivateKey, ec.EllipticCurvePrivateKey +] + + +class PKCS7Options(utils.Enum): + Text = "Add text/plain MIME type" + Binary = "Don't translate input data into canonical MIME format" + DetachedSignature = "Don't embed data in the PKCS7 structure" + NoCapabilities = "Don't embed SMIME capabilities" + NoAttributes = "Don't embed authenticatedAttributes" + NoCerts = "Don't embed signer certificate" + + +class PKCS7SignatureBuilder: + def __init__( + self, + data: bytes | None = None, + signers: list[ + tuple[ + x509.Certificate, + PKCS7PrivateKeyTypes, + PKCS7HashTypes, + padding.PSS | padding.PKCS1v15 | None, + ] + ] = [], + additional_certs: list[x509.Certificate] = [], + ): + self._data = data + self._signers = signers + self._additional_certs = additional_certs + + def set_data(self, data: bytes) -> PKCS7SignatureBuilder: + _check_byteslike("data", data) + if self._data is not None: + raise ValueError("data may only be set once") + + return PKCS7SignatureBuilder(data, self._signers) + + def add_signer( + self, + certificate: x509.Certificate, + private_key: PKCS7PrivateKeyTypes, + hash_algorithm: PKCS7HashTypes, + *, + rsa_padding: padding.PSS | padding.PKCS1v15 | None = None, + ) -> PKCS7SignatureBuilder: + if not isinstance( + hash_algorithm, + ( + hashes.SHA224, + hashes.SHA256, + hashes.SHA384, + hashes.SHA512, + ), + ): + raise TypeError( + "hash_algorithm must be one of hashes.SHA224, " + "SHA256, SHA384, or SHA512" + ) + if not isinstance(certificate, x509.Certificate): + raise TypeError("certificate must be a x509.Certificate") + + if not isinstance( + private_key, (rsa.RSAPrivateKey, ec.EllipticCurvePrivateKey) + ): + raise TypeError("Only RSA & EC keys are supported at this time.") + + if rsa_padding is not None: + if not isinstance(rsa_padding, (padding.PSS, padding.PKCS1v15)): + raise TypeError("Padding must be PSS or PKCS1v15") + if not isinstance(private_key, rsa.RSAPrivateKey): + raise TypeError("Padding is only supported for RSA keys") + + return PKCS7SignatureBuilder( + self._data, + [ + *self._signers, + (certificate, private_key, hash_algorithm, rsa_padding), + ], + ) + + def add_certificate( + self, certificate: x509.Certificate + ) -> PKCS7SignatureBuilder: + if not isinstance(certificate, x509.Certificate): + raise TypeError("certificate must be a x509.Certificate") + + return PKCS7SignatureBuilder( + self._data, self._signers, [*self._additional_certs, certificate] + ) + + def sign( + self, + encoding: serialization.Encoding, + options: typing.Iterable[PKCS7Options], + backend: typing.Any = None, + ) -> bytes: + if len(self._signers) == 0: + raise ValueError("Must have at least one signer") + if self._data is None: + raise ValueError("You must add data to sign") + options = list(options) + if not all(isinstance(x, PKCS7Options) for x in options): + raise ValueError("options must be from the PKCS7Options enum") + if encoding not in ( + serialization.Encoding.PEM, + serialization.Encoding.DER, + serialization.Encoding.SMIME, + ): + raise ValueError( + "Must be PEM, DER, or SMIME from the Encoding enum" + ) + + # Text is a meaningless option unless it is accompanied by + # DetachedSignature + if ( + PKCS7Options.Text in options + and PKCS7Options.DetachedSignature not in options + ): + raise ValueError( + "When passing the Text option you must also pass " + "DetachedSignature" + ) + + if PKCS7Options.Text in options and encoding in ( + serialization.Encoding.DER, + serialization.Encoding.PEM, + ): + raise ValueError( + "The Text option is only available for SMIME serialization" + ) + + # No attributes implies no capabilities so we'll error if you try to + # pass both. + if ( + PKCS7Options.NoAttributes in options + and PKCS7Options.NoCapabilities in options + ): + raise ValueError( + "NoAttributes is a superset of NoCapabilities. Do not pass " + "both values." + ) + + return rust_pkcs7.sign_and_serialize(self, encoding, options) + + +def _smime_encode( + data: bytes, signature: bytes, micalg: str, text_mode: bool +) -> bytes: + # This function works pretty hard to replicate what OpenSSL does + # precisely. For good and for ill. + + m = email.message.Message() + m.add_header("MIME-Version", "1.0") + m.add_header( + "Content-Type", + "multipart/signed", + protocol="application/x-pkcs7-signature", + micalg=micalg, + ) + + m.preamble = "This is an S/MIME signed message\n" + + msg_part = OpenSSLMimePart() + msg_part.set_payload(data) + if text_mode: + msg_part.add_header("Content-Type", "text/plain") + m.attach(msg_part) + + sig_part = email.message.MIMEPart() + sig_part.add_header( + "Content-Type", "application/x-pkcs7-signature", name="smime.p7s" + ) + sig_part.add_header("Content-Transfer-Encoding", "base64") + sig_part.add_header( + "Content-Disposition", "attachment", filename="smime.p7s" + ) + sig_part.set_payload( + email.base64mime.body_encode(signature, maxlinelen=65) + ) + del sig_part["MIME-Version"] + m.attach(sig_part) + + fp = io.BytesIO() + g = email.generator.BytesGenerator( + fp, + maxheaderlen=0, + mangle_from_=False, + policy=m.policy.clone(linesep="\r\n"), + ) + g.flatten(m) + return fp.getvalue() + + +class OpenSSLMimePart(email.message.MIMEPart): + # A MIMEPart subclass that replicates OpenSSL's behavior of not including + # a newline if there are no headers. + def _write_headers(self, generator) -> None: + if list(self.raw_items()): + generator._write_headers(self) diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/ssh.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/ssh.py new file mode 100644 index 00000000..f33edd55 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/ssh.py @@ -0,0 +1,1507 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import binascii +import enum +import os +import re +import typing +import warnings +from base64 import encodebytes as _base64_encode +from dataclasses import dataclass + +from cryptography import utils +from cryptography.exceptions import UnsupportedAlgorithm +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric import ( + dsa, + ec, + ed25519, + padding, + rsa, +) +from cryptography.hazmat.primitives.asymmetric import utils as asym_utils +from cryptography.hazmat.primitives.ciphers import ( + AEADDecryptionContext, + Cipher, + algorithms, + modes, +) +from cryptography.hazmat.primitives.serialization import ( + Encoding, + KeySerializationEncryption, + NoEncryption, + PrivateFormat, + PublicFormat, + _KeySerializationEncryption, +) + +try: + from bcrypt import kdf as _bcrypt_kdf + + _bcrypt_supported = True +except ImportError: + _bcrypt_supported = False + + def _bcrypt_kdf( + password: bytes, + salt: bytes, + desired_key_bytes: int, + rounds: int, + ignore_few_rounds: bool = False, + ) -> bytes: + raise UnsupportedAlgorithm("Need bcrypt module") + + +_SSH_ED25519 = b"ssh-ed25519" +_SSH_RSA = b"ssh-rsa" +_SSH_DSA = b"ssh-dss" +_ECDSA_NISTP256 = b"ecdsa-sha2-nistp256" +_ECDSA_NISTP384 = b"ecdsa-sha2-nistp384" +_ECDSA_NISTP521 = b"ecdsa-sha2-nistp521" +_CERT_SUFFIX = b"-cert-v01@openssh.com" + +# These are not key types, only algorithms, so they cannot appear +# as a public key type +_SSH_RSA_SHA256 = b"rsa-sha2-256" +_SSH_RSA_SHA512 = b"rsa-sha2-512" + +_SSH_PUBKEY_RC = re.compile(rb"\A(\S+)[ \t]+(\S+)") +_SK_MAGIC = b"openssh-key-v1\0" +_SK_START = b"-----BEGIN OPENSSH PRIVATE KEY-----" +_SK_END = b"-----END OPENSSH PRIVATE KEY-----" +_BCRYPT = b"bcrypt" +_NONE = b"none" +_DEFAULT_CIPHER = b"aes256-ctr" +_DEFAULT_ROUNDS = 16 + +# re is only way to work on bytes-like data +_PEM_RC = re.compile(_SK_START + b"(.*?)" + _SK_END, re.DOTALL) + +# padding for max blocksize +_PADDING = memoryview(bytearray(range(1, 1 + 16))) + + +@dataclass +class _SSHCipher: + alg: type[algorithms.AES] + key_len: int + mode: type[modes.CTR] | type[modes.CBC] | type[modes.GCM] + block_len: int + iv_len: int + tag_len: int | None + is_aead: bool + + +# ciphers that are actually used in key wrapping +_SSH_CIPHERS: dict[bytes, _SSHCipher] = { + b"aes256-ctr": _SSHCipher( + alg=algorithms.AES, + key_len=32, + mode=modes.CTR, + block_len=16, + iv_len=16, + tag_len=None, + is_aead=False, + ), + b"aes256-cbc": _SSHCipher( + alg=algorithms.AES, + key_len=32, + mode=modes.CBC, + block_len=16, + iv_len=16, + tag_len=None, + is_aead=False, + ), + b"aes256-gcm@openssh.com": _SSHCipher( + alg=algorithms.AES, + key_len=32, + mode=modes.GCM, + block_len=16, + iv_len=12, + tag_len=16, + is_aead=True, + ), +} + +# map local curve name to key type +_ECDSA_KEY_TYPE = { + "secp256r1": _ECDSA_NISTP256, + "secp384r1": _ECDSA_NISTP384, + "secp521r1": _ECDSA_NISTP521, +} + + +def _get_ssh_key_type(key: SSHPrivateKeyTypes | SSHPublicKeyTypes) -> bytes: + if isinstance(key, ec.EllipticCurvePrivateKey): + key_type = _ecdsa_key_type(key.public_key()) + elif isinstance(key, ec.EllipticCurvePublicKey): + key_type = _ecdsa_key_type(key) + elif isinstance(key, (rsa.RSAPrivateKey, rsa.RSAPublicKey)): + key_type = _SSH_RSA + elif isinstance(key, (dsa.DSAPrivateKey, dsa.DSAPublicKey)): + key_type = _SSH_DSA + elif isinstance( + key, (ed25519.Ed25519PrivateKey, ed25519.Ed25519PublicKey) + ): + key_type = _SSH_ED25519 + else: + raise ValueError("Unsupported key type") + + return key_type + + +def _ecdsa_key_type(public_key: ec.EllipticCurvePublicKey) -> bytes: + """Return SSH key_type and curve_name for private key.""" + curve = public_key.curve + if curve.name not in _ECDSA_KEY_TYPE: + raise ValueError( + f"Unsupported curve for ssh private key: {curve.name!r}" + ) + return _ECDSA_KEY_TYPE[curve.name] + + +def _ssh_pem_encode( + data: bytes, + prefix: bytes = _SK_START + b"\n", + suffix: bytes = _SK_END + b"\n", +) -> bytes: + return b"".join([prefix, _base64_encode(data), suffix]) + + +def _check_block_size(data: bytes, block_len: int) -> None: + """Require data to be full blocks""" + if not data or len(data) % block_len != 0: + raise ValueError("Corrupt data: missing padding") + + +def _check_empty(data: bytes) -> None: + """All data should have been parsed.""" + if data: + raise ValueError("Corrupt data: unparsed data") + + +def _init_cipher( + ciphername: bytes, + password: bytes | None, + salt: bytes, + rounds: int, +) -> Cipher[modes.CBC | modes.CTR | modes.GCM]: + """Generate key + iv and return cipher.""" + if not password: + raise ValueError("Key is password-protected.") + + ciph = _SSH_CIPHERS[ciphername] + seed = _bcrypt_kdf( + password, salt, ciph.key_len + ciph.iv_len, rounds, True + ) + return Cipher( + ciph.alg(seed[: ciph.key_len]), + ciph.mode(seed[ciph.key_len :]), + ) + + +def _get_u32(data: memoryview) -> tuple[int, memoryview]: + """Uint32""" + if len(data) < 4: + raise ValueError("Invalid data") + return int.from_bytes(data[:4], byteorder="big"), data[4:] + + +def _get_u64(data: memoryview) -> tuple[int, memoryview]: + """Uint64""" + if len(data) < 8: + raise ValueError("Invalid data") + return int.from_bytes(data[:8], byteorder="big"), data[8:] + + +def _get_sshstr(data: memoryview) -> tuple[memoryview, memoryview]: + """Bytes with u32 length prefix""" + n, data = _get_u32(data) + if n > len(data): + raise ValueError("Invalid data") + return data[:n], data[n:] + + +def _get_mpint(data: memoryview) -> tuple[int, memoryview]: + """Big integer.""" + val, data = _get_sshstr(data) + if val and val[0] > 0x7F: + raise ValueError("Invalid data") + return int.from_bytes(val, "big"), data + + +def _to_mpint(val: int) -> bytes: + """Storage format for signed bigint.""" + if val < 0: + raise ValueError("negative mpint not allowed") + if not val: + return b"" + nbytes = (val.bit_length() + 8) // 8 + return utils.int_to_bytes(val, nbytes) + + +class _FragList: + """Build recursive structure without data copy.""" + + flist: list[bytes] + + def __init__(self, init: list[bytes] | None = None) -> None: + self.flist = [] + if init: + self.flist.extend(init) + + def put_raw(self, val: bytes) -> None: + """Add plain bytes""" + self.flist.append(val) + + def put_u32(self, val: int) -> None: + """Big-endian uint32""" + self.flist.append(val.to_bytes(length=4, byteorder="big")) + + def put_u64(self, val: int) -> None: + """Big-endian uint64""" + self.flist.append(val.to_bytes(length=8, byteorder="big")) + + def put_sshstr(self, val: bytes | _FragList) -> None: + """Bytes prefixed with u32 length""" + if isinstance(val, (bytes, memoryview, bytearray)): + self.put_u32(len(val)) + self.flist.append(val) + else: + self.put_u32(val.size()) + self.flist.extend(val.flist) + + def put_mpint(self, val: int) -> None: + """Big-endian bigint prefixed with u32 length""" + self.put_sshstr(_to_mpint(val)) + + def size(self) -> int: + """Current number of bytes""" + return sum(map(len, self.flist)) + + def render(self, dstbuf: memoryview, pos: int = 0) -> int: + """Write into bytearray""" + for frag in self.flist: + flen = len(frag) + start, pos = pos, pos + flen + dstbuf[start:pos] = frag + return pos + + def tobytes(self) -> bytes: + """Return as bytes""" + buf = memoryview(bytearray(self.size())) + self.render(buf) + return buf.tobytes() + + +class _SSHFormatRSA: + """Format for RSA keys. + + Public: + mpint e, n + Private: + mpint n, e, d, iqmp, p, q + """ + + def get_public(self, data: memoryview): + """RSA public fields""" + e, data = _get_mpint(data) + n, data = _get_mpint(data) + return (e, n), data + + def load_public( + self, data: memoryview + ) -> tuple[rsa.RSAPublicKey, memoryview]: + """Make RSA public key from data.""" + (e, n), data = self.get_public(data) + public_numbers = rsa.RSAPublicNumbers(e, n) + public_key = public_numbers.public_key() + return public_key, data + + def load_private( + self, data: memoryview, pubfields + ) -> tuple[rsa.RSAPrivateKey, memoryview]: + """Make RSA private key from data.""" + n, data = _get_mpint(data) + e, data = _get_mpint(data) + d, data = _get_mpint(data) + iqmp, data = _get_mpint(data) + p, data = _get_mpint(data) + q, data = _get_mpint(data) + + if (e, n) != pubfields: + raise ValueError("Corrupt data: rsa field mismatch") + dmp1 = rsa.rsa_crt_dmp1(d, p) + dmq1 = rsa.rsa_crt_dmq1(d, q) + public_numbers = rsa.RSAPublicNumbers(e, n) + private_numbers = rsa.RSAPrivateNumbers( + p, q, d, dmp1, dmq1, iqmp, public_numbers + ) + private_key = private_numbers.private_key() + return private_key, data + + def encode_public( + self, public_key: rsa.RSAPublicKey, f_pub: _FragList + ) -> None: + """Write RSA public key""" + pubn = public_key.public_numbers() + f_pub.put_mpint(pubn.e) + f_pub.put_mpint(pubn.n) + + def encode_private( + self, private_key: rsa.RSAPrivateKey, f_priv: _FragList + ) -> None: + """Write RSA private key""" + private_numbers = private_key.private_numbers() + public_numbers = private_numbers.public_numbers + + f_priv.put_mpint(public_numbers.n) + f_priv.put_mpint(public_numbers.e) + + f_priv.put_mpint(private_numbers.d) + f_priv.put_mpint(private_numbers.iqmp) + f_priv.put_mpint(private_numbers.p) + f_priv.put_mpint(private_numbers.q) + + +class _SSHFormatDSA: + """Format for DSA keys. + + Public: + mpint p, q, g, y + Private: + mpint p, q, g, y, x + """ + + def get_public(self, data: memoryview) -> tuple[tuple, memoryview]: + """DSA public fields""" + p, data = _get_mpint(data) + q, data = _get_mpint(data) + g, data = _get_mpint(data) + y, data = _get_mpint(data) + return (p, q, g, y), data + + def load_public( + self, data: memoryview + ) -> tuple[dsa.DSAPublicKey, memoryview]: + """Make DSA public key from data.""" + (p, q, g, y), data = self.get_public(data) + parameter_numbers = dsa.DSAParameterNumbers(p, q, g) + public_numbers = dsa.DSAPublicNumbers(y, parameter_numbers) + self._validate(public_numbers) + public_key = public_numbers.public_key() + return public_key, data + + def load_private( + self, data: memoryview, pubfields + ) -> tuple[dsa.DSAPrivateKey, memoryview]: + """Make DSA private key from data.""" + (p, q, g, y), data = self.get_public(data) + x, data = _get_mpint(data) + + if (p, q, g, y) != pubfields: + raise ValueError("Corrupt data: dsa field mismatch") + parameter_numbers = dsa.DSAParameterNumbers(p, q, g) + public_numbers = dsa.DSAPublicNumbers(y, parameter_numbers) + self._validate(public_numbers) + private_numbers = dsa.DSAPrivateNumbers(x, public_numbers) + private_key = private_numbers.private_key() + return private_key, data + + def encode_public( + self, public_key: dsa.DSAPublicKey, f_pub: _FragList + ) -> None: + """Write DSA public key""" + public_numbers = public_key.public_numbers() + parameter_numbers = public_numbers.parameter_numbers + self._validate(public_numbers) + + f_pub.put_mpint(parameter_numbers.p) + f_pub.put_mpint(parameter_numbers.q) + f_pub.put_mpint(parameter_numbers.g) + f_pub.put_mpint(public_numbers.y) + + def encode_private( + self, private_key: dsa.DSAPrivateKey, f_priv: _FragList + ) -> None: + """Write DSA private key""" + self.encode_public(private_key.public_key(), f_priv) + f_priv.put_mpint(private_key.private_numbers().x) + + def _validate(self, public_numbers: dsa.DSAPublicNumbers) -> None: + parameter_numbers = public_numbers.parameter_numbers + if parameter_numbers.p.bit_length() != 1024: + raise ValueError("SSH supports only 1024 bit DSA keys") + + +class _SSHFormatECDSA: + """Format for ECDSA keys. + + Public: + str curve + bytes point + Private: + str curve + bytes point + mpint secret + """ + + def __init__(self, ssh_curve_name: bytes, curve: ec.EllipticCurve): + self.ssh_curve_name = ssh_curve_name + self.curve = curve + + def get_public(self, data: memoryview) -> tuple[tuple, memoryview]: + """ECDSA public fields""" + curve, data = _get_sshstr(data) + point, data = _get_sshstr(data) + if curve != self.ssh_curve_name: + raise ValueError("Curve name mismatch") + if point[0] != 4: + raise NotImplementedError("Need uncompressed point") + return (curve, point), data + + def load_public( + self, data: memoryview + ) -> tuple[ec.EllipticCurvePublicKey, memoryview]: + """Make ECDSA public key from data.""" + (_, point), data = self.get_public(data) + public_key = ec.EllipticCurvePublicKey.from_encoded_point( + self.curve, point.tobytes() + ) + return public_key, data + + def load_private( + self, data: memoryview, pubfields + ) -> tuple[ec.EllipticCurvePrivateKey, memoryview]: + """Make ECDSA private key from data.""" + (curve_name, point), data = self.get_public(data) + secret, data = _get_mpint(data) + + if (curve_name, point) != pubfields: + raise ValueError("Corrupt data: ecdsa field mismatch") + private_key = ec.derive_private_key(secret, self.curve) + return private_key, data + + def encode_public( + self, public_key: ec.EllipticCurvePublicKey, f_pub: _FragList + ) -> None: + """Write ECDSA public key""" + point = public_key.public_bytes( + Encoding.X962, PublicFormat.UncompressedPoint + ) + f_pub.put_sshstr(self.ssh_curve_name) + f_pub.put_sshstr(point) + + def encode_private( + self, private_key: ec.EllipticCurvePrivateKey, f_priv: _FragList + ) -> None: + """Write ECDSA private key""" + public_key = private_key.public_key() + private_numbers = private_key.private_numbers() + + self.encode_public(public_key, f_priv) + f_priv.put_mpint(private_numbers.private_value) + + +class _SSHFormatEd25519: + """Format for Ed25519 keys. + + Public: + bytes point + Private: + bytes point + bytes secret_and_point + """ + + def get_public(self, data: memoryview) -> tuple[tuple, memoryview]: + """Ed25519 public fields""" + point, data = _get_sshstr(data) + return (point,), data + + def load_public( + self, data: memoryview + ) -> tuple[ed25519.Ed25519PublicKey, memoryview]: + """Make Ed25519 public key from data.""" + (point,), data = self.get_public(data) + public_key = ed25519.Ed25519PublicKey.from_public_bytes( + point.tobytes() + ) + return public_key, data + + def load_private( + self, data: memoryview, pubfields + ) -> tuple[ed25519.Ed25519PrivateKey, memoryview]: + """Make Ed25519 private key from data.""" + (point,), data = self.get_public(data) + keypair, data = _get_sshstr(data) + + secret = keypair[:32] + point2 = keypair[32:] + if point != point2 or (point,) != pubfields: + raise ValueError("Corrupt data: ed25519 field mismatch") + private_key = ed25519.Ed25519PrivateKey.from_private_bytes(secret) + return private_key, data + + def encode_public( + self, public_key: ed25519.Ed25519PublicKey, f_pub: _FragList + ) -> None: + """Write Ed25519 public key""" + raw_public_key = public_key.public_bytes( + Encoding.Raw, PublicFormat.Raw + ) + f_pub.put_sshstr(raw_public_key) + + def encode_private( + self, private_key: ed25519.Ed25519PrivateKey, f_priv: _FragList + ) -> None: + """Write Ed25519 private key""" + public_key = private_key.public_key() + raw_private_key = private_key.private_bytes( + Encoding.Raw, PrivateFormat.Raw, NoEncryption() + ) + raw_public_key = public_key.public_bytes( + Encoding.Raw, PublicFormat.Raw + ) + f_keypair = _FragList([raw_private_key, raw_public_key]) + + self.encode_public(public_key, f_priv) + f_priv.put_sshstr(f_keypair) + + +_KEY_FORMATS = { + _SSH_RSA: _SSHFormatRSA(), + _SSH_DSA: _SSHFormatDSA(), + _SSH_ED25519: _SSHFormatEd25519(), + _ECDSA_NISTP256: _SSHFormatECDSA(b"nistp256", ec.SECP256R1()), + _ECDSA_NISTP384: _SSHFormatECDSA(b"nistp384", ec.SECP384R1()), + _ECDSA_NISTP521: _SSHFormatECDSA(b"nistp521", ec.SECP521R1()), +} + + +def _lookup_kformat(key_type: bytes): + """Return valid format or throw error""" + if not isinstance(key_type, bytes): + key_type = memoryview(key_type).tobytes() + if key_type in _KEY_FORMATS: + return _KEY_FORMATS[key_type] + raise UnsupportedAlgorithm(f"Unsupported key type: {key_type!r}") + + +SSHPrivateKeyTypes = typing.Union[ + ec.EllipticCurvePrivateKey, + rsa.RSAPrivateKey, + dsa.DSAPrivateKey, + ed25519.Ed25519PrivateKey, +] + + +def load_ssh_private_key( + data: bytes, + password: bytes | None, + backend: typing.Any = None, +) -> SSHPrivateKeyTypes: + """Load private key from OpenSSH custom encoding.""" + utils._check_byteslike("data", data) + if password is not None: + utils._check_bytes("password", password) + + m = _PEM_RC.search(data) + if not m: + raise ValueError("Not OpenSSH private key format") + p1 = m.start(1) + p2 = m.end(1) + data = binascii.a2b_base64(memoryview(data)[p1:p2]) + if not data.startswith(_SK_MAGIC): + raise ValueError("Not OpenSSH private key format") + data = memoryview(data)[len(_SK_MAGIC) :] + + # parse header + ciphername, data = _get_sshstr(data) + kdfname, data = _get_sshstr(data) + kdfoptions, data = _get_sshstr(data) + nkeys, data = _get_u32(data) + if nkeys != 1: + raise ValueError("Only one key supported") + + # load public key data + pubdata, data = _get_sshstr(data) + pub_key_type, pubdata = _get_sshstr(pubdata) + kformat = _lookup_kformat(pub_key_type) + pubfields, pubdata = kformat.get_public(pubdata) + _check_empty(pubdata) + + if (ciphername, kdfname) != (_NONE, _NONE): + ciphername_bytes = ciphername.tobytes() + if ciphername_bytes not in _SSH_CIPHERS: + raise UnsupportedAlgorithm( + f"Unsupported cipher: {ciphername_bytes!r}" + ) + if kdfname != _BCRYPT: + raise UnsupportedAlgorithm(f"Unsupported KDF: {kdfname!r}") + blklen = _SSH_CIPHERS[ciphername_bytes].block_len + tag_len = _SSH_CIPHERS[ciphername_bytes].tag_len + # load secret data + edata, data = _get_sshstr(data) + # see https://bugzilla.mindrot.org/show_bug.cgi?id=3553 for + # information about how OpenSSH handles AEAD tags + if _SSH_CIPHERS[ciphername_bytes].is_aead: + tag = bytes(data) + if len(tag) != tag_len: + raise ValueError("Corrupt data: invalid tag length for cipher") + else: + _check_empty(data) + _check_block_size(edata, blklen) + salt, kbuf = _get_sshstr(kdfoptions) + rounds, kbuf = _get_u32(kbuf) + _check_empty(kbuf) + ciph = _init_cipher(ciphername_bytes, password, salt.tobytes(), rounds) + dec = ciph.decryptor() + edata = memoryview(dec.update(edata)) + if _SSH_CIPHERS[ciphername_bytes].is_aead: + assert isinstance(dec, AEADDecryptionContext) + _check_empty(dec.finalize_with_tag(tag)) + else: + # _check_block_size requires data to be a full block so there + # should be no output from finalize + _check_empty(dec.finalize()) + else: + # load secret data + edata, data = _get_sshstr(data) + _check_empty(data) + blklen = 8 + _check_block_size(edata, blklen) + ck1, edata = _get_u32(edata) + ck2, edata = _get_u32(edata) + if ck1 != ck2: + raise ValueError("Corrupt data: broken checksum") + + # load per-key struct + key_type, edata = _get_sshstr(edata) + if key_type != pub_key_type: + raise ValueError("Corrupt data: key type mismatch") + private_key, edata = kformat.load_private(edata, pubfields) + # We don't use the comment + _, edata = _get_sshstr(edata) + + # yes, SSH does padding check *after* all other parsing is done. + # need to follow as it writes zero-byte padding too. + if edata != _PADDING[: len(edata)]: + raise ValueError("Corrupt data: invalid padding") + + if isinstance(private_key, dsa.DSAPrivateKey): + warnings.warn( + "SSH DSA keys are deprecated and will be removed in a future " + "release.", + utils.DeprecatedIn40, + stacklevel=2, + ) + + return private_key + + +def _serialize_ssh_private_key( + private_key: SSHPrivateKeyTypes, + password: bytes, + encryption_algorithm: KeySerializationEncryption, +) -> bytes: + """Serialize private key with OpenSSH custom encoding.""" + utils._check_bytes("password", password) + if isinstance(private_key, dsa.DSAPrivateKey): + warnings.warn( + "SSH DSA key support is deprecated and will be " + "removed in a future release", + utils.DeprecatedIn40, + stacklevel=4, + ) + + key_type = _get_ssh_key_type(private_key) + kformat = _lookup_kformat(key_type) + + # setup parameters + f_kdfoptions = _FragList() + if password: + ciphername = _DEFAULT_CIPHER + blklen = _SSH_CIPHERS[ciphername].block_len + kdfname = _BCRYPT + rounds = _DEFAULT_ROUNDS + if ( + isinstance(encryption_algorithm, _KeySerializationEncryption) + and encryption_algorithm._kdf_rounds is not None + ): + rounds = encryption_algorithm._kdf_rounds + salt = os.urandom(16) + f_kdfoptions.put_sshstr(salt) + f_kdfoptions.put_u32(rounds) + ciph = _init_cipher(ciphername, password, salt, rounds) + else: + ciphername = kdfname = _NONE + blklen = 8 + ciph = None + nkeys = 1 + checkval = os.urandom(4) + comment = b"" + + # encode public and private parts together + f_public_key = _FragList() + f_public_key.put_sshstr(key_type) + kformat.encode_public(private_key.public_key(), f_public_key) + + f_secrets = _FragList([checkval, checkval]) + f_secrets.put_sshstr(key_type) + kformat.encode_private(private_key, f_secrets) + f_secrets.put_sshstr(comment) + f_secrets.put_raw(_PADDING[: blklen - (f_secrets.size() % blklen)]) + + # top-level structure + f_main = _FragList() + f_main.put_raw(_SK_MAGIC) + f_main.put_sshstr(ciphername) + f_main.put_sshstr(kdfname) + f_main.put_sshstr(f_kdfoptions) + f_main.put_u32(nkeys) + f_main.put_sshstr(f_public_key) + f_main.put_sshstr(f_secrets) + + # copy result info bytearray + slen = f_secrets.size() + mlen = f_main.size() + buf = memoryview(bytearray(mlen + blklen)) + f_main.render(buf) + ofs = mlen - slen + + # encrypt in-place + if ciph is not None: + ciph.encryptor().update_into(buf[ofs:mlen], buf[ofs:]) + + return _ssh_pem_encode(buf[:mlen]) + + +SSHPublicKeyTypes = typing.Union[ + ec.EllipticCurvePublicKey, + rsa.RSAPublicKey, + dsa.DSAPublicKey, + ed25519.Ed25519PublicKey, +] + +SSHCertPublicKeyTypes = typing.Union[ + ec.EllipticCurvePublicKey, + rsa.RSAPublicKey, + ed25519.Ed25519PublicKey, +] + + +class SSHCertificateType(enum.Enum): + USER = 1 + HOST = 2 + + +class SSHCertificate: + def __init__( + self, + _nonce: memoryview, + _public_key: SSHPublicKeyTypes, + _serial: int, + _cctype: int, + _key_id: memoryview, + _valid_principals: list[bytes], + _valid_after: int, + _valid_before: int, + _critical_options: dict[bytes, bytes], + _extensions: dict[bytes, bytes], + _sig_type: memoryview, + _sig_key: memoryview, + _inner_sig_type: memoryview, + _signature: memoryview, + _tbs_cert_body: memoryview, + _cert_key_type: bytes, + _cert_body: memoryview, + ): + self._nonce = _nonce + self._public_key = _public_key + self._serial = _serial + try: + self._type = SSHCertificateType(_cctype) + except ValueError: + raise ValueError("Invalid certificate type") + self._key_id = _key_id + self._valid_principals = _valid_principals + self._valid_after = _valid_after + self._valid_before = _valid_before + self._critical_options = _critical_options + self._extensions = _extensions + self._sig_type = _sig_type + self._sig_key = _sig_key + self._inner_sig_type = _inner_sig_type + self._signature = _signature + self._cert_key_type = _cert_key_type + self._cert_body = _cert_body + self._tbs_cert_body = _tbs_cert_body + + @property + def nonce(self) -> bytes: + return bytes(self._nonce) + + def public_key(self) -> SSHCertPublicKeyTypes: + # make mypy happy until we remove DSA support entirely and + # the underlying union won't have a disallowed type + return typing.cast(SSHCertPublicKeyTypes, self._public_key) + + @property + def serial(self) -> int: + return self._serial + + @property + def type(self) -> SSHCertificateType: + return self._type + + @property + def key_id(self) -> bytes: + return bytes(self._key_id) + + @property + def valid_principals(self) -> list[bytes]: + return self._valid_principals + + @property + def valid_before(self) -> int: + return self._valid_before + + @property + def valid_after(self) -> int: + return self._valid_after + + @property + def critical_options(self) -> dict[bytes, bytes]: + return self._critical_options + + @property + def extensions(self) -> dict[bytes, bytes]: + return self._extensions + + def signature_key(self) -> SSHCertPublicKeyTypes: + sigformat = _lookup_kformat(self._sig_type) + signature_key, sigkey_rest = sigformat.load_public(self._sig_key) + _check_empty(sigkey_rest) + return signature_key + + def public_bytes(self) -> bytes: + return ( + bytes(self._cert_key_type) + + b" " + + binascii.b2a_base64(bytes(self._cert_body), newline=False) + ) + + def verify_cert_signature(self) -> None: + signature_key = self.signature_key() + if isinstance(signature_key, ed25519.Ed25519PublicKey): + signature_key.verify( + bytes(self._signature), bytes(self._tbs_cert_body) + ) + elif isinstance(signature_key, ec.EllipticCurvePublicKey): + # The signature is encoded as a pair of big-endian integers + r, data = _get_mpint(self._signature) + s, data = _get_mpint(data) + _check_empty(data) + computed_sig = asym_utils.encode_dss_signature(r, s) + hash_alg = _get_ec_hash_alg(signature_key.curve) + signature_key.verify( + computed_sig, bytes(self._tbs_cert_body), ec.ECDSA(hash_alg) + ) + else: + assert isinstance(signature_key, rsa.RSAPublicKey) + if self._inner_sig_type == _SSH_RSA: + hash_alg = hashes.SHA1() + elif self._inner_sig_type == _SSH_RSA_SHA256: + hash_alg = hashes.SHA256() + else: + assert self._inner_sig_type == _SSH_RSA_SHA512 + hash_alg = hashes.SHA512() + signature_key.verify( + bytes(self._signature), + bytes(self._tbs_cert_body), + padding.PKCS1v15(), + hash_alg, + ) + + +def _get_ec_hash_alg(curve: ec.EllipticCurve) -> hashes.HashAlgorithm: + if isinstance(curve, ec.SECP256R1): + return hashes.SHA256() + elif isinstance(curve, ec.SECP384R1): + return hashes.SHA384() + else: + assert isinstance(curve, ec.SECP521R1) + return hashes.SHA512() + + +def _load_ssh_public_identity( + data: bytes, + _legacy_dsa_allowed=False, +) -> SSHCertificate | SSHPublicKeyTypes: + utils._check_byteslike("data", data) + + m = _SSH_PUBKEY_RC.match(data) + if not m: + raise ValueError("Invalid line format") + key_type = orig_key_type = m.group(1) + key_body = m.group(2) + with_cert = False + if key_type.endswith(_CERT_SUFFIX): + with_cert = True + key_type = key_type[: -len(_CERT_SUFFIX)] + if key_type == _SSH_DSA and not _legacy_dsa_allowed: + raise UnsupportedAlgorithm( + "DSA keys aren't supported in SSH certificates" + ) + kformat = _lookup_kformat(key_type) + + try: + rest = memoryview(binascii.a2b_base64(key_body)) + except (TypeError, binascii.Error): + raise ValueError("Invalid format") + + if with_cert: + cert_body = rest + inner_key_type, rest = _get_sshstr(rest) + if inner_key_type != orig_key_type: + raise ValueError("Invalid key format") + if with_cert: + nonce, rest = _get_sshstr(rest) + public_key, rest = kformat.load_public(rest) + if with_cert: + serial, rest = _get_u64(rest) + cctype, rest = _get_u32(rest) + key_id, rest = _get_sshstr(rest) + principals, rest = _get_sshstr(rest) + valid_principals = [] + while principals: + principal, principals = _get_sshstr(principals) + valid_principals.append(bytes(principal)) + valid_after, rest = _get_u64(rest) + valid_before, rest = _get_u64(rest) + crit_options, rest = _get_sshstr(rest) + critical_options = _parse_exts_opts(crit_options) + exts, rest = _get_sshstr(rest) + extensions = _parse_exts_opts(exts) + # Get the reserved field, which is unused. + _, rest = _get_sshstr(rest) + sig_key_raw, rest = _get_sshstr(rest) + sig_type, sig_key = _get_sshstr(sig_key_raw) + if sig_type == _SSH_DSA and not _legacy_dsa_allowed: + raise UnsupportedAlgorithm( + "DSA signatures aren't supported in SSH certificates" + ) + # Get the entire cert body and subtract the signature + tbs_cert_body = cert_body[: -len(rest)] + signature_raw, rest = _get_sshstr(rest) + _check_empty(rest) + inner_sig_type, sig_rest = _get_sshstr(signature_raw) + # RSA certs can have multiple algorithm types + if ( + sig_type == _SSH_RSA + and inner_sig_type + not in [_SSH_RSA_SHA256, _SSH_RSA_SHA512, _SSH_RSA] + ) or (sig_type != _SSH_RSA and inner_sig_type != sig_type): + raise ValueError("Signature key type does not match") + signature, sig_rest = _get_sshstr(sig_rest) + _check_empty(sig_rest) + return SSHCertificate( + nonce, + public_key, + serial, + cctype, + key_id, + valid_principals, + valid_after, + valid_before, + critical_options, + extensions, + sig_type, + sig_key, + inner_sig_type, + signature, + tbs_cert_body, + orig_key_type, + cert_body, + ) + else: + _check_empty(rest) + return public_key + + +def load_ssh_public_identity( + data: bytes, +) -> SSHCertificate | SSHPublicKeyTypes: + return _load_ssh_public_identity(data) + + +def _parse_exts_opts(exts_opts: memoryview) -> dict[bytes, bytes]: + result: dict[bytes, bytes] = {} + last_name = None + while exts_opts: + name, exts_opts = _get_sshstr(exts_opts) + bname: bytes = bytes(name) + if bname in result: + raise ValueError("Duplicate name") + if last_name is not None and bname < last_name: + raise ValueError("Fields not lexically sorted") + value, exts_opts = _get_sshstr(exts_opts) + if len(value) > 0: + value, extra = _get_sshstr(value) + if len(extra) > 0: + raise ValueError("Unexpected extra data after value") + result[bname] = bytes(value) + last_name = bname + return result + + +def load_ssh_public_key( + data: bytes, backend: typing.Any = None +) -> SSHPublicKeyTypes: + cert_or_key = _load_ssh_public_identity(data, _legacy_dsa_allowed=True) + public_key: SSHPublicKeyTypes + if isinstance(cert_or_key, SSHCertificate): + public_key = cert_or_key.public_key() + else: + public_key = cert_or_key + + if isinstance(public_key, dsa.DSAPublicKey): + warnings.warn( + "SSH DSA keys are deprecated and will be removed in a future " + "release.", + utils.DeprecatedIn40, + stacklevel=2, + ) + return public_key + + +def serialize_ssh_public_key(public_key: SSHPublicKeyTypes) -> bytes: + """One-line public key format for OpenSSH""" + if isinstance(public_key, dsa.DSAPublicKey): + warnings.warn( + "SSH DSA key support is deprecated and will be " + "removed in a future release", + utils.DeprecatedIn40, + stacklevel=4, + ) + key_type = _get_ssh_key_type(public_key) + kformat = _lookup_kformat(key_type) + + f_pub = _FragList() + f_pub.put_sshstr(key_type) + kformat.encode_public(public_key, f_pub) + + pub = binascii.b2a_base64(f_pub.tobytes()).strip() + return b"".join([key_type, b" ", pub]) + + +SSHCertPrivateKeyTypes = typing.Union[ + ec.EllipticCurvePrivateKey, + rsa.RSAPrivateKey, + ed25519.Ed25519PrivateKey, +] + + +# This is an undocumented limit enforced in the openssh codebase for sshd and +# ssh-keygen, but it is undefined in the ssh certificates spec. +_SSHKEY_CERT_MAX_PRINCIPALS = 256 + + +class SSHCertificateBuilder: + def __init__( + self, + _public_key: SSHCertPublicKeyTypes | None = None, + _serial: int | None = None, + _type: SSHCertificateType | None = None, + _key_id: bytes | None = None, + _valid_principals: list[bytes] = [], + _valid_for_all_principals: bool = False, + _valid_before: int | None = None, + _valid_after: int | None = None, + _critical_options: list[tuple[bytes, bytes]] = [], + _extensions: list[tuple[bytes, bytes]] = [], + ): + self._public_key = _public_key + self._serial = _serial + self._type = _type + self._key_id = _key_id + self._valid_principals = _valid_principals + self._valid_for_all_principals = _valid_for_all_principals + self._valid_before = _valid_before + self._valid_after = _valid_after + self._critical_options = _critical_options + self._extensions = _extensions + + def public_key( + self, public_key: SSHCertPublicKeyTypes + ) -> SSHCertificateBuilder: + if not isinstance( + public_key, + ( + ec.EllipticCurvePublicKey, + rsa.RSAPublicKey, + ed25519.Ed25519PublicKey, + ), + ): + raise TypeError("Unsupported key type") + if self._public_key is not None: + raise ValueError("public_key already set") + + return SSHCertificateBuilder( + _public_key=public_key, + _serial=self._serial, + _type=self._type, + _key_id=self._key_id, + _valid_principals=self._valid_principals, + _valid_for_all_principals=self._valid_for_all_principals, + _valid_before=self._valid_before, + _valid_after=self._valid_after, + _critical_options=self._critical_options, + _extensions=self._extensions, + ) + + def serial(self, serial: int) -> SSHCertificateBuilder: + if not isinstance(serial, int): + raise TypeError("serial must be an integer") + if not 0 <= serial < 2**64: + raise ValueError("serial must be between 0 and 2**64") + if self._serial is not None: + raise ValueError("serial already set") + + return SSHCertificateBuilder( + _public_key=self._public_key, + _serial=serial, + _type=self._type, + _key_id=self._key_id, + _valid_principals=self._valid_principals, + _valid_for_all_principals=self._valid_for_all_principals, + _valid_before=self._valid_before, + _valid_after=self._valid_after, + _critical_options=self._critical_options, + _extensions=self._extensions, + ) + + def type(self, type: SSHCertificateType) -> SSHCertificateBuilder: + if not isinstance(type, SSHCertificateType): + raise TypeError("type must be an SSHCertificateType") + if self._type is not None: + raise ValueError("type already set") + + return SSHCertificateBuilder( + _public_key=self._public_key, + _serial=self._serial, + _type=type, + _key_id=self._key_id, + _valid_principals=self._valid_principals, + _valid_for_all_principals=self._valid_for_all_principals, + _valid_before=self._valid_before, + _valid_after=self._valid_after, + _critical_options=self._critical_options, + _extensions=self._extensions, + ) + + def key_id(self, key_id: bytes) -> SSHCertificateBuilder: + if not isinstance(key_id, bytes): + raise TypeError("key_id must be bytes") + if self._key_id is not None: + raise ValueError("key_id already set") + + return SSHCertificateBuilder( + _public_key=self._public_key, + _serial=self._serial, + _type=self._type, + _key_id=key_id, + _valid_principals=self._valid_principals, + _valid_for_all_principals=self._valid_for_all_principals, + _valid_before=self._valid_before, + _valid_after=self._valid_after, + _critical_options=self._critical_options, + _extensions=self._extensions, + ) + + def valid_principals( + self, valid_principals: list[bytes] + ) -> SSHCertificateBuilder: + if self._valid_for_all_principals: + raise ValueError( + "Principals can't be set because the cert is valid " + "for all principals" + ) + if ( + not all(isinstance(x, bytes) for x in valid_principals) + or not valid_principals + ): + raise TypeError( + "principals must be a list of bytes and can't be empty" + ) + if self._valid_principals: + raise ValueError("valid_principals already set") + + if len(valid_principals) > _SSHKEY_CERT_MAX_PRINCIPALS: + raise ValueError( + "Reached or exceeded the maximum number of valid_principals" + ) + + return SSHCertificateBuilder( + _public_key=self._public_key, + _serial=self._serial, + _type=self._type, + _key_id=self._key_id, + _valid_principals=valid_principals, + _valid_for_all_principals=self._valid_for_all_principals, + _valid_before=self._valid_before, + _valid_after=self._valid_after, + _critical_options=self._critical_options, + _extensions=self._extensions, + ) + + def valid_for_all_principals(self): + if self._valid_principals: + raise ValueError( + "valid_principals already set, can't set " + "valid_for_all_principals" + ) + if self._valid_for_all_principals: + raise ValueError("valid_for_all_principals already set") + + return SSHCertificateBuilder( + _public_key=self._public_key, + _serial=self._serial, + _type=self._type, + _key_id=self._key_id, + _valid_principals=self._valid_principals, + _valid_for_all_principals=True, + _valid_before=self._valid_before, + _valid_after=self._valid_after, + _critical_options=self._critical_options, + _extensions=self._extensions, + ) + + def valid_before(self, valid_before: int | float) -> SSHCertificateBuilder: + if not isinstance(valid_before, (int, float)): + raise TypeError("valid_before must be an int or float") + valid_before = int(valid_before) + if valid_before < 0 or valid_before >= 2**64: + raise ValueError("valid_before must [0, 2**64)") + if self._valid_before is not None: + raise ValueError("valid_before already set") + + return SSHCertificateBuilder( + _public_key=self._public_key, + _serial=self._serial, + _type=self._type, + _key_id=self._key_id, + _valid_principals=self._valid_principals, + _valid_for_all_principals=self._valid_for_all_principals, + _valid_before=valid_before, + _valid_after=self._valid_after, + _critical_options=self._critical_options, + _extensions=self._extensions, + ) + + def valid_after(self, valid_after: int | float) -> SSHCertificateBuilder: + if not isinstance(valid_after, (int, float)): + raise TypeError("valid_after must be an int or float") + valid_after = int(valid_after) + if valid_after < 0 or valid_after >= 2**64: + raise ValueError("valid_after must [0, 2**64)") + if self._valid_after is not None: + raise ValueError("valid_after already set") + + return SSHCertificateBuilder( + _public_key=self._public_key, + _serial=self._serial, + _type=self._type, + _key_id=self._key_id, + _valid_principals=self._valid_principals, + _valid_for_all_principals=self._valid_for_all_principals, + _valid_before=self._valid_before, + _valid_after=valid_after, + _critical_options=self._critical_options, + _extensions=self._extensions, + ) + + def add_critical_option( + self, name: bytes, value: bytes + ) -> SSHCertificateBuilder: + if not isinstance(name, bytes) or not isinstance(value, bytes): + raise TypeError("name and value must be bytes") + # This is O(n**2) + if name in [name for name, _ in self._critical_options]: + raise ValueError("Duplicate critical option name") + + return SSHCertificateBuilder( + _public_key=self._public_key, + _serial=self._serial, + _type=self._type, + _key_id=self._key_id, + _valid_principals=self._valid_principals, + _valid_for_all_principals=self._valid_for_all_principals, + _valid_before=self._valid_before, + _valid_after=self._valid_after, + _critical_options=[*self._critical_options, (name, value)], + _extensions=self._extensions, + ) + + def add_extension( + self, name: bytes, value: bytes + ) -> SSHCertificateBuilder: + if not isinstance(name, bytes) or not isinstance(value, bytes): + raise TypeError("name and value must be bytes") + # This is O(n**2) + if name in [name for name, _ in self._extensions]: + raise ValueError("Duplicate extension name") + + return SSHCertificateBuilder( + _public_key=self._public_key, + _serial=self._serial, + _type=self._type, + _key_id=self._key_id, + _valid_principals=self._valid_principals, + _valid_for_all_principals=self._valid_for_all_principals, + _valid_before=self._valid_before, + _valid_after=self._valid_after, + _critical_options=self._critical_options, + _extensions=[*self._extensions, (name, value)], + ) + + def sign(self, private_key: SSHCertPrivateKeyTypes) -> SSHCertificate: + if not isinstance( + private_key, + ( + ec.EllipticCurvePrivateKey, + rsa.RSAPrivateKey, + ed25519.Ed25519PrivateKey, + ), + ): + raise TypeError("Unsupported private key type") + + if self._public_key is None: + raise ValueError("public_key must be set") + + # Not required + serial = 0 if self._serial is None else self._serial + + if self._type is None: + raise ValueError("type must be set") + + # Not required + key_id = b"" if self._key_id is None else self._key_id + + # A zero length list is valid, but means the certificate + # is valid for any principal of the specified type. We require + # the user to explicitly set valid_for_all_principals to get + # that behavior. + if not self._valid_principals and not self._valid_for_all_principals: + raise ValueError( + "valid_principals must be set if valid_for_all_principals " + "is False" + ) + + if self._valid_before is None: + raise ValueError("valid_before must be set") + + if self._valid_after is None: + raise ValueError("valid_after must be set") + + if self._valid_after > self._valid_before: + raise ValueError("valid_after must be earlier than valid_before") + + # lexically sort our byte strings + self._critical_options.sort(key=lambda x: x[0]) + self._extensions.sort(key=lambda x: x[0]) + + key_type = _get_ssh_key_type(self._public_key) + cert_prefix = key_type + _CERT_SUFFIX + + # Marshal the bytes to be signed + nonce = os.urandom(32) + kformat = _lookup_kformat(key_type) + f = _FragList() + f.put_sshstr(cert_prefix) + f.put_sshstr(nonce) + kformat.encode_public(self._public_key, f) + f.put_u64(serial) + f.put_u32(self._type.value) + f.put_sshstr(key_id) + fprincipals = _FragList() + for p in self._valid_principals: + fprincipals.put_sshstr(p) + f.put_sshstr(fprincipals.tobytes()) + f.put_u64(self._valid_after) + f.put_u64(self._valid_before) + fcrit = _FragList() + for name, value in self._critical_options: + fcrit.put_sshstr(name) + if len(value) > 0: + foptval = _FragList() + foptval.put_sshstr(value) + fcrit.put_sshstr(foptval.tobytes()) + else: + fcrit.put_sshstr(value) + f.put_sshstr(fcrit.tobytes()) + fext = _FragList() + for name, value in self._extensions: + fext.put_sshstr(name) + if len(value) > 0: + fextval = _FragList() + fextval.put_sshstr(value) + fext.put_sshstr(fextval.tobytes()) + else: + fext.put_sshstr(value) + f.put_sshstr(fext.tobytes()) + f.put_sshstr(b"") # RESERVED FIELD + # encode CA public key + ca_type = _get_ssh_key_type(private_key) + caformat = _lookup_kformat(ca_type) + caf = _FragList() + caf.put_sshstr(ca_type) + caformat.encode_public(private_key.public_key(), caf) + f.put_sshstr(caf.tobytes()) + # Sigs according to the rules defined for the CA's public key + # (RFC4253 section 6.6 for ssh-rsa, RFC5656 for ECDSA, + # and RFC8032 for Ed25519). + if isinstance(private_key, ed25519.Ed25519PrivateKey): + signature = private_key.sign(f.tobytes()) + fsig = _FragList() + fsig.put_sshstr(ca_type) + fsig.put_sshstr(signature) + f.put_sshstr(fsig.tobytes()) + elif isinstance(private_key, ec.EllipticCurvePrivateKey): + hash_alg = _get_ec_hash_alg(private_key.curve) + signature = private_key.sign(f.tobytes(), ec.ECDSA(hash_alg)) + r, s = asym_utils.decode_dss_signature(signature) + fsig = _FragList() + fsig.put_sshstr(ca_type) + fsigblob = _FragList() + fsigblob.put_mpint(r) + fsigblob.put_mpint(s) + fsig.put_sshstr(fsigblob.tobytes()) + f.put_sshstr(fsig.tobytes()) + + else: + assert isinstance(private_key, rsa.RSAPrivateKey) + # Just like Golang, we're going to use SHA512 for RSA + # https://cs.opensource.google/go/x/crypto/+/refs/tags/ + # v0.4.0:ssh/certs.go;l=445 + # RFC 8332 defines SHA256 and 512 as options + fsig = _FragList() + fsig.put_sshstr(_SSH_RSA_SHA512) + signature = private_key.sign( + f.tobytes(), padding.PKCS1v15(), hashes.SHA512() + ) + fsig.put_sshstr(signature) + f.put_sshstr(fsig.tobytes()) + + cert_data = binascii.b2a_base64(f.tobytes()).strip() + # load_ssh_public_identity returns a union, but this is + # guaranteed to be an SSHCertificate, so we cast to make + # mypy happy. + return typing.cast( + SSHCertificate, + load_ssh_public_identity(b"".join([cert_prefix, b" ", cert_data])), + ) diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__init__.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__init__.py new file mode 100644 index 00000000..c1af4230 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__init__.py @@ -0,0 +1,9 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + + +class InvalidToken(Exception): + pass diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65416fdeea142482be917e8f66f5dacc4f10bd05 GIT binary patch literal 527 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 DX4k6p literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/totp.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/totp.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d709bbdfb07c880de89ec487d47e8793e8cdde71 GIT binary patch literal 2544 zcmb7F&2Jk;6rWw&8{4tt;I<)Y)6^vN!!&V(RH+mpXr+|42&IUci)Crq?2PTD`{B-x zgB%$tLOt}*LvQJ!ND+rrG#t1f@n<-dC9IVyRpP|WRmvq?cyBg#VpG_a-7i7dAe2zWCXP~46qHq4EvfK~*bygMib`G7 zjyYOMlXA=+apI-8lPD#eWGSf-m0TlKyG!WEmP*Jr{D-47O4VB=AO9Vvc_kP%T-OtZ zusqjahI!fqK^U&kh2=0%q;9yYhHcTJcbmESND#e#v-nw%M!atLwPLf*{2;AYnaj8# znBL%)x&JQth=dbm_W}qTgpra$Nl8tR1feJBG#$GeD@Eu@n!O8g(HVLSo-ulg9*3t! z74S6|M2qmY%L(1U}VKG z!E?Ho6wSKjRts0$W{_oW#p5Q^;Xr-=py-O{*(Pr94-EuxU)fy(VS}`yEu!~rMC=EK zik8w+TalLbqp}5Q+}=+m=!rfco)QQ}1&a9**a1W)CBxE5j&BNLdd(B{{74Y>nO)(d zpyO$T48l0V8wj}HM?Z7n*t3`3FPk2P;L2ZkmEv^>*e`$19OkSr&U}-(CMy?KnY&v4 z)LJR~mS78YSY%Y0Up9HOF1#u?>b2%#%~*2`u~_GpV+m`O`HSLfuVR?O<>r+`D!p<1NydL zwmr~%qk?^K*5;w~^-q9=sl$69Wy*3s%Ew>{pFnsMAc*&?Js;tdsGUabi0L(4!MKk{ zLu&XGnsNa9O!arY1uB0YV4Xb69(zC^79Z(56Z1RSg-&+i-bgodPnc1hA+0BbP zne&~@`F8v~KLHznCdfh%UG`jN9*zLINyv);VVIW#PFiGh5I-y%jK4?SQigkmpAm3sPc7|auXeIm+o`L)2r5HUNN&n7WeRoIa99xW1rIdK_Zy7wC1C=E z`3mpY&t*N9K^W%!a5Yi|TLe`F#<@ShKFHuOqZPHPY{AOy!D`?)vdoc~K&t}{9t9rb zFqQRqP@a7X&!Q<0FihdmDieC0d#jcY{T})ScI&k%N$BfL@`Oup%sTl)BjYE#sqy=t zbW_=GY7%j5;=9PhrAIe+Cg(eo^X>FPJ5_iws*S__2Ivtjk(9(j+biZ%VM9xyXR@ow zJ0)8i7FXEcq)s-uEb6eO@S^|_EnYEx5@7}b&&g|&5-EpvxnJ7nLc1j59B#l^_&W&F zjyh@YY+c*$(8o-Ur&uHYLEOM7|SU@{HyQ+ LbuV9Ikg@y)`K(Jb literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/hotp.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/hotp.py new file mode 100644 index 00000000..af5ab6ef --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/hotp.py @@ -0,0 +1,92 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import base64 +import typing +from urllib.parse import quote, urlencode + +from cryptography.hazmat.primitives import constant_time, hmac +from cryptography.hazmat.primitives.hashes import SHA1, SHA256, SHA512 +from cryptography.hazmat.primitives.twofactor import InvalidToken + +HOTPHashTypes = typing.Union[SHA1, SHA256, SHA512] + + +def _generate_uri( + hotp: HOTP, + type_name: str, + account_name: str, + issuer: str | None, + extra_parameters: list[tuple[str, int]], +) -> str: + parameters = [ + ("digits", hotp._length), + ("secret", base64.b32encode(hotp._key)), + ("algorithm", hotp._algorithm.name.upper()), + ] + + if issuer is not None: + parameters.append(("issuer", issuer)) + + parameters.extend(extra_parameters) + + label = ( + f"{quote(issuer)}:{quote(account_name)}" + if issuer + else quote(account_name) + ) + return f"otpauth://{type_name}/{label}?{urlencode(parameters)}" + + +class HOTP: + def __init__( + self, + key: bytes, + length: int, + algorithm: HOTPHashTypes, + backend: typing.Any = None, + enforce_key_length: bool = True, + ) -> None: + if len(key) < 16 and enforce_key_length is True: + raise ValueError("Key length has to be at least 128 bits.") + + if not isinstance(length, int): + raise TypeError("Length parameter must be an integer type.") + + if length < 6 or length > 8: + raise ValueError("Length of HOTP has to be between 6 and 8.") + + if not isinstance(algorithm, (SHA1, SHA256, SHA512)): + raise TypeError("Algorithm must be SHA1, SHA256 or SHA512.") + + self._key = key + self._length = length + self._algorithm = algorithm + + def generate(self, counter: int) -> bytes: + truncated_value = self._dynamic_truncate(counter) + hotp = truncated_value % (10**self._length) + return "{0:0{1}}".format(hotp, self._length).encode() + + def verify(self, hotp: bytes, counter: int) -> None: + if not constant_time.bytes_eq(self.generate(counter), hotp): + raise InvalidToken("Supplied HOTP value does not match.") + + def _dynamic_truncate(self, counter: int) -> int: + ctx = hmac.HMAC(self._key, self._algorithm) + ctx.update(counter.to_bytes(length=8, byteorder="big")) + hmac_value = ctx.finalize() + + offset = hmac_value[len(hmac_value) - 1] & 0b1111 + p = hmac_value[offset : offset + 4] + return int.from_bytes(p, byteorder="big") & 0x7FFFFFFF + + def get_provisioning_uri( + self, account_name: str, counter: int, issuer: str | None + ) -> str: + return _generate_uri( + self, "hotp", account_name, issuer, [("counter", int(counter))] + ) diff --git a/.venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/totp.py b/.venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/totp.py new file mode 100644 index 00000000..68a50774 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/totp.py @@ -0,0 +1,50 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import typing + +from cryptography.hazmat.primitives import constant_time +from cryptography.hazmat.primitives.twofactor import InvalidToken +from cryptography.hazmat.primitives.twofactor.hotp import ( + HOTP, + HOTPHashTypes, + _generate_uri, +) + + +class TOTP: + def __init__( + self, + key: bytes, + length: int, + algorithm: HOTPHashTypes, + time_step: int, + backend: typing.Any = None, + enforce_key_length: bool = True, + ): + self._time_step = time_step + self._hotp = HOTP( + key, length, algorithm, enforce_key_length=enforce_key_length + ) + + def generate(self, time: int | float) -> bytes: + counter = int(time / self._time_step) + return self._hotp.generate(counter) + + def verify(self, totp: bytes, time: int) -> None: + if not constant_time.bytes_eq(self.generate(time), totp): + raise InvalidToken("Supplied TOTP value does not match.") + + def get_provisioning_uri( + self, account_name: str, issuer: str | None + ) -> str: + return _generate_uri( + self._hotp, + "totp", + account_name, + issuer, + [("period", int(self._time_step))], + ) diff --git a/.venv/Lib/site-packages/cryptography/py.typed b/.venv/Lib/site-packages/cryptography/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/.venv/Lib/site-packages/cryptography/utils.py b/.venv/Lib/site-packages/cryptography/utils.py new file mode 100644 index 00000000..a0ec7a3c --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/utils.py @@ -0,0 +1,131 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import enum +import sys +import types +import typing +import warnings + + +# We use a UserWarning subclass, instead of DeprecationWarning, because CPython +# decided deprecation warnings should be invisible by default. +class CryptographyDeprecationWarning(UserWarning): + pass + + +# Several APIs were deprecated with no specific end-of-life date because of the +# ubiquity of their use. They should not be removed until we agree on when that +# cycle ends. +DeprecatedIn36 = CryptographyDeprecationWarning +DeprecatedIn37 = CryptographyDeprecationWarning +DeprecatedIn40 = CryptographyDeprecationWarning +DeprecatedIn41 = CryptographyDeprecationWarning +DeprecatedIn42 = CryptographyDeprecationWarning + + +def _check_bytes(name: str, value: bytes) -> None: + if not isinstance(value, bytes): + raise TypeError(f"{name} must be bytes") + + +def _check_byteslike(name: str, value: bytes) -> None: + try: + memoryview(value) + except TypeError: + raise TypeError(f"{name} must be bytes-like") + + +def int_to_bytes(integer: int, length: int | None = None) -> bytes: + return integer.to_bytes( + length or (integer.bit_length() + 7) // 8 or 1, "big" + ) + + +def _extract_buffer_length(obj: typing.Any) -> tuple[typing.Any, int]: + from cryptography.hazmat.bindings._rust import _openssl + + buf = _openssl.ffi.from_buffer(obj) + return buf, int(_openssl.ffi.cast("uintptr_t", buf)) + + +class InterfaceNotImplemented(Exception): + pass + + +class _DeprecatedValue: + def __init__(self, value: object, message: str, warning_class): + self.value = value + self.message = message + self.warning_class = warning_class + + +class _ModuleWithDeprecations(types.ModuleType): + def __init__(self, module: types.ModuleType): + super().__init__(module.__name__) + self.__dict__["_module"] = module + + def __getattr__(self, attr: str) -> object: + obj = getattr(self._module, attr) + if isinstance(obj, _DeprecatedValue): + warnings.warn(obj.message, obj.warning_class, stacklevel=2) + obj = obj.value + return obj + + def __setattr__(self, attr: str, value: object) -> None: + setattr(self._module, attr, value) + + def __delattr__(self, attr: str) -> None: + obj = getattr(self._module, attr) + if isinstance(obj, _DeprecatedValue): + warnings.warn(obj.message, obj.warning_class, stacklevel=2) + + delattr(self._module, attr) + + def __dir__(self) -> typing.Sequence[str]: + return ["_module", *dir(self._module)] + + +def deprecated( + value: object, + module_name: str, + message: str, + warning_class: type[Warning], + name: str | None = None, +) -> _DeprecatedValue: + module = sys.modules[module_name] + if not isinstance(module, _ModuleWithDeprecations): + sys.modules[module_name] = module = _ModuleWithDeprecations(module) + dv = _DeprecatedValue(value, message, warning_class) + # Maintain backwards compatibility with `name is None` for pyOpenSSL. + if name is not None: + setattr(module, name, dv) + return dv + + +def cached_property(func: typing.Callable) -> property: + cached_name = f"_cached_{func}" + sentinel = object() + + def inner(instance: object): + cache = getattr(instance, cached_name, sentinel) + if cache is not sentinel: + return cache + result = func(instance) + setattr(instance, cached_name, result) + return result + + return property(inner) + + +# Python 3.10 changed representation of enums. We use well-defined object +# representation and string representation from Python 3.9. +class Enum(enum.Enum): + def __repr__(self) -> str: + return f"<{self.__class__.__name__}.{self._name_}: {self._value_!r}>" + + def __str__(self) -> str: + return f"{self.__class__.__name__}.{self._name_}" diff --git a/.venv/Lib/site-packages/cryptography/x509/__init__.py b/.venv/Lib/site-packages/cryptography/x509/__init__.py new file mode 100644 index 00000000..931618aa --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/x509/__init__.py @@ -0,0 +1,257 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +from cryptography.x509 import certificate_transparency, verification +from cryptography.x509.base import ( + Attribute, + AttributeNotFound, + Attributes, + Certificate, + CertificateBuilder, + CertificateRevocationList, + CertificateRevocationListBuilder, + CertificateSigningRequest, + CertificateSigningRequestBuilder, + InvalidVersion, + RevokedCertificate, + RevokedCertificateBuilder, + Version, + load_der_x509_certificate, + load_der_x509_crl, + load_der_x509_csr, + load_pem_x509_certificate, + load_pem_x509_certificates, + load_pem_x509_crl, + load_pem_x509_csr, + random_serial_number, +) +from cryptography.x509.extensions import ( + AccessDescription, + AuthorityInformationAccess, + AuthorityKeyIdentifier, + BasicConstraints, + CertificateIssuer, + CertificatePolicies, + CRLDistributionPoints, + CRLNumber, + CRLReason, + DeltaCRLIndicator, + DistributionPoint, + DuplicateExtension, + ExtendedKeyUsage, + Extension, + ExtensionNotFound, + Extensions, + ExtensionType, + FreshestCRL, + GeneralNames, + InhibitAnyPolicy, + InvalidityDate, + IssuerAlternativeName, + IssuingDistributionPoint, + KeyUsage, + MSCertificateTemplate, + NameConstraints, + NoticeReference, + OCSPAcceptableResponses, + OCSPNoCheck, + OCSPNonce, + PolicyConstraints, + PolicyInformation, + PrecertificateSignedCertificateTimestamps, + PrecertPoison, + ReasonFlags, + SignedCertificateTimestamps, + SubjectAlternativeName, + SubjectInformationAccess, + SubjectKeyIdentifier, + TLSFeature, + TLSFeatureType, + UnrecognizedExtension, + UserNotice, +) +from cryptography.x509.general_name import ( + DirectoryName, + DNSName, + GeneralName, + IPAddress, + OtherName, + RegisteredID, + RFC822Name, + UniformResourceIdentifier, + UnsupportedGeneralNameType, +) +from cryptography.x509.name import ( + Name, + NameAttribute, + RelativeDistinguishedName, +) +from cryptography.x509.oid import ( + AuthorityInformationAccessOID, + CertificatePoliciesOID, + CRLEntryExtensionOID, + ExtendedKeyUsageOID, + ExtensionOID, + NameOID, + ObjectIdentifier, + SignatureAlgorithmOID, +) + +OID_AUTHORITY_INFORMATION_ACCESS = ExtensionOID.AUTHORITY_INFORMATION_ACCESS +OID_AUTHORITY_KEY_IDENTIFIER = ExtensionOID.AUTHORITY_KEY_IDENTIFIER +OID_BASIC_CONSTRAINTS = ExtensionOID.BASIC_CONSTRAINTS +OID_CERTIFICATE_POLICIES = ExtensionOID.CERTIFICATE_POLICIES +OID_CRL_DISTRIBUTION_POINTS = ExtensionOID.CRL_DISTRIBUTION_POINTS +OID_EXTENDED_KEY_USAGE = ExtensionOID.EXTENDED_KEY_USAGE +OID_FRESHEST_CRL = ExtensionOID.FRESHEST_CRL +OID_INHIBIT_ANY_POLICY = ExtensionOID.INHIBIT_ANY_POLICY +OID_ISSUER_ALTERNATIVE_NAME = ExtensionOID.ISSUER_ALTERNATIVE_NAME +OID_KEY_USAGE = ExtensionOID.KEY_USAGE +OID_NAME_CONSTRAINTS = ExtensionOID.NAME_CONSTRAINTS +OID_OCSP_NO_CHECK = ExtensionOID.OCSP_NO_CHECK +OID_POLICY_CONSTRAINTS = ExtensionOID.POLICY_CONSTRAINTS +OID_POLICY_MAPPINGS = ExtensionOID.POLICY_MAPPINGS +OID_SUBJECT_ALTERNATIVE_NAME = ExtensionOID.SUBJECT_ALTERNATIVE_NAME +OID_SUBJECT_DIRECTORY_ATTRIBUTES = ExtensionOID.SUBJECT_DIRECTORY_ATTRIBUTES +OID_SUBJECT_INFORMATION_ACCESS = ExtensionOID.SUBJECT_INFORMATION_ACCESS +OID_SUBJECT_KEY_IDENTIFIER = ExtensionOID.SUBJECT_KEY_IDENTIFIER + +OID_DSA_WITH_SHA1 = SignatureAlgorithmOID.DSA_WITH_SHA1 +OID_DSA_WITH_SHA224 = SignatureAlgorithmOID.DSA_WITH_SHA224 +OID_DSA_WITH_SHA256 = SignatureAlgorithmOID.DSA_WITH_SHA256 +OID_ECDSA_WITH_SHA1 = SignatureAlgorithmOID.ECDSA_WITH_SHA1 +OID_ECDSA_WITH_SHA224 = SignatureAlgorithmOID.ECDSA_WITH_SHA224 +OID_ECDSA_WITH_SHA256 = SignatureAlgorithmOID.ECDSA_WITH_SHA256 +OID_ECDSA_WITH_SHA384 = SignatureAlgorithmOID.ECDSA_WITH_SHA384 +OID_ECDSA_WITH_SHA512 = SignatureAlgorithmOID.ECDSA_WITH_SHA512 +OID_RSA_WITH_MD5 = SignatureAlgorithmOID.RSA_WITH_MD5 +OID_RSA_WITH_SHA1 = SignatureAlgorithmOID.RSA_WITH_SHA1 +OID_RSA_WITH_SHA224 = SignatureAlgorithmOID.RSA_WITH_SHA224 +OID_RSA_WITH_SHA256 = SignatureAlgorithmOID.RSA_WITH_SHA256 +OID_RSA_WITH_SHA384 = SignatureAlgorithmOID.RSA_WITH_SHA384 +OID_RSA_WITH_SHA512 = SignatureAlgorithmOID.RSA_WITH_SHA512 +OID_RSASSA_PSS = SignatureAlgorithmOID.RSASSA_PSS + +OID_COMMON_NAME = NameOID.COMMON_NAME +OID_COUNTRY_NAME = NameOID.COUNTRY_NAME +OID_DOMAIN_COMPONENT = NameOID.DOMAIN_COMPONENT +OID_DN_QUALIFIER = NameOID.DN_QUALIFIER +OID_EMAIL_ADDRESS = NameOID.EMAIL_ADDRESS +OID_GENERATION_QUALIFIER = NameOID.GENERATION_QUALIFIER +OID_GIVEN_NAME = NameOID.GIVEN_NAME +OID_LOCALITY_NAME = NameOID.LOCALITY_NAME +OID_ORGANIZATIONAL_UNIT_NAME = NameOID.ORGANIZATIONAL_UNIT_NAME +OID_ORGANIZATION_NAME = NameOID.ORGANIZATION_NAME +OID_PSEUDONYM = NameOID.PSEUDONYM +OID_SERIAL_NUMBER = NameOID.SERIAL_NUMBER +OID_STATE_OR_PROVINCE_NAME = NameOID.STATE_OR_PROVINCE_NAME +OID_SURNAME = NameOID.SURNAME +OID_TITLE = NameOID.TITLE + +OID_CLIENT_AUTH = ExtendedKeyUsageOID.CLIENT_AUTH +OID_CODE_SIGNING = ExtendedKeyUsageOID.CODE_SIGNING +OID_EMAIL_PROTECTION = ExtendedKeyUsageOID.EMAIL_PROTECTION +OID_OCSP_SIGNING = ExtendedKeyUsageOID.OCSP_SIGNING +OID_SERVER_AUTH = ExtendedKeyUsageOID.SERVER_AUTH +OID_TIME_STAMPING = ExtendedKeyUsageOID.TIME_STAMPING + +OID_ANY_POLICY = CertificatePoliciesOID.ANY_POLICY +OID_CPS_QUALIFIER = CertificatePoliciesOID.CPS_QUALIFIER +OID_CPS_USER_NOTICE = CertificatePoliciesOID.CPS_USER_NOTICE + +OID_CERTIFICATE_ISSUER = CRLEntryExtensionOID.CERTIFICATE_ISSUER +OID_CRL_REASON = CRLEntryExtensionOID.CRL_REASON +OID_INVALIDITY_DATE = CRLEntryExtensionOID.INVALIDITY_DATE + +OID_CA_ISSUERS = AuthorityInformationAccessOID.CA_ISSUERS +OID_OCSP = AuthorityInformationAccessOID.OCSP + +__all__ = [ + "certificate_transparency", + "verification", + "load_pem_x509_certificate", + "load_pem_x509_certificates", + "load_der_x509_certificate", + "load_pem_x509_csr", + "load_der_x509_csr", + "load_pem_x509_crl", + "load_der_x509_crl", + "random_serial_number", + "verification", + "Attribute", + "AttributeNotFound", + "Attributes", + "InvalidVersion", + "DeltaCRLIndicator", + "DuplicateExtension", + "ExtensionNotFound", + "UnsupportedGeneralNameType", + "NameAttribute", + "Name", + "RelativeDistinguishedName", + "ObjectIdentifier", + "ExtensionType", + "Extensions", + "Extension", + "ExtendedKeyUsage", + "FreshestCRL", + "IssuingDistributionPoint", + "TLSFeature", + "TLSFeatureType", + "OCSPAcceptableResponses", + "OCSPNoCheck", + "BasicConstraints", + "CRLNumber", + "KeyUsage", + "AuthorityInformationAccess", + "SubjectInformationAccess", + "AccessDescription", + "CertificatePolicies", + "PolicyInformation", + "UserNotice", + "NoticeReference", + "SubjectKeyIdentifier", + "NameConstraints", + "CRLDistributionPoints", + "DistributionPoint", + "ReasonFlags", + "InhibitAnyPolicy", + "SubjectAlternativeName", + "IssuerAlternativeName", + "AuthorityKeyIdentifier", + "GeneralNames", + "GeneralName", + "RFC822Name", + "DNSName", + "UniformResourceIdentifier", + "RegisteredID", + "DirectoryName", + "IPAddress", + "OtherName", + "Certificate", + "CertificateRevocationList", + "CertificateRevocationListBuilder", + "CertificateSigningRequest", + "RevokedCertificate", + "RevokedCertificateBuilder", + "CertificateSigningRequestBuilder", + "CertificateBuilder", + "Version", + "OID_CA_ISSUERS", + "OID_OCSP", + "CertificateIssuer", + "CRLReason", + "InvalidityDate", + "UnrecognizedExtension", + "PolicyConstraints", + "PrecertificateSignedCertificateTimestamps", + "PrecertPoison", + "OCSPNonce", + "SignedCertificateTimestamps", + "SignatureAlgorithmOID", + "NameOID", + "MSCertificateTemplate", +] diff --git a/.venv/Lib/site-packages/cryptography/x509/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/x509/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..df2d67e98c131c9636d60cf6fa937fa34ce5c4e1 GIT binary patch literal 8120 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 ZJBHUA@6^ZZ9N@w-t~cNx?N9K6_y@&3Du)07 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/x509/__pycache__/base.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/x509/__pycache__/base.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6e4d41ed6b4800bbc1e41e653edc7a626d0d31f9 GIT binary patch literal 50830 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 DEILu~ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/x509/__pycache__/certificate_transparency.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/x509/__pycache__/certificate_transparency.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6bd6a326966986972b4e927a55ce93522363f63e GIT binary patch literal 4537 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 jH{8-iMB7Nz?c#16NS7kV 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 PhmV>67wd#FBKZFS2Q;Xs literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/x509/__pycache__/ocsp.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/x509/__pycache__/ocsp.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65f2833d6cd413f1f41f792b95c9d768b2fd18ed GIT binary patch literal 25432 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/x509/__pycache__/oid.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/x509/__pycache__/oid.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..612e0637fe74e935339269f438cb0c2fc71d4238 GIT binary patch literal 832 zcmc(cKX21O7{>2nCrsHoc1~HgPOx7lC)*&5c5sP(6m-R@G*~DfJahOY7<`EC06eY$7 zOg0j8iv0F>-Q35u6LFr)NYb1azEiscDFvOC5+Yu_ zzB2?N>72%qgyTG;F@*r!qspzJdF*7v45+!!*E_|yD${$s8D@37S&Sbsfd<~s=tWds{QGQIZf6~n*NQ` zUnWie#_5kqZG~Z!WnuUUU8?@*>hxegi1UQ`12zKzMGQQKpnneh zJUF7Wpr8^SFO^8`Z4s=8+qrnMySJl~^_SIE_bJPhGK1%0TbW?>6rUAV2F7@0BmC$q cdbobCOc%FS=zrqA>*xf(@Xpeg*ixZ?0v9*n_W%F@ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/cryptography/x509/__pycache__/verification.cpython-311.pyc b/.venv/Lib/site-packages/cryptography/x509/__pycache__/verification.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c50662993778a3cb152f8e681b25f8f0cfe039bd GIT binary patch literal 754 zcmZutJCD;q5Z-m-ICgLzC;}Z46i0!Kz@ec40RnUgkWh3Y9ED|MIrb#y;77E!1EKN{ zxPk&fLxE@zKY;&{B1N>-NmO)^t~(lL6XkR#u{)lfZ{GfX=(*_?E&_RJP=muN+n)#ZscGRi$J|eEB=IRFFrj8KRq| zfi$YE`w{{QR0q=51`_KW=IR@0>4@qlsE(*{f*QWmBSz(qa2S-=+&E4$Hw%(D?IJF} zzkTbDA#r7=+v~a!aP|4_Bj0C`riRSrUY0Q6N-yt^z{_~O2W$fDHLze10OR^@5(eJ% zaUO&|!qz(At=d0fEMZ2IYmPI>vz&qBFhLZrWYcjF5BavorsFIbGIzW`HTT^Qk(-(Q zAoeksnhwj;jFm-!DojT#%CDTM5iWBGF)%lDV%(m|n9nMrNO2rD3~{C+kh~Y;AG4|m zt3nB)nc(*)IYLd2-|XDAy+q8m_maV@XRh})wO>L6Q6G>E4`L5&a{}?iei8KTG|1rQ z7?a!~r1t5pI%2C1vV;_^nJ~xG None: + super().__init__(msg) + self.oid = oid + + +def _reject_duplicate_extension( + extension: Extension[ExtensionType], + extensions: list[Extension[ExtensionType]], +) -> None: + # This is quadratic in the number of extensions + for e in extensions: + if e.oid == extension.oid: + raise ValueError("This extension has already been set.") + + +def _reject_duplicate_attribute( + oid: ObjectIdentifier, + attributes: list[tuple[ObjectIdentifier, bytes, int | None]], +) -> None: + # This is quadratic in the number of attributes + for attr_oid, _, _ in attributes: + if attr_oid == oid: + raise ValueError("This attribute has already been set.") + + +def _convert_to_naive_utc_time(time: datetime.datetime) -> datetime.datetime: + """Normalizes a datetime to a naive datetime in UTC. + + time -- datetime to normalize. Assumed to be in UTC if not timezone + aware. + """ + if time.tzinfo is not None: + offset = time.utcoffset() + offset = offset if offset else datetime.timedelta() + return time.replace(tzinfo=None) - offset + else: + return time + + +class Attribute: + def __init__( + self, + oid: ObjectIdentifier, + value: bytes, + _type: int = _ASN1Type.UTF8String.value, + ) -> None: + self._oid = oid + self._value = value + self._type = _type + + @property + def oid(self) -> ObjectIdentifier: + return self._oid + + @property + def value(self) -> bytes: + return self._value + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Attribute): + return NotImplemented + + return ( + self.oid == other.oid + and self.value == other.value + and self._type == other._type + ) + + def __hash__(self) -> int: + return hash((self.oid, self.value, self._type)) + + +class Attributes: + def __init__( + self, + attributes: typing.Iterable[Attribute], + ) -> None: + self._attributes = list(attributes) + + __len__, __iter__, __getitem__ = _make_sequence_methods("_attributes") + + def __repr__(self) -> str: + return f"" + + def get_attribute_for_oid(self, oid: ObjectIdentifier) -> Attribute: + for attr in self: + if attr.oid == oid: + return attr + + raise AttributeNotFound(f"No {oid} attribute was found", oid) + + +class Version(utils.Enum): + v1 = 0 + v3 = 2 + + +class InvalidVersion(Exception): + def __init__(self, msg: str, parsed_version: int) -> None: + super().__init__(msg) + self.parsed_version = parsed_version + + +class Certificate(metaclass=abc.ABCMeta): + @abc.abstractmethod + def fingerprint(self, algorithm: hashes.HashAlgorithm) -> bytes: + """ + Returns bytes using digest passed. + """ + + @property + @abc.abstractmethod + def serial_number(self) -> int: + """ + Returns certificate serial number + """ + + @property + @abc.abstractmethod + def version(self) -> Version: + """ + Returns the certificate version + """ + + @abc.abstractmethod + def public_key(self) -> CertificatePublicKeyTypes: + """ + Returns the public key + """ + + @property + @abc.abstractmethod + def not_valid_before(self) -> datetime.datetime: + """ + Not before time (represented as UTC datetime) + """ + + @property + @abc.abstractmethod + def not_valid_before_utc(self) -> datetime.datetime: + """ + Not before time (represented as a non-naive UTC datetime) + """ + + @property + @abc.abstractmethod + def not_valid_after(self) -> datetime.datetime: + """ + Not after time (represented as UTC datetime) + """ + + @property + @abc.abstractmethod + def not_valid_after_utc(self) -> datetime.datetime: + """ + Not after time (represented as a non-naive UTC datetime) + """ + + @property + @abc.abstractmethod + def issuer(self) -> Name: + """ + Returns the issuer name object. + """ + + @property + @abc.abstractmethod + def subject(self) -> Name: + """ + Returns the subject name object. + """ + + @property + @abc.abstractmethod + def signature_hash_algorithm( + self, + ) -> hashes.HashAlgorithm | None: + """ + Returns a HashAlgorithm corresponding to the type of the digest signed + in the certificate. + """ + + @property + @abc.abstractmethod + def signature_algorithm_oid(self) -> ObjectIdentifier: + """ + Returns the ObjectIdentifier of the signature algorithm. + """ + + @property + @abc.abstractmethod + def signature_algorithm_parameters( + self, + ) -> None | padding.PSS | padding.PKCS1v15 | ec.ECDSA: + """ + Returns the signature algorithm parameters. + """ + + @property + @abc.abstractmethod + def extensions(self) -> Extensions: + """ + Returns an Extensions object. + """ + + @property + @abc.abstractmethod + def signature(self) -> bytes: + """ + Returns the signature bytes. + """ + + @property + @abc.abstractmethod + def tbs_certificate_bytes(self) -> bytes: + """ + Returns the tbsCertificate payload bytes as defined in RFC 5280. + """ + + @property + @abc.abstractmethod + def tbs_precertificate_bytes(self) -> bytes: + """ + Returns the tbsCertificate payload bytes with the SCT list extension + stripped. + """ + + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Checks equality. + """ + + @abc.abstractmethod + def __hash__(self) -> int: + """ + Computes a hash. + """ + + @abc.abstractmethod + def public_bytes(self, encoding: serialization.Encoding) -> bytes: + """ + Serializes the certificate to PEM or DER format. + """ + + @abc.abstractmethod + def verify_directly_issued_by(self, issuer: Certificate) -> None: + """ + This method verifies that certificate issuer name matches the + issuer subject name and that the certificate is signed by the + issuer's private key. No other validation is performed. + """ + + +# Runtime isinstance checks need this since the rust class is not a subclass. +Certificate.register(rust_x509.Certificate) + + +class RevokedCertificate(metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def serial_number(self) -> int: + """ + Returns the serial number of the revoked certificate. + """ + + @property + @abc.abstractmethod + def revocation_date(self) -> datetime.datetime: + """ + Returns the date of when this certificate was revoked. + """ + + @property + @abc.abstractmethod + def revocation_date_utc(self) -> datetime.datetime: + """ + Returns the date of when this certificate was revoked as a non-naive + UTC datetime. + """ + + @property + @abc.abstractmethod + def extensions(self) -> Extensions: + """ + Returns an Extensions object containing a list of Revoked extensions. + """ + + +# Runtime isinstance checks need this since the rust class is not a subclass. +RevokedCertificate.register(rust_x509.RevokedCertificate) + + +class _RawRevokedCertificate(RevokedCertificate): + def __init__( + self, + serial_number: int, + revocation_date: datetime.datetime, + extensions: Extensions, + ): + self._serial_number = serial_number + self._revocation_date = revocation_date + self._extensions = extensions + + @property + def serial_number(self) -> int: + return self._serial_number + + @property + def revocation_date(self) -> datetime.datetime: + warnings.warn( + "Properties that return a naïve datetime object have been " + "deprecated. Please switch to revocation_date_utc.", + utils.DeprecatedIn42, + stacklevel=2, + ) + return self._revocation_date + + @property + def revocation_date_utc(self) -> datetime.datetime: + return self._revocation_date.replace(tzinfo=datetime.timezone.utc) + + @property + def extensions(self) -> Extensions: + return self._extensions + + +class CertificateRevocationList(metaclass=abc.ABCMeta): + @abc.abstractmethod + def public_bytes(self, encoding: serialization.Encoding) -> bytes: + """ + Serializes the CRL to PEM or DER format. + """ + + @abc.abstractmethod + def fingerprint(self, algorithm: hashes.HashAlgorithm) -> bytes: + """ + Returns bytes using digest passed. + """ + + @abc.abstractmethod + def get_revoked_certificate_by_serial_number( + self, serial_number: int + ) -> RevokedCertificate | None: + """ + Returns an instance of RevokedCertificate or None if the serial_number + is not in the CRL. + """ + + @property + @abc.abstractmethod + def signature_hash_algorithm( + self, + ) -> hashes.HashAlgorithm | None: + """ + Returns a HashAlgorithm corresponding to the type of the digest signed + in the certificate. + """ + + @property + @abc.abstractmethod + def signature_algorithm_oid(self) -> ObjectIdentifier: + """ + Returns the ObjectIdentifier of the signature algorithm. + """ + + @property + @abc.abstractmethod + def signature_algorithm_parameters( + self, + ) -> None | padding.PSS | padding.PKCS1v15 | ec.ECDSA: + """ + Returns the signature algorithm parameters. + """ + + @property + @abc.abstractmethod + def issuer(self) -> Name: + """ + Returns the X509Name with the issuer of this CRL. + """ + + @property + @abc.abstractmethod + def next_update(self) -> datetime.datetime | None: + """ + Returns the date of next update for this CRL. + """ + + @property + @abc.abstractmethod + def next_update_utc(self) -> datetime.datetime | None: + """ + Returns the date of next update for this CRL as a non-naive UTC + datetime. + """ + + @property + @abc.abstractmethod + def last_update(self) -> datetime.datetime: + """ + Returns the date of last update for this CRL. + """ + + @property + @abc.abstractmethod + def last_update_utc(self) -> datetime.datetime: + """ + Returns the date of last update for this CRL as a non-naive UTC + datetime. + """ + + @property + @abc.abstractmethod + def extensions(self) -> Extensions: + """ + Returns an Extensions object containing a list of CRL extensions. + """ + + @property + @abc.abstractmethod + def signature(self) -> bytes: + """ + Returns the signature bytes. + """ + + @property + @abc.abstractmethod + def tbs_certlist_bytes(self) -> bytes: + """ + Returns the tbsCertList payload bytes as defined in RFC 5280. + """ + + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Checks equality. + """ + + @abc.abstractmethod + def __len__(self) -> int: + """ + Number of revoked certificates in the CRL. + """ + + @typing.overload + def __getitem__(self, idx: int) -> RevokedCertificate: + ... + + @typing.overload + def __getitem__(self, idx: slice) -> list[RevokedCertificate]: + ... + + @abc.abstractmethod + def __getitem__( + self, idx: int | slice + ) -> RevokedCertificate | list[RevokedCertificate]: + """ + Returns a revoked certificate (or slice of revoked certificates). + """ + + @abc.abstractmethod + def __iter__(self) -> typing.Iterator[RevokedCertificate]: + """ + Iterator over the revoked certificates + """ + + @abc.abstractmethod + def is_signature_valid( + self, public_key: CertificateIssuerPublicKeyTypes + ) -> bool: + """ + Verifies signature of revocation list against given public key. + """ + + +CertificateRevocationList.register(rust_x509.CertificateRevocationList) + + +class CertificateSigningRequest(metaclass=abc.ABCMeta): + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Checks equality. + """ + + @abc.abstractmethod + def __hash__(self) -> int: + """ + Computes a hash. + """ + + @abc.abstractmethod + def public_key(self) -> CertificatePublicKeyTypes: + """ + Returns the public key + """ + + @property + @abc.abstractmethod + def subject(self) -> Name: + """ + Returns the subject name object. + """ + + @property + @abc.abstractmethod + def signature_hash_algorithm( + self, + ) -> hashes.HashAlgorithm | None: + """ + Returns a HashAlgorithm corresponding to the type of the digest signed + in the certificate. + """ + + @property + @abc.abstractmethod + def signature_algorithm_oid(self) -> ObjectIdentifier: + """ + Returns the ObjectIdentifier of the signature algorithm. + """ + + @property + @abc.abstractmethod + def signature_algorithm_parameters( + self, + ) -> None | padding.PSS | padding.PKCS1v15 | ec.ECDSA: + """ + Returns the signature algorithm parameters. + """ + + @property + @abc.abstractmethod + def extensions(self) -> Extensions: + """ + Returns the extensions in the signing request. + """ + + @property + @abc.abstractmethod + def attributes(self) -> Attributes: + """ + Returns an Attributes object. + """ + + @abc.abstractmethod + def public_bytes(self, encoding: serialization.Encoding) -> bytes: + """ + Encodes the request to PEM or DER format. + """ + + @property + @abc.abstractmethod + def signature(self) -> bytes: + """ + Returns the signature bytes. + """ + + @property + @abc.abstractmethod + def tbs_certrequest_bytes(self) -> bytes: + """ + Returns the PKCS#10 CertificationRequestInfo bytes as defined in RFC + 2986. + """ + + @property + @abc.abstractmethod + def is_signature_valid(self) -> bool: + """ + Verifies signature of signing request. + """ + + @abc.abstractmethod + def get_attribute_for_oid(self, oid: ObjectIdentifier) -> bytes: + """ + Get the attribute value for a given OID. + """ + + +# Runtime isinstance checks need this since the rust class is not a subclass. +CertificateSigningRequest.register(rust_x509.CertificateSigningRequest) + + +load_pem_x509_certificate = rust_x509.load_pem_x509_certificate +load_der_x509_certificate = rust_x509.load_der_x509_certificate + +load_pem_x509_certificates = rust_x509.load_pem_x509_certificates + +load_pem_x509_csr = rust_x509.load_pem_x509_csr +load_der_x509_csr = rust_x509.load_der_x509_csr + +load_pem_x509_crl = rust_x509.load_pem_x509_crl +load_der_x509_crl = rust_x509.load_der_x509_crl + + +class CertificateSigningRequestBuilder: + def __init__( + self, + subject_name: Name | None = None, + extensions: list[Extension[ExtensionType]] = [], + attributes: list[tuple[ObjectIdentifier, bytes, int | None]] = [], + ): + """ + Creates an empty X.509 certificate request (v1). + """ + self._subject_name = subject_name + self._extensions = extensions + self._attributes = attributes + + def subject_name(self, name: Name) -> CertificateSigningRequestBuilder: + """ + Sets the certificate requestor's distinguished name. + """ + if not isinstance(name, Name): + raise TypeError("Expecting x509.Name object.") + if self._subject_name is not None: + raise ValueError("The subject name may only be set once.") + return CertificateSigningRequestBuilder( + name, self._extensions, self._attributes + ) + + def add_extension( + self, extval: ExtensionType, critical: bool + ) -> CertificateSigningRequestBuilder: + """ + Adds an X.509 extension to the certificate request. + """ + if not isinstance(extval, ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = Extension(extval.oid, critical, extval) + _reject_duplicate_extension(extension, self._extensions) + + return CertificateSigningRequestBuilder( + self._subject_name, + [*self._extensions, extension], + self._attributes, + ) + + def add_attribute( + self, + oid: ObjectIdentifier, + value: bytes, + *, + _tag: _ASN1Type | None = None, + ) -> CertificateSigningRequestBuilder: + """ + Adds an X.509 attribute with an OID and associated value. + """ + if not isinstance(oid, ObjectIdentifier): + raise TypeError("oid must be an ObjectIdentifier") + + if not isinstance(value, bytes): + raise TypeError("value must be bytes") + + if _tag is not None and not isinstance(_tag, _ASN1Type): + raise TypeError("tag must be _ASN1Type") + + _reject_duplicate_attribute(oid, self._attributes) + + if _tag is not None: + tag = _tag.value + else: + tag = None + + return CertificateSigningRequestBuilder( + self._subject_name, + self._extensions, + [*self._attributes, (oid, value, tag)], + ) + + def sign( + self, + private_key: CertificateIssuerPrivateKeyTypes, + algorithm: _AllowedHashTypes | None, + backend: typing.Any = None, + *, + rsa_padding: padding.PSS | padding.PKCS1v15 | None = None, + ) -> CertificateSigningRequest: + """ + Signs the request using the requestor's private key. + """ + if self._subject_name is None: + raise ValueError("A CertificateSigningRequest must have a subject") + + if rsa_padding is not None: + if not isinstance(rsa_padding, (padding.PSS, padding.PKCS1v15)): + raise TypeError("Padding must be PSS or PKCS1v15") + if not isinstance(private_key, rsa.RSAPrivateKey): + raise TypeError("Padding is only supported for RSA keys") + + return rust_x509.create_x509_csr( + self, private_key, algorithm, rsa_padding + ) + + +class CertificateBuilder: + _extensions: list[Extension[ExtensionType]] + + def __init__( + self, + issuer_name: Name | None = None, + subject_name: Name | None = None, + public_key: CertificatePublicKeyTypes | None = None, + serial_number: int | None = None, + not_valid_before: datetime.datetime | None = None, + not_valid_after: datetime.datetime | None = None, + extensions: list[Extension[ExtensionType]] = [], + ) -> None: + self._version = Version.v3 + self._issuer_name = issuer_name + self._subject_name = subject_name + self._public_key = public_key + self._serial_number = serial_number + self._not_valid_before = not_valid_before + self._not_valid_after = not_valid_after + self._extensions = extensions + + def issuer_name(self, name: Name) -> CertificateBuilder: + """ + Sets the CA's distinguished name. + """ + if not isinstance(name, Name): + raise TypeError("Expecting x509.Name object.") + if self._issuer_name is not None: + raise ValueError("The issuer name may only be set once.") + return CertificateBuilder( + name, + self._subject_name, + self._public_key, + self._serial_number, + self._not_valid_before, + self._not_valid_after, + self._extensions, + ) + + def subject_name(self, name: Name) -> CertificateBuilder: + """ + Sets the requestor's distinguished name. + """ + if not isinstance(name, Name): + raise TypeError("Expecting x509.Name object.") + if self._subject_name is not None: + raise ValueError("The subject name may only be set once.") + return CertificateBuilder( + self._issuer_name, + name, + self._public_key, + self._serial_number, + self._not_valid_before, + self._not_valid_after, + self._extensions, + ) + + def public_key( + self, + key: CertificatePublicKeyTypes, + ) -> CertificateBuilder: + """ + Sets the requestor's public key (as found in the signing request). + """ + if not isinstance( + key, + ( + dsa.DSAPublicKey, + rsa.RSAPublicKey, + ec.EllipticCurvePublicKey, + ed25519.Ed25519PublicKey, + ed448.Ed448PublicKey, + x25519.X25519PublicKey, + x448.X448PublicKey, + ), + ): + raise TypeError( + "Expecting one of DSAPublicKey, RSAPublicKey," + " EllipticCurvePublicKey, Ed25519PublicKey," + " Ed448PublicKey, X25519PublicKey, or " + "X448PublicKey." + ) + if self._public_key is not None: + raise ValueError("The public key may only be set once.") + return CertificateBuilder( + self._issuer_name, + self._subject_name, + key, + self._serial_number, + self._not_valid_before, + self._not_valid_after, + self._extensions, + ) + + def serial_number(self, number: int) -> CertificateBuilder: + """ + Sets the certificate serial number. + """ + if not isinstance(number, int): + raise TypeError("Serial number must be of integral type.") + if self._serial_number is not None: + raise ValueError("The serial number may only be set once.") + if number <= 0: + raise ValueError("The serial number should be positive.") + + # ASN.1 integers are always signed, so most significant bit must be + # zero. + if number.bit_length() >= 160: # As defined in RFC 5280 + raise ValueError( + "The serial number should not be more than 159 " "bits." + ) + return CertificateBuilder( + self._issuer_name, + self._subject_name, + self._public_key, + number, + self._not_valid_before, + self._not_valid_after, + self._extensions, + ) + + def not_valid_before(self, time: datetime.datetime) -> CertificateBuilder: + """ + Sets the certificate activation time. + """ + if not isinstance(time, datetime.datetime): + raise TypeError("Expecting datetime object.") + if self._not_valid_before is not None: + raise ValueError("The not valid before may only be set once.") + time = _convert_to_naive_utc_time(time) + if time < _EARLIEST_UTC_TIME: + raise ValueError( + "The not valid before date must be on or after" + " 1950 January 1)." + ) + if self._not_valid_after is not None and time > self._not_valid_after: + raise ValueError( + "The not valid before date must be before the not valid after " + "date." + ) + return CertificateBuilder( + self._issuer_name, + self._subject_name, + self._public_key, + self._serial_number, + time, + self._not_valid_after, + self._extensions, + ) + + def not_valid_after(self, time: datetime.datetime) -> CertificateBuilder: + """ + Sets the certificate expiration time. + """ + if not isinstance(time, datetime.datetime): + raise TypeError("Expecting datetime object.") + if self._not_valid_after is not None: + raise ValueError("The not valid after may only be set once.") + time = _convert_to_naive_utc_time(time) + if time < _EARLIEST_UTC_TIME: + raise ValueError( + "The not valid after date must be on or after" + " 1950 January 1." + ) + if ( + self._not_valid_before is not None + and time < self._not_valid_before + ): + raise ValueError( + "The not valid after date must be after the not valid before " + "date." + ) + return CertificateBuilder( + self._issuer_name, + self._subject_name, + self._public_key, + self._serial_number, + self._not_valid_before, + time, + self._extensions, + ) + + def add_extension( + self, extval: ExtensionType, critical: bool + ) -> CertificateBuilder: + """ + Adds an X.509 extension to the certificate. + """ + if not isinstance(extval, ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = Extension(extval.oid, critical, extval) + _reject_duplicate_extension(extension, self._extensions) + + return CertificateBuilder( + self._issuer_name, + self._subject_name, + self._public_key, + self._serial_number, + self._not_valid_before, + self._not_valid_after, + [*self._extensions, extension], + ) + + def sign( + self, + private_key: CertificateIssuerPrivateKeyTypes, + algorithm: _AllowedHashTypes | None, + backend: typing.Any = None, + *, + rsa_padding: padding.PSS | padding.PKCS1v15 | None = None, + ) -> Certificate: + """ + Signs the certificate using the CA's private key. + """ + if self._subject_name is None: + raise ValueError("A certificate must have a subject name") + + if self._issuer_name is None: + raise ValueError("A certificate must have an issuer name") + + if self._serial_number is None: + raise ValueError("A certificate must have a serial number") + + if self._not_valid_before is None: + raise ValueError("A certificate must have a not valid before time") + + if self._not_valid_after is None: + raise ValueError("A certificate must have a not valid after time") + + if self._public_key is None: + raise ValueError("A certificate must have a public key") + + if rsa_padding is not None: + if not isinstance(rsa_padding, (padding.PSS, padding.PKCS1v15)): + raise TypeError("Padding must be PSS or PKCS1v15") + if not isinstance(private_key, rsa.RSAPrivateKey): + raise TypeError("Padding is only supported for RSA keys") + + return rust_x509.create_x509_certificate( + self, private_key, algorithm, rsa_padding + ) + + +class CertificateRevocationListBuilder: + _extensions: list[Extension[ExtensionType]] + _revoked_certificates: list[RevokedCertificate] + + def __init__( + self, + issuer_name: Name | None = None, + last_update: datetime.datetime | None = None, + next_update: datetime.datetime | None = None, + extensions: list[Extension[ExtensionType]] = [], + revoked_certificates: list[RevokedCertificate] = [], + ): + self._issuer_name = issuer_name + self._last_update = last_update + self._next_update = next_update + self._extensions = extensions + self._revoked_certificates = revoked_certificates + + def issuer_name( + self, issuer_name: Name + ) -> CertificateRevocationListBuilder: + if not isinstance(issuer_name, Name): + raise TypeError("Expecting x509.Name object.") + if self._issuer_name is not None: + raise ValueError("The issuer name may only be set once.") + return CertificateRevocationListBuilder( + issuer_name, + self._last_update, + self._next_update, + self._extensions, + self._revoked_certificates, + ) + + def last_update( + self, last_update: datetime.datetime + ) -> CertificateRevocationListBuilder: + if not isinstance(last_update, datetime.datetime): + raise TypeError("Expecting datetime object.") + if self._last_update is not None: + raise ValueError("Last update may only be set once.") + last_update = _convert_to_naive_utc_time(last_update) + if last_update < _EARLIEST_UTC_TIME: + raise ValueError( + "The last update date must be on or after" " 1950 January 1." + ) + if self._next_update is not None and last_update > self._next_update: + raise ValueError( + "The last update date must be before the next update date." + ) + return CertificateRevocationListBuilder( + self._issuer_name, + last_update, + self._next_update, + self._extensions, + self._revoked_certificates, + ) + + def next_update( + self, next_update: datetime.datetime + ) -> CertificateRevocationListBuilder: + if not isinstance(next_update, datetime.datetime): + raise TypeError("Expecting datetime object.") + if self._next_update is not None: + raise ValueError("Last update may only be set once.") + next_update = _convert_to_naive_utc_time(next_update) + if next_update < _EARLIEST_UTC_TIME: + raise ValueError( + "The last update date must be on or after" " 1950 January 1." + ) + if self._last_update is not None and next_update < self._last_update: + raise ValueError( + "The next update date must be after the last update date." + ) + return CertificateRevocationListBuilder( + self._issuer_name, + self._last_update, + next_update, + self._extensions, + self._revoked_certificates, + ) + + def add_extension( + self, extval: ExtensionType, critical: bool + ) -> CertificateRevocationListBuilder: + """ + Adds an X.509 extension to the certificate revocation list. + """ + if not isinstance(extval, ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = Extension(extval.oid, critical, extval) + _reject_duplicate_extension(extension, self._extensions) + return CertificateRevocationListBuilder( + self._issuer_name, + self._last_update, + self._next_update, + [*self._extensions, extension], + self._revoked_certificates, + ) + + def add_revoked_certificate( + self, revoked_certificate: RevokedCertificate + ) -> CertificateRevocationListBuilder: + """ + Adds a revoked certificate to the CRL. + """ + if not isinstance(revoked_certificate, RevokedCertificate): + raise TypeError("Must be an instance of RevokedCertificate") + + return CertificateRevocationListBuilder( + self._issuer_name, + self._last_update, + self._next_update, + self._extensions, + [*self._revoked_certificates, revoked_certificate], + ) + + def sign( + self, + private_key: CertificateIssuerPrivateKeyTypes, + algorithm: _AllowedHashTypes | None, + backend: typing.Any = None, + *, + rsa_padding: padding.PSS | padding.PKCS1v15 | None = None, + ) -> CertificateRevocationList: + if self._issuer_name is None: + raise ValueError("A CRL must have an issuer name") + + if self._last_update is None: + raise ValueError("A CRL must have a last update time") + + if self._next_update is None: + raise ValueError("A CRL must have a next update time") + + if rsa_padding is not None: + if not isinstance(rsa_padding, (padding.PSS, padding.PKCS1v15)): + raise TypeError("Padding must be PSS or PKCS1v15") + if not isinstance(private_key, rsa.RSAPrivateKey): + raise TypeError("Padding is only supported for RSA keys") + + return rust_x509.create_x509_crl( + self, private_key, algorithm, rsa_padding + ) + + +class RevokedCertificateBuilder: + def __init__( + self, + serial_number: int | None = None, + revocation_date: datetime.datetime | None = None, + extensions: list[Extension[ExtensionType]] = [], + ): + self._serial_number = serial_number + self._revocation_date = revocation_date + self._extensions = extensions + + def serial_number(self, number: int) -> RevokedCertificateBuilder: + if not isinstance(number, int): + raise TypeError("Serial number must be of integral type.") + if self._serial_number is not None: + raise ValueError("The serial number may only be set once.") + if number <= 0: + raise ValueError("The serial number should be positive") + + # ASN.1 integers are always signed, so most significant bit must be + # zero. + if number.bit_length() >= 160: # As defined in RFC 5280 + raise ValueError( + "The serial number should not be more than 159 " "bits." + ) + return RevokedCertificateBuilder( + number, self._revocation_date, self._extensions + ) + + def revocation_date( + self, time: datetime.datetime + ) -> RevokedCertificateBuilder: + if not isinstance(time, datetime.datetime): + raise TypeError("Expecting datetime object.") + if self._revocation_date is not None: + raise ValueError("The revocation date may only be set once.") + time = _convert_to_naive_utc_time(time) + if time < _EARLIEST_UTC_TIME: + raise ValueError( + "The revocation date must be on or after" " 1950 January 1." + ) + return RevokedCertificateBuilder( + self._serial_number, time, self._extensions + ) + + def add_extension( + self, extval: ExtensionType, critical: bool + ) -> RevokedCertificateBuilder: + if not isinstance(extval, ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = Extension(extval.oid, critical, extval) + _reject_duplicate_extension(extension, self._extensions) + return RevokedCertificateBuilder( + self._serial_number, + self._revocation_date, + [*self._extensions, extension], + ) + + def build(self, backend: typing.Any = None) -> RevokedCertificate: + if self._serial_number is None: + raise ValueError("A revoked certificate must have a serial number") + if self._revocation_date is None: + raise ValueError( + "A revoked certificate must have a revocation date" + ) + return _RawRevokedCertificate( + self._serial_number, + self._revocation_date, + Extensions(self._extensions), + ) + + +def random_serial_number() -> int: + return int.from_bytes(os.urandom(20), "big") >> 1 diff --git a/.venv/Lib/site-packages/cryptography/x509/certificate_transparency.py b/.venv/Lib/site-packages/cryptography/x509/certificate_transparency.py new file mode 100644 index 00000000..73647ee7 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/x509/certificate_transparency.py @@ -0,0 +1,97 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc +import datetime + +from cryptography import utils +from cryptography.hazmat.bindings._rust import x509 as rust_x509 +from cryptography.hazmat.primitives.hashes import HashAlgorithm + + +class LogEntryType(utils.Enum): + X509_CERTIFICATE = 0 + PRE_CERTIFICATE = 1 + + +class Version(utils.Enum): + v1 = 0 + + +class SignatureAlgorithm(utils.Enum): + """ + Signature algorithms that are valid for SCTs. + + These are exactly the same as SignatureAlgorithm in RFC 5246 (TLS 1.2). + + See: + """ + + ANONYMOUS = 0 + RSA = 1 + DSA = 2 + ECDSA = 3 + + +class SignedCertificateTimestamp(metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def version(self) -> Version: + """ + Returns the SCT version. + """ + + @property + @abc.abstractmethod + def log_id(self) -> bytes: + """ + Returns an identifier indicating which log this SCT is for. + """ + + @property + @abc.abstractmethod + def timestamp(self) -> datetime.datetime: + """ + Returns the timestamp for this SCT. + """ + + @property + @abc.abstractmethod + def entry_type(self) -> LogEntryType: + """ + Returns whether this is an SCT for a certificate or pre-certificate. + """ + + @property + @abc.abstractmethod + def signature_hash_algorithm(self) -> HashAlgorithm: + """ + Returns the hash algorithm used for the SCT's signature. + """ + + @property + @abc.abstractmethod + def signature_algorithm(self) -> SignatureAlgorithm: + """ + Returns the signing algorithm used for the SCT's signature. + """ + + @property + @abc.abstractmethod + def signature(self) -> bytes: + """ + Returns the signature for this SCT. + """ + + @property + @abc.abstractmethod + def extension_bytes(self) -> bytes: + """ + Returns the raw bytes of any extensions for this SCT. + """ + + +SignedCertificateTimestamp.register(rust_x509.Sct) diff --git a/.venv/Lib/site-packages/cryptography/x509/extensions.py b/.venv/Lib/site-packages/cryptography/x509/extensions.py new file mode 100644 index 00000000..c61c1f48 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/x509/extensions.py @@ -0,0 +1,2175 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc +import datetime +import hashlib +import ipaddress +import typing + +from cryptography import utils +from cryptography.hazmat.bindings._rust import asn1 +from cryptography.hazmat.bindings._rust import x509 as rust_x509 +from cryptography.hazmat.primitives import constant_time, serialization +from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey +from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey +from cryptography.hazmat.primitives.asymmetric.types import ( + CertificateIssuerPublicKeyTypes, + CertificatePublicKeyTypes, +) +from cryptography.x509.certificate_transparency import ( + SignedCertificateTimestamp, +) +from cryptography.x509.general_name import ( + DirectoryName, + DNSName, + GeneralName, + IPAddress, + OtherName, + RegisteredID, + RFC822Name, + UniformResourceIdentifier, + _IPAddressTypes, +) +from cryptography.x509.name import Name, RelativeDistinguishedName +from cryptography.x509.oid import ( + CRLEntryExtensionOID, + ExtensionOID, + ObjectIdentifier, + OCSPExtensionOID, +) + +ExtensionTypeVar = typing.TypeVar( + "ExtensionTypeVar", bound="ExtensionType", covariant=True +) + + +def _key_identifier_from_public_key( + public_key: CertificatePublicKeyTypes, +) -> bytes: + if isinstance(public_key, RSAPublicKey): + data = public_key.public_bytes( + serialization.Encoding.DER, + serialization.PublicFormat.PKCS1, + ) + elif isinstance(public_key, EllipticCurvePublicKey): + data = public_key.public_bytes( + serialization.Encoding.X962, + serialization.PublicFormat.UncompressedPoint, + ) + else: + # This is a very slow way to do this. + serialized = public_key.public_bytes( + serialization.Encoding.DER, + serialization.PublicFormat.SubjectPublicKeyInfo, + ) + data = asn1.parse_spki_for_data(serialized) + + return hashlib.sha1(data).digest() + + +def _make_sequence_methods(field_name: str): + def len_method(self) -> int: + return len(getattr(self, field_name)) + + def iter_method(self): + return iter(getattr(self, field_name)) + + def getitem_method(self, idx): + return getattr(self, field_name)[idx] + + return len_method, iter_method, getitem_method + + +class DuplicateExtension(Exception): + def __init__(self, msg: str, oid: ObjectIdentifier) -> None: + super().__init__(msg) + self.oid = oid + + +class ExtensionNotFound(Exception): + def __init__(self, msg: str, oid: ObjectIdentifier) -> None: + super().__init__(msg) + self.oid = oid + + +class ExtensionType(metaclass=abc.ABCMeta): + oid: typing.ClassVar[ObjectIdentifier] + + def public_bytes(self) -> bytes: + """ + Serializes the extension type to DER. + """ + raise NotImplementedError( + f"public_bytes is not implemented for extension type {self!r}" + ) + + +class Extensions: + def __init__( + self, extensions: typing.Iterable[Extension[ExtensionType]] + ) -> None: + self._extensions = list(extensions) + + def get_extension_for_oid( + self, oid: ObjectIdentifier + ) -> Extension[ExtensionType]: + for ext in self: + if ext.oid == oid: + return ext + + raise ExtensionNotFound(f"No {oid} extension was found", oid) + + def get_extension_for_class( + self, extclass: type[ExtensionTypeVar] + ) -> Extension[ExtensionTypeVar]: + if extclass is UnrecognizedExtension: + raise TypeError( + "UnrecognizedExtension can't be used with " + "get_extension_for_class because more than one instance of the" + " class may be present." + ) + + for ext in self: + if isinstance(ext.value, extclass): + return ext + + raise ExtensionNotFound( + f"No {extclass} extension was found", extclass.oid + ) + + __len__, __iter__, __getitem__ = _make_sequence_methods("_extensions") + + def __repr__(self) -> str: + return f"" + + +class CRLNumber(ExtensionType): + oid = ExtensionOID.CRL_NUMBER + + def __init__(self, crl_number: int) -> None: + if not isinstance(crl_number, int): + raise TypeError("crl_number must be an integer") + + self._crl_number = crl_number + + def __eq__(self, other: object) -> bool: + if not isinstance(other, CRLNumber): + return NotImplemented + + return self.crl_number == other.crl_number + + def __hash__(self) -> int: + return hash(self.crl_number) + + def __repr__(self) -> str: + return f"" + + @property + def crl_number(self) -> int: + return self._crl_number + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class AuthorityKeyIdentifier(ExtensionType): + oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER + + def __init__( + self, + key_identifier: bytes | None, + authority_cert_issuer: typing.Iterable[GeneralName] | None, + authority_cert_serial_number: int | None, + ) -> None: + if (authority_cert_issuer is None) != ( + authority_cert_serial_number is None + ): + raise ValueError( + "authority_cert_issuer and authority_cert_serial_number " + "must both be present or both None" + ) + + if authority_cert_issuer is not None: + authority_cert_issuer = list(authority_cert_issuer) + if not all( + isinstance(x, GeneralName) for x in authority_cert_issuer + ): + raise TypeError( + "authority_cert_issuer must be a list of GeneralName " + "objects" + ) + + if authority_cert_serial_number is not None and not isinstance( + authority_cert_serial_number, int + ): + raise TypeError("authority_cert_serial_number must be an integer") + + self._key_identifier = key_identifier + self._authority_cert_issuer = authority_cert_issuer + self._authority_cert_serial_number = authority_cert_serial_number + + # This takes a subset of CertificatePublicKeyTypes because an issuer + # cannot have an X25519/X448 key. This introduces some unfortunate + # asymmetry that requires typing users to explicitly + # narrow their type, but we should make this accurate and not just + # convenient. + @classmethod + def from_issuer_public_key( + cls, public_key: CertificateIssuerPublicKeyTypes + ) -> AuthorityKeyIdentifier: + digest = _key_identifier_from_public_key(public_key) + return cls( + key_identifier=digest, + authority_cert_issuer=None, + authority_cert_serial_number=None, + ) + + @classmethod + def from_issuer_subject_key_identifier( + cls, ski: SubjectKeyIdentifier + ) -> AuthorityKeyIdentifier: + return cls( + key_identifier=ski.digest, + authority_cert_issuer=None, + authority_cert_serial_number=None, + ) + + def __repr__(self) -> str: + return ( + f"" + ) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, AuthorityKeyIdentifier): + return NotImplemented + + return ( + self.key_identifier == other.key_identifier + and self.authority_cert_issuer == other.authority_cert_issuer + and self.authority_cert_serial_number + == other.authority_cert_serial_number + ) + + def __hash__(self) -> int: + if self.authority_cert_issuer is None: + aci = None + else: + aci = tuple(self.authority_cert_issuer) + return hash( + (self.key_identifier, aci, self.authority_cert_serial_number) + ) + + @property + def key_identifier(self) -> bytes | None: + return self._key_identifier + + @property + def authority_cert_issuer( + self, + ) -> list[GeneralName] | None: + return self._authority_cert_issuer + + @property + def authority_cert_serial_number(self) -> int | None: + return self._authority_cert_serial_number + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class SubjectKeyIdentifier(ExtensionType): + oid = ExtensionOID.SUBJECT_KEY_IDENTIFIER + + def __init__(self, digest: bytes) -> None: + self._digest = digest + + @classmethod + def from_public_key( + cls, public_key: CertificatePublicKeyTypes + ) -> SubjectKeyIdentifier: + return cls(_key_identifier_from_public_key(public_key)) + + @property + def digest(self) -> bytes: + return self._digest + + @property + def key_identifier(self) -> bytes: + return self._digest + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, SubjectKeyIdentifier): + return NotImplemented + + return constant_time.bytes_eq(self.digest, other.digest) + + def __hash__(self) -> int: + return hash(self.digest) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class AuthorityInformationAccess(ExtensionType): + oid = ExtensionOID.AUTHORITY_INFORMATION_ACCESS + + def __init__( + self, descriptions: typing.Iterable[AccessDescription] + ) -> None: + descriptions = list(descriptions) + if not all(isinstance(x, AccessDescription) for x in descriptions): + raise TypeError( + "Every item in the descriptions list must be an " + "AccessDescription" + ) + + self._descriptions = descriptions + + __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions") + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, AuthorityInformationAccess): + return NotImplemented + + return self._descriptions == other._descriptions + + def __hash__(self) -> int: + return hash(tuple(self._descriptions)) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class SubjectInformationAccess(ExtensionType): + oid = ExtensionOID.SUBJECT_INFORMATION_ACCESS + + def __init__( + self, descriptions: typing.Iterable[AccessDescription] + ) -> None: + descriptions = list(descriptions) + if not all(isinstance(x, AccessDescription) for x in descriptions): + raise TypeError( + "Every item in the descriptions list must be an " + "AccessDescription" + ) + + self._descriptions = descriptions + + __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions") + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, SubjectInformationAccess): + return NotImplemented + + return self._descriptions == other._descriptions + + def __hash__(self) -> int: + return hash(tuple(self._descriptions)) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class AccessDescription: + def __init__( + self, access_method: ObjectIdentifier, access_location: GeneralName + ) -> None: + if not isinstance(access_method, ObjectIdentifier): + raise TypeError("access_method must be an ObjectIdentifier") + + if not isinstance(access_location, GeneralName): + raise TypeError("access_location must be a GeneralName") + + self._access_method = access_method + self._access_location = access_location + + def __repr__(self) -> str: + return ( + "".format(self) + ) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, AccessDescription): + return NotImplemented + + return ( + self.access_method == other.access_method + and self.access_location == other.access_location + ) + + def __hash__(self) -> int: + return hash((self.access_method, self.access_location)) + + @property + def access_method(self) -> ObjectIdentifier: + return self._access_method + + @property + def access_location(self) -> GeneralName: + return self._access_location + + +class BasicConstraints(ExtensionType): + oid = ExtensionOID.BASIC_CONSTRAINTS + + def __init__(self, ca: bool, path_length: int | None) -> None: + if not isinstance(ca, bool): + raise TypeError("ca must be a boolean value") + + if path_length is not None and not ca: + raise ValueError("path_length must be None when ca is False") + + if path_length is not None and ( + not isinstance(path_length, int) or path_length < 0 + ): + raise TypeError( + "path_length must be a non-negative integer or None" + ) + + self._ca = ca + self._path_length = path_length + + @property + def ca(self) -> bool: + return self._ca + + @property + def path_length(self) -> int | None: + return self._path_length + + def __repr__(self) -> str: + return ( + "" + ).format(self) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, BasicConstraints): + return NotImplemented + + return self.ca == other.ca and self.path_length == other.path_length + + def __hash__(self) -> int: + return hash((self.ca, self.path_length)) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class DeltaCRLIndicator(ExtensionType): + oid = ExtensionOID.DELTA_CRL_INDICATOR + + def __init__(self, crl_number: int) -> None: + if not isinstance(crl_number, int): + raise TypeError("crl_number must be an integer") + + self._crl_number = crl_number + + @property + def crl_number(self) -> int: + return self._crl_number + + def __eq__(self, other: object) -> bool: + if not isinstance(other, DeltaCRLIndicator): + return NotImplemented + + return self.crl_number == other.crl_number + + def __hash__(self) -> int: + return hash(self.crl_number) + + def __repr__(self) -> str: + return f"" + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class CRLDistributionPoints(ExtensionType): + oid = ExtensionOID.CRL_DISTRIBUTION_POINTS + + def __init__( + self, distribution_points: typing.Iterable[DistributionPoint] + ) -> None: + distribution_points = list(distribution_points) + if not all( + isinstance(x, DistributionPoint) for x in distribution_points + ): + raise TypeError( + "distribution_points must be a list of DistributionPoint " + "objects" + ) + + self._distribution_points = distribution_points + + __len__, __iter__, __getitem__ = _make_sequence_methods( + "_distribution_points" + ) + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, CRLDistributionPoints): + return NotImplemented + + return self._distribution_points == other._distribution_points + + def __hash__(self) -> int: + return hash(tuple(self._distribution_points)) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class FreshestCRL(ExtensionType): + oid = ExtensionOID.FRESHEST_CRL + + def __init__( + self, distribution_points: typing.Iterable[DistributionPoint] + ) -> None: + distribution_points = list(distribution_points) + if not all( + isinstance(x, DistributionPoint) for x in distribution_points + ): + raise TypeError( + "distribution_points must be a list of DistributionPoint " + "objects" + ) + + self._distribution_points = distribution_points + + __len__, __iter__, __getitem__ = _make_sequence_methods( + "_distribution_points" + ) + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, FreshestCRL): + return NotImplemented + + return self._distribution_points == other._distribution_points + + def __hash__(self) -> int: + return hash(tuple(self._distribution_points)) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class DistributionPoint: + def __init__( + self, + full_name: typing.Iterable[GeneralName] | None, + relative_name: RelativeDistinguishedName | None, + reasons: frozenset[ReasonFlags] | None, + crl_issuer: typing.Iterable[GeneralName] | None, + ) -> None: + if full_name and relative_name: + raise ValueError( + "You cannot provide both full_name and relative_name, at " + "least one must be None." + ) + if not full_name and not relative_name and not crl_issuer: + raise ValueError( + "Either full_name, relative_name or crl_issuer must be " + "provided." + ) + + if full_name is not None: + full_name = list(full_name) + if not all(isinstance(x, GeneralName) for x in full_name): + raise TypeError( + "full_name must be a list of GeneralName objects" + ) + + if relative_name: + if not isinstance(relative_name, RelativeDistinguishedName): + raise TypeError( + "relative_name must be a RelativeDistinguishedName" + ) + + if crl_issuer is not None: + crl_issuer = list(crl_issuer) + if not all(isinstance(x, GeneralName) for x in crl_issuer): + raise TypeError( + "crl_issuer must be None or a list of general names" + ) + + if reasons and ( + not isinstance(reasons, frozenset) + or not all(isinstance(x, ReasonFlags) for x in reasons) + ): + raise TypeError("reasons must be None or frozenset of ReasonFlags") + + if reasons and ( + ReasonFlags.unspecified in reasons + or ReasonFlags.remove_from_crl in reasons + ): + raise ValueError( + "unspecified and remove_from_crl are not valid reasons in a " + "DistributionPoint" + ) + + self._full_name = full_name + self._relative_name = relative_name + self._reasons = reasons + self._crl_issuer = crl_issuer + + def __repr__(self) -> str: + return ( + "".format(self) + ) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, DistributionPoint): + return NotImplemented + + return ( + self.full_name == other.full_name + and self.relative_name == other.relative_name + and self.reasons == other.reasons + and self.crl_issuer == other.crl_issuer + ) + + def __hash__(self) -> int: + if self.full_name is not None: + fn: tuple[GeneralName, ...] | None = tuple(self.full_name) + else: + fn = None + + if self.crl_issuer is not None: + crl_issuer: tuple[GeneralName, ...] | None = tuple(self.crl_issuer) + else: + crl_issuer = None + + return hash((fn, self.relative_name, self.reasons, crl_issuer)) + + @property + def full_name(self) -> list[GeneralName] | None: + return self._full_name + + @property + def relative_name(self) -> RelativeDistinguishedName | None: + return self._relative_name + + @property + def reasons(self) -> frozenset[ReasonFlags] | None: + return self._reasons + + @property + def crl_issuer(self) -> list[GeneralName] | None: + return self._crl_issuer + + +class ReasonFlags(utils.Enum): + unspecified = "unspecified" + key_compromise = "keyCompromise" + ca_compromise = "cACompromise" + affiliation_changed = "affiliationChanged" + superseded = "superseded" + cessation_of_operation = "cessationOfOperation" + certificate_hold = "certificateHold" + privilege_withdrawn = "privilegeWithdrawn" + aa_compromise = "aACompromise" + remove_from_crl = "removeFromCRL" + + +# These are distribution point bit string mappings. Not to be confused with +# CRLReason reason flags bit string mappings. +# ReasonFlags ::= BIT STRING { +# unused (0), +# keyCompromise (1), +# cACompromise (2), +# affiliationChanged (3), +# superseded (4), +# cessationOfOperation (5), +# certificateHold (6), +# privilegeWithdrawn (7), +# aACompromise (8) } +_REASON_BIT_MAPPING = { + 1: ReasonFlags.key_compromise, + 2: ReasonFlags.ca_compromise, + 3: ReasonFlags.affiliation_changed, + 4: ReasonFlags.superseded, + 5: ReasonFlags.cessation_of_operation, + 6: ReasonFlags.certificate_hold, + 7: ReasonFlags.privilege_withdrawn, + 8: ReasonFlags.aa_compromise, +} + +_CRLREASONFLAGS = { + ReasonFlags.key_compromise: 1, + ReasonFlags.ca_compromise: 2, + ReasonFlags.affiliation_changed: 3, + ReasonFlags.superseded: 4, + ReasonFlags.cessation_of_operation: 5, + ReasonFlags.certificate_hold: 6, + ReasonFlags.privilege_withdrawn: 7, + ReasonFlags.aa_compromise: 8, +} + + +class PolicyConstraints(ExtensionType): + oid = ExtensionOID.POLICY_CONSTRAINTS + + def __init__( + self, + require_explicit_policy: int | None, + inhibit_policy_mapping: int | None, + ) -> None: + if require_explicit_policy is not None and not isinstance( + require_explicit_policy, int + ): + raise TypeError( + "require_explicit_policy must be a non-negative integer or " + "None" + ) + + if inhibit_policy_mapping is not None and not isinstance( + inhibit_policy_mapping, int + ): + raise TypeError( + "inhibit_policy_mapping must be a non-negative integer or None" + ) + + if inhibit_policy_mapping is None and require_explicit_policy is None: + raise ValueError( + "At least one of require_explicit_policy and " + "inhibit_policy_mapping must not be None" + ) + + self._require_explicit_policy = require_explicit_policy + self._inhibit_policy_mapping = inhibit_policy_mapping + + def __repr__(self) -> str: + return ( + "".format(self) + ) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, PolicyConstraints): + return NotImplemented + + return ( + self.require_explicit_policy == other.require_explicit_policy + and self.inhibit_policy_mapping == other.inhibit_policy_mapping + ) + + def __hash__(self) -> int: + return hash( + (self.require_explicit_policy, self.inhibit_policy_mapping) + ) + + @property + def require_explicit_policy(self) -> int | None: + return self._require_explicit_policy + + @property + def inhibit_policy_mapping(self) -> int | None: + return self._inhibit_policy_mapping + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class CertificatePolicies(ExtensionType): + oid = ExtensionOID.CERTIFICATE_POLICIES + + def __init__(self, policies: typing.Iterable[PolicyInformation]) -> None: + policies = list(policies) + if not all(isinstance(x, PolicyInformation) for x in policies): + raise TypeError( + "Every item in the policies list must be a " + "PolicyInformation" + ) + + self._policies = policies + + __len__, __iter__, __getitem__ = _make_sequence_methods("_policies") + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, CertificatePolicies): + return NotImplemented + + return self._policies == other._policies + + def __hash__(self) -> int: + return hash(tuple(self._policies)) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class PolicyInformation: + def __init__( + self, + policy_identifier: ObjectIdentifier, + policy_qualifiers: typing.Iterable[str | UserNotice] | None, + ) -> None: + if not isinstance(policy_identifier, ObjectIdentifier): + raise TypeError("policy_identifier must be an ObjectIdentifier") + + self._policy_identifier = policy_identifier + + if policy_qualifiers is not None: + policy_qualifiers = list(policy_qualifiers) + if not all( + isinstance(x, (str, UserNotice)) for x in policy_qualifiers + ): + raise TypeError( + "policy_qualifiers must be a list of strings and/or " + "UserNotice objects or None" + ) + + self._policy_qualifiers = policy_qualifiers + + def __repr__(self) -> str: + return ( + "".format(self) + ) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, PolicyInformation): + return NotImplemented + + return ( + self.policy_identifier == other.policy_identifier + and self.policy_qualifiers == other.policy_qualifiers + ) + + def __hash__(self) -> int: + if self.policy_qualifiers is not None: + pq: tuple[str | UserNotice, ...] | None = tuple( + self.policy_qualifiers + ) + else: + pq = None + + return hash((self.policy_identifier, pq)) + + @property + def policy_identifier(self) -> ObjectIdentifier: + return self._policy_identifier + + @property + def policy_qualifiers( + self, + ) -> list[str | UserNotice] | None: + return self._policy_qualifiers + + +class UserNotice: + def __init__( + self, + notice_reference: NoticeReference | None, + explicit_text: str | None, + ) -> None: + if notice_reference and not isinstance( + notice_reference, NoticeReference + ): + raise TypeError( + "notice_reference must be None or a NoticeReference" + ) + + self._notice_reference = notice_reference + self._explicit_text = explicit_text + + def __repr__(self) -> str: + return ( + "".format(self) + ) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, UserNotice): + return NotImplemented + + return ( + self.notice_reference == other.notice_reference + and self.explicit_text == other.explicit_text + ) + + def __hash__(self) -> int: + return hash((self.notice_reference, self.explicit_text)) + + @property + def notice_reference(self) -> NoticeReference | None: + return self._notice_reference + + @property + def explicit_text(self) -> str | None: + return self._explicit_text + + +class NoticeReference: + def __init__( + self, + organization: str | None, + notice_numbers: typing.Iterable[int], + ) -> None: + self._organization = organization + notice_numbers = list(notice_numbers) + if not all(isinstance(x, int) for x in notice_numbers): + raise TypeError("notice_numbers must be a list of integers") + + self._notice_numbers = notice_numbers + + def __repr__(self) -> str: + return ( + "".format(self) + ) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, NoticeReference): + return NotImplemented + + return ( + self.organization == other.organization + and self.notice_numbers == other.notice_numbers + ) + + def __hash__(self) -> int: + return hash((self.organization, tuple(self.notice_numbers))) + + @property + def organization(self) -> str | None: + return self._organization + + @property + def notice_numbers(self) -> list[int]: + return self._notice_numbers + + +class ExtendedKeyUsage(ExtensionType): + oid = ExtensionOID.EXTENDED_KEY_USAGE + + def __init__(self, usages: typing.Iterable[ObjectIdentifier]) -> None: + usages = list(usages) + if not all(isinstance(x, ObjectIdentifier) for x in usages): + raise TypeError( + "Every item in the usages list must be an ObjectIdentifier" + ) + + self._usages = usages + + __len__, __iter__, __getitem__ = _make_sequence_methods("_usages") + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, ExtendedKeyUsage): + return NotImplemented + + return self._usages == other._usages + + def __hash__(self) -> int: + return hash(tuple(self._usages)) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class OCSPNoCheck(ExtensionType): + oid = ExtensionOID.OCSP_NO_CHECK + + def __eq__(self, other: object) -> bool: + if not isinstance(other, OCSPNoCheck): + return NotImplemented + + return True + + def __hash__(self) -> int: + return hash(OCSPNoCheck) + + def __repr__(self) -> str: + return "" + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class PrecertPoison(ExtensionType): + oid = ExtensionOID.PRECERT_POISON + + def __eq__(self, other: object) -> bool: + if not isinstance(other, PrecertPoison): + return NotImplemented + + return True + + def __hash__(self) -> int: + return hash(PrecertPoison) + + def __repr__(self) -> str: + return "" + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class TLSFeature(ExtensionType): + oid = ExtensionOID.TLS_FEATURE + + def __init__(self, features: typing.Iterable[TLSFeatureType]) -> None: + features = list(features) + if ( + not all(isinstance(x, TLSFeatureType) for x in features) + or len(features) == 0 + ): + raise TypeError( + "features must be a list of elements from the TLSFeatureType " + "enum" + ) + + self._features = features + + __len__, __iter__, __getitem__ = _make_sequence_methods("_features") + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, TLSFeature): + return NotImplemented + + return self._features == other._features + + def __hash__(self) -> int: + return hash(tuple(self._features)) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class TLSFeatureType(utils.Enum): + # status_request is defined in RFC 6066 and is used for what is commonly + # called OCSP Must-Staple when present in the TLS Feature extension in an + # X.509 certificate. + status_request = 5 + # status_request_v2 is defined in RFC 6961 and allows multiple OCSP + # responses to be provided. It is not currently in use by clients or + # servers. + status_request_v2 = 17 + + +_TLS_FEATURE_TYPE_TO_ENUM = {x.value: x for x in TLSFeatureType} + + +class InhibitAnyPolicy(ExtensionType): + oid = ExtensionOID.INHIBIT_ANY_POLICY + + def __init__(self, skip_certs: int) -> None: + if not isinstance(skip_certs, int): + raise TypeError("skip_certs must be an integer") + + if skip_certs < 0: + raise ValueError("skip_certs must be a non-negative integer") + + self._skip_certs = skip_certs + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, InhibitAnyPolicy): + return NotImplemented + + return self.skip_certs == other.skip_certs + + def __hash__(self) -> int: + return hash(self.skip_certs) + + @property + def skip_certs(self) -> int: + return self._skip_certs + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class KeyUsage(ExtensionType): + oid = ExtensionOID.KEY_USAGE + + def __init__( + self, + digital_signature: bool, + content_commitment: bool, + key_encipherment: bool, + data_encipherment: bool, + key_agreement: bool, + key_cert_sign: bool, + crl_sign: bool, + encipher_only: bool, + decipher_only: bool, + ) -> None: + if not key_agreement and (encipher_only or decipher_only): + raise ValueError( + "encipher_only and decipher_only can only be true when " + "key_agreement is true" + ) + + self._digital_signature = digital_signature + self._content_commitment = content_commitment + self._key_encipherment = key_encipherment + self._data_encipherment = data_encipherment + self._key_agreement = key_agreement + self._key_cert_sign = key_cert_sign + self._crl_sign = crl_sign + self._encipher_only = encipher_only + self._decipher_only = decipher_only + + @property + def digital_signature(self) -> bool: + return self._digital_signature + + @property + def content_commitment(self) -> bool: + return self._content_commitment + + @property + def key_encipherment(self) -> bool: + return self._key_encipherment + + @property + def data_encipherment(self) -> bool: + return self._data_encipherment + + @property + def key_agreement(self) -> bool: + return self._key_agreement + + @property + def key_cert_sign(self) -> bool: + return self._key_cert_sign + + @property + def crl_sign(self) -> bool: + return self._crl_sign + + @property + def encipher_only(self) -> bool: + if not self.key_agreement: + raise ValueError( + "encipher_only is undefined unless key_agreement is true" + ) + else: + return self._encipher_only + + @property + def decipher_only(self) -> bool: + if not self.key_agreement: + raise ValueError( + "decipher_only is undefined unless key_agreement is true" + ) + else: + return self._decipher_only + + def __repr__(self) -> str: + try: + encipher_only = self.encipher_only + decipher_only = self.decipher_only + except ValueError: + # Users found None confusing because even though encipher/decipher + # have no meaning unless key_agreement is true, to construct an + # instance of the class you still need to pass False. + encipher_only = False + decipher_only = False + + return ( + f"" + ) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, KeyUsage): + return NotImplemented + + return ( + self.digital_signature == other.digital_signature + and self.content_commitment == other.content_commitment + and self.key_encipherment == other.key_encipherment + and self.data_encipherment == other.data_encipherment + and self.key_agreement == other.key_agreement + and self.key_cert_sign == other.key_cert_sign + and self.crl_sign == other.crl_sign + and self._encipher_only == other._encipher_only + and self._decipher_only == other._decipher_only + ) + + def __hash__(self) -> int: + return hash( + ( + self.digital_signature, + self.content_commitment, + self.key_encipherment, + self.data_encipherment, + self.key_agreement, + self.key_cert_sign, + self.crl_sign, + self._encipher_only, + self._decipher_only, + ) + ) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class NameConstraints(ExtensionType): + oid = ExtensionOID.NAME_CONSTRAINTS + + def __init__( + self, + permitted_subtrees: typing.Iterable[GeneralName] | None, + excluded_subtrees: typing.Iterable[GeneralName] | None, + ) -> None: + if permitted_subtrees is not None: + permitted_subtrees = list(permitted_subtrees) + if not permitted_subtrees: + raise ValueError( + "permitted_subtrees must be a non-empty list or None" + ) + if not all(isinstance(x, GeneralName) for x in permitted_subtrees): + raise TypeError( + "permitted_subtrees must be a list of GeneralName objects " + "or None" + ) + + self._validate_tree(permitted_subtrees) + + if excluded_subtrees is not None: + excluded_subtrees = list(excluded_subtrees) + if not excluded_subtrees: + raise ValueError( + "excluded_subtrees must be a non-empty list or None" + ) + if not all(isinstance(x, GeneralName) for x in excluded_subtrees): + raise TypeError( + "excluded_subtrees must be a list of GeneralName objects " + "or None" + ) + + self._validate_tree(excluded_subtrees) + + if permitted_subtrees is None and excluded_subtrees is None: + raise ValueError( + "At least one of permitted_subtrees and excluded_subtrees " + "must not be None" + ) + + self._permitted_subtrees = permitted_subtrees + self._excluded_subtrees = excluded_subtrees + + def __eq__(self, other: object) -> bool: + if not isinstance(other, NameConstraints): + return NotImplemented + + return ( + self.excluded_subtrees == other.excluded_subtrees + and self.permitted_subtrees == other.permitted_subtrees + ) + + def _validate_tree(self, tree: typing.Iterable[GeneralName]) -> None: + self._validate_ip_name(tree) + self._validate_dns_name(tree) + + def _validate_ip_name(self, tree: typing.Iterable[GeneralName]) -> None: + if any( + isinstance(name, IPAddress) + and not isinstance( + name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network) + ) + for name in tree + ): + raise TypeError( + "IPAddress name constraints must be an IPv4Network or" + " IPv6Network object" + ) + + def _validate_dns_name(self, tree: typing.Iterable[GeneralName]) -> None: + if any( + isinstance(name, DNSName) and "*" in name.value for name in tree + ): + raise ValueError( + "DNSName name constraints must not contain the '*' wildcard" + " character" + ) + + def __repr__(self) -> str: + return ( + f"" + ) + + def __hash__(self) -> int: + if self.permitted_subtrees is not None: + ps: tuple[GeneralName, ...] | None = tuple(self.permitted_subtrees) + else: + ps = None + + if self.excluded_subtrees is not None: + es: tuple[GeneralName, ...] | None = tuple(self.excluded_subtrees) + else: + es = None + + return hash((ps, es)) + + @property + def permitted_subtrees( + self, + ) -> list[GeneralName] | None: + return self._permitted_subtrees + + @property + def excluded_subtrees( + self, + ) -> list[GeneralName] | None: + return self._excluded_subtrees + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class Extension(typing.Generic[ExtensionTypeVar]): + def __init__( + self, oid: ObjectIdentifier, critical: bool, value: ExtensionTypeVar + ) -> None: + if not isinstance(oid, ObjectIdentifier): + raise TypeError( + "oid argument must be an ObjectIdentifier instance." + ) + + if not isinstance(critical, bool): + raise TypeError("critical must be a boolean value") + + self._oid = oid + self._critical = critical + self._value = value + + @property + def oid(self) -> ObjectIdentifier: + return self._oid + + @property + def critical(self) -> bool: + return self._critical + + @property + def value(self) -> ExtensionTypeVar: + return self._value + + def __repr__(self) -> str: + return ( + f"" + ) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Extension): + return NotImplemented + + return ( + self.oid == other.oid + and self.critical == other.critical + and self.value == other.value + ) + + def __hash__(self) -> int: + return hash((self.oid, self.critical, self.value)) + + +class GeneralNames: + def __init__(self, general_names: typing.Iterable[GeneralName]) -> None: + general_names = list(general_names) + if not all(isinstance(x, GeneralName) for x in general_names): + raise TypeError( + "Every item in the general_names list must be an " + "object conforming to the GeneralName interface" + ) + + self._general_names = general_names + + __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") + + @typing.overload + def get_values_for_type( + self, + type: type[DNSName] + | type[UniformResourceIdentifier] + | type[RFC822Name], + ) -> list[str]: + ... + + @typing.overload + def get_values_for_type( + self, + type: type[DirectoryName], + ) -> list[Name]: + ... + + @typing.overload + def get_values_for_type( + self, + type: type[RegisteredID], + ) -> list[ObjectIdentifier]: + ... + + @typing.overload + def get_values_for_type( + self, type: type[IPAddress] + ) -> list[_IPAddressTypes]: + ... + + @typing.overload + def get_values_for_type(self, type: type[OtherName]) -> list[OtherName]: + ... + + def get_values_for_type( + self, + type: type[DNSName] + | type[DirectoryName] + | type[IPAddress] + | type[OtherName] + | type[RFC822Name] + | type[RegisteredID] + | type[UniformResourceIdentifier], + ) -> ( + list[_IPAddressTypes] + | list[str] + | list[OtherName] + | list[Name] + | list[ObjectIdentifier] + ): + # Return the value of each GeneralName, except for OtherName instances + # which we return directly because it has two important properties not + # just one value. + objs = (i for i in self if isinstance(i, type)) + if type != OtherName: + return [i.value for i in objs] + return list(objs) + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, GeneralNames): + return NotImplemented + + return self._general_names == other._general_names + + def __hash__(self) -> int: + return hash(tuple(self._general_names)) + + +class SubjectAlternativeName(ExtensionType): + oid = ExtensionOID.SUBJECT_ALTERNATIVE_NAME + + def __init__(self, general_names: typing.Iterable[GeneralName]) -> None: + self._general_names = GeneralNames(general_names) + + __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") + + @typing.overload + def get_values_for_type( + self, + type: type[DNSName] + | type[UniformResourceIdentifier] + | type[RFC822Name], + ) -> list[str]: + ... + + @typing.overload + def get_values_for_type( + self, + type: type[DirectoryName], + ) -> list[Name]: + ... + + @typing.overload + def get_values_for_type( + self, + type: type[RegisteredID], + ) -> list[ObjectIdentifier]: + ... + + @typing.overload + def get_values_for_type( + self, type: type[IPAddress] + ) -> list[_IPAddressTypes]: + ... + + @typing.overload + def get_values_for_type(self, type: type[OtherName]) -> list[OtherName]: + ... + + def get_values_for_type( + self, + type: type[DNSName] + | type[DirectoryName] + | type[IPAddress] + | type[OtherName] + | type[RFC822Name] + | type[RegisteredID] + | type[UniformResourceIdentifier], + ) -> ( + list[_IPAddressTypes] + | list[str] + | list[OtherName] + | list[Name] + | list[ObjectIdentifier] + ): + return self._general_names.get_values_for_type(type) + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, SubjectAlternativeName): + return NotImplemented + + return self._general_names == other._general_names + + def __hash__(self) -> int: + return hash(self._general_names) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class IssuerAlternativeName(ExtensionType): + oid = ExtensionOID.ISSUER_ALTERNATIVE_NAME + + def __init__(self, general_names: typing.Iterable[GeneralName]) -> None: + self._general_names = GeneralNames(general_names) + + __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") + + @typing.overload + def get_values_for_type( + self, + type: type[DNSName] + | type[UniformResourceIdentifier] + | type[RFC822Name], + ) -> list[str]: + ... + + @typing.overload + def get_values_for_type( + self, + type: type[DirectoryName], + ) -> list[Name]: + ... + + @typing.overload + def get_values_for_type( + self, + type: type[RegisteredID], + ) -> list[ObjectIdentifier]: + ... + + @typing.overload + def get_values_for_type( + self, type: type[IPAddress] + ) -> list[_IPAddressTypes]: + ... + + @typing.overload + def get_values_for_type(self, type: type[OtherName]) -> list[OtherName]: + ... + + def get_values_for_type( + self, + type: type[DNSName] + | type[DirectoryName] + | type[IPAddress] + | type[OtherName] + | type[RFC822Name] + | type[RegisteredID] + | type[UniformResourceIdentifier], + ) -> ( + list[_IPAddressTypes] + | list[str] + | list[OtherName] + | list[Name] + | list[ObjectIdentifier] + ): + return self._general_names.get_values_for_type(type) + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, IssuerAlternativeName): + return NotImplemented + + return self._general_names == other._general_names + + def __hash__(self) -> int: + return hash(self._general_names) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class CertificateIssuer(ExtensionType): + oid = CRLEntryExtensionOID.CERTIFICATE_ISSUER + + def __init__(self, general_names: typing.Iterable[GeneralName]) -> None: + self._general_names = GeneralNames(general_names) + + __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") + + @typing.overload + def get_values_for_type( + self, + type: type[DNSName] + | type[UniformResourceIdentifier] + | type[RFC822Name], + ) -> list[str]: + ... + + @typing.overload + def get_values_for_type( + self, + type: type[DirectoryName], + ) -> list[Name]: + ... + + @typing.overload + def get_values_for_type( + self, + type: type[RegisteredID], + ) -> list[ObjectIdentifier]: + ... + + @typing.overload + def get_values_for_type( + self, type: type[IPAddress] + ) -> list[_IPAddressTypes]: + ... + + @typing.overload + def get_values_for_type(self, type: type[OtherName]) -> list[OtherName]: + ... + + def get_values_for_type( + self, + type: type[DNSName] + | type[DirectoryName] + | type[IPAddress] + | type[OtherName] + | type[RFC822Name] + | type[RegisteredID] + | type[UniformResourceIdentifier], + ) -> ( + list[_IPAddressTypes] + | list[str] + | list[OtherName] + | list[Name] + | list[ObjectIdentifier] + ): + return self._general_names.get_values_for_type(type) + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, CertificateIssuer): + return NotImplemented + + return self._general_names == other._general_names + + def __hash__(self) -> int: + return hash(self._general_names) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class CRLReason(ExtensionType): + oid = CRLEntryExtensionOID.CRL_REASON + + def __init__(self, reason: ReasonFlags) -> None: + if not isinstance(reason, ReasonFlags): + raise TypeError("reason must be an element from ReasonFlags") + + self._reason = reason + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, CRLReason): + return NotImplemented + + return self.reason == other.reason + + def __hash__(self) -> int: + return hash(self.reason) + + @property + def reason(self) -> ReasonFlags: + return self._reason + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class InvalidityDate(ExtensionType): + oid = CRLEntryExtensionOID.INVALIDITY_DATE + + def __init__(self, invalidity_date: datetime.datetime) -> None: + if not isinstance(invalidity_date, datetime.datetime): + raise TypeError("invalidity_date must be a datetime.datetime") + + self._invalidity_date = invalidity_date + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, InvalidityDate): + return NotImplemented + + return self.invalidity_date == other.invalidity_date + + def __hash__(self) -> int: + return hash(self.invalidity_date) + + @property + def invalidity_date(self) -> datetime.datetime: + return self._invalidity_date + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class PrecertificateSignedCertificateTimestamps(ExtensionType): + oid = ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS + + def __init__( + self, + signed_certificate_timestamps: typing.Iterable[ + SignedCertificateTimestamp + ], + ) -> None: + signed_certificate_timestamps = list(signed_certificate_timestamps) + if not all( + isinstance(sct, SignedCertificateTimestamp) + for sct in signed_certificate_timestamps + ): + raise TypeError( + "Every item in the signed_certificate_timestamps list must be " + "a SignedCertificateTimestamp" + ) + self._signed_certificate_timestamps = signed_certificate_timestamps + + __len__, __iter__, __getitem__ = _make_sequence_methods( + "_signed_certificate_timestamps" + ) + + def __repr__(self) -> str: + return f"" + + def __hash__(self) -> int: + return hash(tuple(self._signed_certificate_timestamps)) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, PrecertificateSignedCertificateTimestamps): + return NotImplemented + + return ( + self._signed_certificate_timestamps + == other._signed_certificate_timestamps + ) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class SignedCertificateTimestamps(ExtensionType): + oid = ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS + + def __init__( + self, + signed_certificate_timestamps: typing.Iterable[ + SignedCertificateTimestamp + ], + ) -> None: + signed_certificate_timestamps = list(signed_certificate_timestamps) + if not all( + isinstance(sct, SignedCertificateTimestamp) + for sct in signed_certificate_timestamps + ): + raise TypeError( + "Every item in the signed_certificate_timestamps list must be " + "a SignedCertificateTimestamp" + ) + self._signed_certificate_timestamps = signed_certificate_timestamps + + __len__, __iter__, __getitem__ = _make_sequence_methods( + "_signed_certificate_timestamps" + ) + + def __repr__(self) -> str: + return f"" + + def __hash__(self) -> int: + return hash(tuple(self._signed_certificate_timestamps)) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, SignedCertificateTimestamps): + return NotImplemented + + return ( + self._signed_certificate_timestamps + == other._signed_certificate_timestamps + ) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class OCSPNonce(ExtensionType): + oid = OCSPExtensionOID.NONCE + + def __init__(self, nonce: bytes) -> None: + if not isinstance(nonce, bytes): + raise TypeError("nonce must be bytes") + + self._nonce = nonce + + def __eq__(self, other: object) -> bool: + if not isinstance(other, OCSPNonce): + return NotImplemented + + return self.nonce == other.nonce + + def __hash__(self) -> int: + return hash(self.nonce) + + def __repr__(self) -> str: + return f"" + + @property + def nonce(self) -> bytes: + return self._nonce + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class OCSPAcceptableResponses(ExtensionType): + oid = OCSPExtensionOID.ACCEPTABLE_RESPONSES + + def __init__(self, responses: typing.Iterable[ObjectIdentifier]) -> None: + responses = list(responses) + if any(not isinstance(r, ObjectIdentifier) for r in responses): + raise TypeError("All responses must be ObjectIdentifiers") + + self._responses = responses + + def __eq__(self, other: object) -> bool: + if not isinstance(other, OCSPAcceptableResponses): + return NotImplemented + + return self._responses == other._responses + + def __hash__(self) -> int: + return hash(tuple(self._responses)) + + def __repr__(self) -> str: + return f"" + + def __iter__(self) -> typing.Iterator[ObjectIdentifier]: + return iter(self._responses) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class IssuingDistributionPoint(ExtensionType): + oid = ExtensionOID.ISSUING_DISTRIBUTION_POINT + + def __init__( + self, + full_name: typing.Iterable[GeneralName] | None, + relative_name: RelativeDistinguishedName | None, + only_contains_user_certs: bool, + only_contains_ca_certs: bool, + only_some_reasons: frozenset[ReasonFlags] | None, + indirect_crl: bool, + only_contains_attribute_certs: bool, + ) -> None: + if full_name is not None: + full_name = list(full_name) + + if only_some_reasons and ( + not isinstance(only_some_reasons, frozenset) + or not all(isinstance(x, ReasonFlags) for x in only_some_reasons) + ): + raise TypeError( + "only_some_reasons must be None or frozenset of ReasonFlags" + ) + + if only_some_reasons and ( + ReasonFlags.unspecified in only_some_reasons + or ReasonFlags.remove_from_crl in only_some_reasons + ): + raise ValueError( + "unspecified and remove_from_crl are not valid reasons in an " + "IssuingDistributionPoint" + ) + + if not ( + isinstance(only_contains_user_certs, bool) + and isinstance(only_contains_ca_certs, bool) + and isinstance(indirect_crl, bool) + and isinstance(only_contains_attribute_certs, bool) + ): + raise TypeError( + "only_contains_user_certs, only_contains_ca_certs, " + "indirect_crl and only_contains_attribute_certs " + "must all be boolean." + ) + + crl_constraints = [ + only_contains_user_certs, + only_contains_ca_certs, + indirect_crl, + only_contains_attribute_certs, + ] + + if len([x for x in crl_constraints if x]) > 1: + raise ValueError( + "Only one of the following can be set to True: " + "only_contains_user_certs, only_contains_ca_certs, " + "indirect_crl, only_contains_attribute_certs" + ) + + if not any( + [ + only_contains_user_certs, + only_contains_ca_certs, + indirect_crl, + only_contains_attribute_certs, + full_name, + relative_name, + only_some_reasons, + ] + ): + raise ValueError( + "Cannot create empty extension: " + "if only_contains_user_certs, only_contains_ca_certs, " + "indirect_crl, and only_contains_attribute_certs are all False" + ", then either full_name, relative_name, or only_some_reasons " + "must have a value." + ) + + self._only_contains_user_certs = only_contains_user_certs + self._only_contains_ca_certs = only_contains_ca_certs + self._indirect_crl = indirect_crl + self._only_contains_attribute_certs = only_contains_attribute_certs + self._only_some_reasons = only_some_reasons + self._full_name = full_name + self._relative_name = relative_name + + def __repr__(self) -> str: + return ( + f"" + ) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, IssuingDistributionPoint): + return NotImplemented + + return ( + self.full_name == other.full_name + and self.relative_name == other.relative_name + and self.only_contains_user_certs == other.only_contains_user_certs + and self.only_contains_ca_certs == other.only_contains_ca_certs + and self.only_some_reasons == other.only_some_reasons + and self.indirect_crl == other.indirect_crl + and self.only_contains_attribute_certs + == other.only_contains_attribute_certs + ) + + def __hash__(self) -> int: + return hash( + ( + self.full_name, + self.relative_name, + self.only_contains_user_certs, + self.only_contains_ca_certs, + self.only_some_reasons, + self.indirect_crl, + self.only_contains_attribute_certs, + ) + ) + + @property + def full_name(self) -> list[GeneralName] | None: + return self._full_name + + @property + def relative_name(self) -> RelativeDistinguishedName | None: + return self._relative_name + + @property + def only_contains_user_certs(self) -> bool: + return self._only_contains_user_certs + + @property + def only_contains_ca_certs(self) -> bool: + return self._only_contains_ca_certs + + @property + def only_some_reasons( + self, + ) -> frozenset[ReasonFlags] | None: + return self._only_some_reasons + + @property + def indirect_crl(self) -> bool: + return self._indirect_crl + + @property + def only_contains_attribute_certs(self) -> bool: + return self._only_contains_attribute_certs + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class MSCertificateTemplate(ExtensionType): + oid = ExtensionOID.MS_CERTIFICATE_TEMPLATE + + def __init__( + self, + template_id: ObjectIdentifier, + major_version: int | None, + minor_version: int | None, + ) -> None: + if not isinstance(template_id, ObjectIdentifier): + raise TypeError("oid must be an ObjectIdentifier") + self._template_id = template_id + if ( + major_version is not None and not isinstance(major_version, int) + ) or ( + minor_version is not None and not isinstance(minor_version, int) + ): + raise TypeError( + "major_version and minor_version must be integers or None" + ) + self._major_version = major_version + self._minor_version = minor_version + + @property + def template_id(self) -> ObjectIdentifier: + return self._template_id + + @property + def major_version(self) -> int | None: + return self._major_version + + @property + def minor_version(self) -> int | None: + return self._minor_version + + def __repr__(self) -> str: + return ( + f"" + ) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, MSCertificateTemplate): + return NotImplemented + + return ( + self.template_id == other.template_id + and self.major_version == other.major_version + and self.minor_version == other.minor_version + ) + + def __hash__(self) -> int: + return hash((self.template_id, self.major_version, self.minor_version)) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class UnrecognizedExtension(ExtensionType): + def __init__(self, oid: ObjectIdentifier, value: bytes) -> None: + if not isinstance(oid, ObjectIdentifier): + raise TypeError("oid must be an ObjectIdentifier") + self._oid = oid + self._value = value + + @property + def oid(self) -> ObjectIdentifier: # type: ignore[override] + return self._oid + + @property + def value(self) -> bytes: + return self._value + + def __repr__(self) -> str: + return ( + f"" + ) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, UnrecognizedExtension): + return NotImplemented + + return self.oid == other.oid and self.value == other.value + + def __hash__(self) -> int: + return hash((self.oid, self.value)) + + def public_bytes(self) -> bytes: + return self.value diff --git a/.venv/Lib/site-packages/cryptography/x509/general_name.py b/.venv/Lib/site-packages/cryptography/x509/general_name.py new file mode 100644 index 00000000..672f2875 --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/x509/general_name.py @@ -0,0 +1,281 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc +import ipaddress +import typing +from email.utils import parseaddr + +from cryptography.x509.name import Name +from cryptography.x509.oid import ObjectIdentifier + +_IPAddressTypes = typing.Union[ + ipaddress.IPv4Address, + ipaddress.IPv6Address, + ipaddress.IPv4Network, + ipaddress.IPv6Network, +] + + +class UnsupportedGeneralNameType(Exception): + pass + + +class GeneralName(metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def value(self) -> typing.Any: + """ + Return the value of the object + """ + + +class RFC822Name(GeneralName): + def __init__(self, value: str) -> None: + if isinstance(value, str): + try: + value.encode("ascii") + except UnicodeEncodeError: + raise ValueError( + "RFC822Name values should be passed as an A-label string. " + "This means unicode characters should be encoded via " + "a library like idna." + ) + else: + raise TypeError("value must be string") + + name, address = parseaddr(value) + if name or not address: + # parseaddr has found a name (e.g. Name ) or the entire + # value is an empty string. + raise ValueError("Invalid rfc822name value") + + self._value = value + + @property + def value(self) -> str: + return self._value + + @classmethod + def _init_without_validation(cls, value: str) -> RFC822Name: + instance = cls.__new__(cls) + instance._value = value + return instance + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, RFC822Name): + return NotImplemented + + return self.value == other.value + + def __hash__(self) -> int: + return hash(self.value) + + +class DNSName(GeneralName): + def __init__(self, value: str) -> None: + if isinstance(value, str): + try: + value.encode("ascii") + except UnicodeEncodeError: + raise ValueError( + "DNSName values should be passed as an A-label string. " + "This means unicode characters should be encoded via " + "a library like idna." + ) + else: + raise TypeError("value must be string") + + self._value = value + + @property + def value(self) -> str: + return self._value + + @classmethod + def _init_without_validation(cls, value: str) -> DNSName: + instance = cls.__new__(cls) + instance._value = value + return instance + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, DNSName): + return NotImplemented + + return self.value == other.value + + def __hash__(self) -> int: + return hash(self.value) + + +class UniformResourceIdentifier(GeneralName): + def __init__(self, value: str) -> None: + if isinstance(value, str): + try: + value.encode("ascii") + except UnicodeEncodeError: + raise ValueError( + "URI values should be passed as an A-label string. " + "This means unicode characters should be encoded via " + "a library like idna." + ) + else: + raise TypeError("value must be string") + + self._value = value + + @property + def value(self) -> str: + return self._value + + @classmethod + def _init_without_validation(cls, value: str) -> UniformResourceIdentifier: + instance = cls.__new__(cls) + instance._value = value + return instance + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, UniformResourceIdentifier): + return NotImplemented + + return self.value == other.value + + def __hash__(self) -> int: + return hash(self.value) + + +class DirectoryName(GeneralName): + def __init__(self, value: Name) -> None: + if not isinstance(value, Name): + raise TypeError("value must be a Name") + + self._value = value + + @property + def value(self) -> Name: + return self._value + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, DirectoryName): + return NotImplemented + + return self.value == other.value + + def __hash__(self) -> int: + return hash(self.value) + + +class RegisteredID(GeneralName): + def __init__(self, value: ObjectIdentifier) -> None: + if not isinstance(value, ObjectIdentifier): + raise TypeError("value must be an ObjectIdentifier") + + self._value = value + + @property + def value(self) -> ObjectIdentifier: + return self._value + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, RegisteredID): + return NotImplemented + + return self.value == other.value + + def __hash__(self) -> int: + return hash(self.value) + + +class IPAddress(GeneralName): + def __init__(self, value: _IPAddressTypes) -> None: + if not isinstance( + value, + ( + ipaddress.IPv4Address, + ipaddress.IPv6Address, + ipaddress.IPv4Network, + ipaddress.IPv6Network, + ), + ): + raise TypeError( + "value must be an instance of ipaddress.IPv4Address, " + "ipaddress.IPv6Address, ipaddress.IPv4Network, or " + "ipaddress.IPv6Network" + ) + + self._value = value + + @property + def value(self) -> _IPAddressTypes: + return self._value + + def _packed(self) -> bytes: + if isinstance( + self.value, (ipaddress.IPv4Address, ipaddress.IPv6Address) + ): + return self.value.packed + else: + return ( + self.value.network_address.packed + self.value.netmask.packed + ) + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, IPAddress): + return NotImplemented + + return self.value == other.value + + def __hash__(self) -> int: + return hash(self.value) + + +class OtherName(GeneralName): + def __init__(self, type_id: ObjectIdentifier, value: bytes) -> None: + if not isinstance(type_id, ObjectIdentifier): + raise TypeError("type_id must be an ObjectIdentifier") + if not isinstance(value, bytes): + raise TypeError("value must be a binary string") + + self._type_id = type_id + self._value = value + + @property + def type_id(self) -> ObjectIdentifier: + return self._type_id + + @property + def value(self) -> bytes: + return self._value + + def __repr__(self) -> str: + return f"" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, OtherName): + return NotImplemented + + return self.type_id == other.type_id and self.value == other.value + + def __hash__(self) -> int: + return hash((self.type_id, self.value)) diff --git a/.venv/Lib/site-packages/cryptography/x509/name.py b/.venv/Lib/site-packages/cryptography/x509/name.py new file mode 100644 index 00000000..5e8ccfff --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/x509/name.py @@ -0,0 +1,456 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import binascii +import re +import sys +import typing +import warnings + +from cryptography import utils +from cryptography.hazmat.bindings._rust import x509 as rust_x509 +from cryptography.x509.oid import NameOID, ObjectIdentifier + + +class _ASN1Type(utils.Enum): + BitString = 3 + OctetString = 4 + UTF8String = 12 + NumericString = 18 + PrintableString = 19 + T61String = 20 + IA5String = 22 + UTCTime = 23 + GeneralizedTime = 24 + VisibleString = 26 + UniversalString = 28 + BMPString = 30 + + +_ASN1_TYPE_TO_ENUM = {i.value: i for i in _ASN1Type} +_NAMEOID_DEFAULT_TYPE: dict[ObjectIdentifier, _ASN1Type] = { + NameOID.COUNTRY_NAME: _ASN1Type.PrintableString, + NameOID.JURISDICTION_COUNTRY_NAME: _ASN1Type.PrintableString, + NameOID.SERIAL_NUMBER: _ASN1Type.PrintableString, + NameOID.DN_QUALIFIER: _ASN1Type.PrintableString, + NameOID.EMAIL_ADDRESS: _ASN1Type.IA5String, + NameOID.DOMAIN_COMPONENT: _ASN1Type.IA5String, +} + +# Type alias +_OidNameMap = typing.Mapping[ObjectIdentifier, str] +_NameOidMap = typing.Mapping[str, ObjectIdentifier] + +#: Short attribute names from RFC 4514: +#: https://tools.ietf.org/html/rfc4514#page-7 +_NAMEOID_TO_NAME: _OidNameMap = { + NameOID.COMMON_NAME: "CN", + NameOID.LOCALITY_NAME: "L", + NameOID.STATE_OR_PROVINCE_NAME: "ST", + NameOID.ORGANIZATION_NAME: "O", + NameOID.ORGANIZATIONAL_UNIT_NAME: "OU", + NameOID.COUNTRY_NAME: "C", + NameOID.STREET_ADDRESS: "STREET", + NameOID.DOMAIN_COMPONENT: "DC", + NameOID.USER_ID: "UID", +} +_NAME_TO_NAMEOID = {v: k for k, v in _NAMEOID_TO_NAME.items()} + + +def _escape_dn_value(val: str | bytes) -> str: + """Escape special characters in RFC4514 Distinguished Name value.""" + + if not val: + return "" + + # RFC 4514 Section 2.4 defines the value as being the # (U+0023) character + # followed by the hexadecimal encoding of the octets. + if isinstance(val, bytes): + return "#" + binascii.hexlify(val).decode("utf8") + + # See https://tools.ietf.org/html/rfc4514#section-2.4 + val = val.replace("\\", "\\\\") + val = val.replace('"', '\\"') + val = val.replace("+", "\\+") + val = val.replace(",", "\\,") + val = val.replace(";", "\\;") + val = val.replace("<", "\\<") + val = val.replace(">", "\\>") + val = val.replace("\0", "\\00") + + if val[0] in ("#", " "): + val = "\\" + val + if val[-1] == " ": + val = val[:-1] + "\\ " + + return val + + +def _unescape_dn_value(val: str) -> str: + if not val: + return "" + + # See https://tools.ietf.org/html/rfc4514#section-3 + + # special = escaped / SPACE / SHARP / EQUALS + # escaped = DQUOTE / PLUS / COMMA / SEMI / LANGLE / RANGLE + def sub(m): + val = m.group(1) + # Regular escape + if len(val) == 1: + return val + # Hex-value scape + return chr(int(val, 16)) + + return _RFC4514NameParser._PAIR_RE.sub(sub, val) + + +class NameAttribute: + def __init__( + self, + oid: ObjectIdentifier, + value: str | bytes, + _type: _ASN1Type | None = None, + *, + _validate: bool = True, + ) -> None: + if not isinstance(oid, ObjectIdentifier): + raise TypeError( + "oid argument must be an ObjectIdentifier instance." + ) + if _type == _ASN1Type.BitString: + if oid != NameOID.X500_UNIQUE_IDENTIFIER: + raise TypeError( + "oid must be X500_UNIQUE_IDENTIFIER for BitString type." + ) + if not isinstance(value, bytes): + raise TypeError("value must be bytes for BitString") + else: + if not isinstance(value, str): + raise TypeError("value argument must be a str") + + if oid in (NameOID.COUNTRY_NAME, NameOID.JURISDICTION_COUNTRY_NAME): + assert isinstance(value, str) + c_len = len(value.encode("utf8")) + if c_len != 2 and _validate is True: + raise ValueError( + "Country name must be a 2 character country code" + ) + elif c_len != 2: + warnings.warn( + "Country names should be two characters, but the " + f"attribute is {c_len} characters in length.", + stacklevel=2, + ) + + # The appropriate ASN1 string type varies by OID and is defined across + # multiple RFCs including 2459, 3280, and 5280. In general UTF8String + # is preferred (2459), but 3280 and 5280 specify several OIDs with + # alternate types. This means when we see the sentinel value we need + # to look up whether the OID has a non-UTF8 type. If it does, set it + # to that. Otherwise, UTF8! + if _type is None: + _type = _NAMEOID_DEFAULT_TYPE.get(oid, _ASN1Type.UTF8String) + + if not isinstance(_type, _ASN1Type): + raise TypeError("_type must be from the _ASN1Type enum") + + self._oid = oid + self._value = value + self._type = _type + + @property + def oid(self) -> ObjectIdentifier: + return self._oid + + @property + def value(self) -> str | bytes: + return self._value + + @property + def rfc4514_attribute_name(self) -> str: + """ + The short attribute name (for example "CN") if available, + otherwise the OID dotted string. + """ + return _NAMEOID_TO_NAME.get(self.oid, self.oid.dotted_string) + + def rfc4514_string( + self, attr_name_overrides: _OidNameMap | None = None + ) -> str: + """ + Format as RFC4514 Distinguished Name string. + + Use short attribute name if available, otherwise fall back to OID + dotted string. + """ + attr_name = ( + attr_name_overrides.get(self.oid) if attr_name_overrides else None + ) + if attr_name is None: + attr_name = self.rfc4514_attribute_name + + return f"{attr_name}={_escape_dn_value(self.value)}" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, NameAttribute): + return NotImplemented + + return self.oid == other.oid and self.value == other.value + + def __hash__(self) -> int: + return hash((self.oid, self.value)) + + def __repr__(self) -> str: + return f"" + + +class RelativeDistinguishedName: + def __init__(self, attributes: typing.Iterable[NameAttribute]): + attributes = list(attributes) + if not attributes: + raise ValueError("a relative distinguished name cannot be empty") + if not all(isinstance(x, NameAttribute) for x in attributes): + raise TypeError("attributes must be an iterable of NameAttribute") + + # Keep list and frozenset to preserve attribute order where it matters + self._attributes = attributes + self._attribute_set = frozenset(attributes) + + if len(self._attribute_set) != len(attributes): + raise ValueError("duplicate attributes are not allowed") + + def get_attributes_for_oid( + self, oid: ObjectIdentifier + ) -> list[NameAttribute]: + return [i for i in self if i.oid == oid] + + def rfc4514_string( + self, attr_name_overrides: _OidNameMap | None = None + ) -> str: + """ + Format as RFC4514 Distinguished Name string. + + Within each RDN, attributes are joined by '+', although that is rarely + used in certificates. + """ + return "+".join( + attr.rfc4514_string(attr_name_overrides) + for attr in self._attributes + ) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, RelativeDistinguishedName): + return NotImplemented + + return self._attribute_set == other._attribute_set + + def __hash__(self) -> int: + return hash(self._attribute_set) + + def __iter__(self) -> typing.Iterator[NameAttribute]: + return iter(self._attributes) + + def __len__(self) -> int: + return len(self._attributes) + + def __repr__(self) -> str: + return f"" + + +class Name: + @typing.overload + def __init__(self, attributes: typing.Iterable[NameAttribute]) -> None: + ... + + @typing.overload + def __init__( + self, attributes: typing.Iterable[RelativeDistinguishedName] + ) -> None: + ... + + def __init__( + self, + attributes: typing.Iterable[NameAttribute | RelativeDistinguishedName], + ) -> None: + attributes = list(attributes) + if all(isinstance(x, NameAttribute) for x in attributes): + self._attributes = [ + RelativeDistinguishedName([typing.cast(NameAttribute, x)]) + for x in attributes + ] + elif all(isinstance(x, RelativeDistinguishedName) for x in attributes): + self._attributes = typing.cast( + typing.List[RelativeDistinguishedName], attributes + ) + else: + raise TypeError( + "attributes must be a list of NameAttribute" + " or a list RelativeDistinguishedName" + ) + + @classmethod + def from_rfc4514_string( + cls, + data: str, + attr_name_overrides: _NameOidMap | None = None, + ) -> Name: + return _RFC4514NameParser(data, attr_name_overrides or {}).parse() + + def rfc4514_string( + self, attr_name_overrides: _OidNameMap | None = None + ) -> str: + """ + Format as RFC4514 Distinguished Name string. + For example 'CN=foobar.com,O=Foo Corp,C=US' + + An X.509 name is a two-level structure: a list of sets of attributes. + Each list element is separated by ',' and within each list element, set + elements are separated by '+'. The latter is almost never used in + real world certificates. According to RFC4514 section 2.1 the + RDNSequence must be reversed when converting to string representation. + """ + return ",".join( + attr.rfc4514_string(attr_name_overrides) + for attr in reversed(self._attributes) + ) + + def get_attributes_for_oid( + self, oid: ObjectIdentifier + ) -> list[NameAttribute]: + return [i for i in self if i.oid == oid] + + @property + def rdns(self) -> list[RelativeDistinguishedName]: + return self._attributes + + def public_bytes(self, backend: typing.Any = None) -> bytes: + return rust_x509.encode_name_bytes(self) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Name): + return NotImplemented + + return self._attributes == other._attributes + + def __hash__(self) -> int: + # TODO: this is relatively expensive, if this looks like a bottleneck + # for you, consider optimizing! + return hash(tuple(self._attributes)) + + def __iter__(self) -> typing.Iterator[NameAttribute]: + for rdn in self._attributes: + yield from rdn + + def __len__(self) -> int: + return sum(len(rdn) for rdn in self._attributes) + + def __repr__(self) -> str: + rdns = ",".join(attr.rfc4514_string() for attr in self._attributes) + return f"" + + +class _RFC4514NameParser: + _OID_RE = re.compile(r"(0|([1-9]\d*))(\.(0|([1-9]\d*)))+") + _DESCR_RE = re.compile(r"[a-zA-Z][a-zA-Z\d-]*") + + _PAIR = r"\\([\\ #=\"\+,;<>]|[\da-zA-Z]{2})" + _PAIR_RE = re.compile(_PAIR) + _LUTF1 = r"[\x01-\x1f\x21\x24-\x2A\x2D-\x3A\x3D\x3F-\x5B\x5D-\x7F]" + _SUTF1 = r"[\x01-\x21\x23-\x2A\x2D-\x3A\x3D\x3F-\x5B\x5D-\x7F]" + _TUTF1 = r"[\x01-\x1F\x21\x23-\x2A\x2D-\x3A\x3D\x3F-\x5B\x5D-\x7F]" + _UTFMB = rf"[\x80-{chr(sys.maxunicode)}]" + _LEADCHAR = rf"{_LUTF1}|{_UTFMB}" + _STRINGCHAR = rf"{_SUTF1}|{_UTFMB}" + _TRAILCHAR = rf"{_TUTF1}|{_UTFMB}" + _STRING_RE = re.compile( + rf""" + ( + ({_LEADCHAR}|{_PAIR}) + ( + ({_STRINGCHAR}|{_PAIR})* + ({_TRAILCHAR}|{_PAIR}) + )? + )? + """, + re.VERBOSE, + ) + _HEXSTRING_RE = re.compile(r"#([\da-zA-Z]{2})+") + + def __init__(self, data: str, attr_name_overrides: _NameOidMap) -> None: + self._data = data + self._idx = 0 + + self._attr_name_overrides = attr_name_overrides + + def _has_data(self) -> bool: + return self._idx < len(self._data) + + def _peek(self) -> str | None: + if self._has_data(): + return self._data[self._idx] + return None + + def _read_char(self, ch: str) -> None: + if self._peek() != ch: + raise ValueError + self._idx += 1 + + def _read_re(self, pat) -> str: + match = pat.match(self._data, pos=self._idx) + if match is None: + raise ValueError + val = match.group() + self._idx += len(val) + return val + + def parse(self) -> Name: + """ + Parses the `data` string and converts it to a Name. + + According to RFC4514 section 2.1 the RDNSequence must be + reversed when converting to string representation. So, when + we parse it, we need to reverse again to get the RDNs on the + correct order. + """ + rdns = [self._parse_rdn()] + + while self._has_data(): + self._read_char(",") + rdns.append(self._parse_rdn()) + + return Name(reversed(rdns)) + + def _parse_rdn(self) -> RelativeDistinguishedName: + nas = [self._parse_na()] + while self._peek() == "+": + self._read_char("+") + nas.append(self._parse_na()) + + return RelativeDistinguishedName(nas) + + def _parse_na(self) -> NameAttribute: + try: + oid_value = self._read_re(self._OID_RE) + except ValueError: + name = self._read_re(self._DESCR_RE) + oid = self._attr_name_overrides.get( + name, _NAME_TO_NAMEOID.get(name) + ) + if oid is None: + raise ValueError + else: + oid = ObjectIdentifier(oid_value) + + self._read_char("=") + if self._peek() == "#": + value = self._read_re(self._HEXSTRING_RE) + value = binascii.unhexlify(value[1:]).decode() + else: + raw_value = self._read_re(self._STRING_RE) + value = _unescape_dn_value(raw_value) + + return NameAttribute(oid, value) diff --git a/.venv/Lib/site-packages/cryptography/x509/ocsp.py b/.venv/Lib/site-packages/cryptography/x509/ocsp.py new file mode 100644 index 00000000..9751ceaf --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/x509/ocsp.py @@ -0,0 +1,615 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import abc +import datetime +import typing + +from cryptography import utils, x509 +from cryptography.hazmat.bindings._rust import ocsp +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric.types import ( + CertificateIssuerPrivateKeyTypes, +) +from cryptography.x509.base import ( + _EARLIEST_UTC_TIME, + _convert_to_naive_utc_time, + _reject_duplicate_extension, +) + + +class OCSPResponderEncoding(utils.Enum): + HASH = "By Hash" + NAME = "By Name" + + +class OCSPResponseStatus(utils.Enum): + SUCCESSFUL = 0 + MALFORMED_REQUEST = 1 + INTERNAL_ERROR = 2 + TRY_LATER = 3 + SIG_REQUIRED = 5 + UNAUTHORIZED = 6 + + +_ALLOWED_HASHES = ( + hashes.SHA1, + hashes.SHA224, + hashes.SHA256, + hashes.SHA384, + hashes.SHA512, +) + + +def _verify_algorithm(algorithm: hashes.HashAlgorithm) -> None: + if not isinstance(algorithm, _ALLOWED_HASHES): + raise ValueError( + "Algorithm must be SHA1, SHA224, SHA256, SHA384, or SHA512" + ) + + +class OCSPCertStatus(utils.Enum): + GOOD = 0 + REVOKED = 1 + UNKNOWN = 2 + + +class _SingleResponse: + def __init__( + self, + cert: x509.Certificate, + issuer: x509.Certificate, + algorithm: hashes.HashAlgorithm, + cert_status: OCSPCertStatus, + this_update: datetime.datetime, + next_update: datetime.datetime | None, + revocation_time: datetime.datetime | None, + revocation_reason: x509.ReasonFlags | None, + ): + if not isinstance(cert, x509.Certificate) or not isinstance( + issuer, x509.Certificate + ): + raise TypeError("cert and issuer must be a Certificate") + + _verify_algorithm(algorithm) + if not isinstance(this_update, datetime.datetime): + raise TypeError("this_update must be a datetime object") + if next_update is not None and not isinstance( + next_update, datetime.datetime + ): + raise TypeError("next_update must be a datetime object or None") + + self._cert = cert + self._issuer = issuer + self._algorithm = algorithm + self._this_update = this_update + self._next_update = next_update + + if not isinstance(cert_status, OCSPCertStatus): + raise TypeError( + "cert_status must be an item from the OCSPCertStatus enum" + ) + if cert_status is not OCSPCertStatus.REVOKED: + if revocation_time is not None: + raise ValueError( + "revocation_time can only be provided if the certificate " + "is revoked" + ) + if revocation_reason is not None: + raise ValueError( + "revocation_reason can only be provided if the certificate" + " is revoked" + ) + else: + if not isinstance(revocation_time, datetime.datetime): + raise TypeError("revocation_time must be a datetime object") + + revocation_time = _convert_to_naive_utc_time(revocation_time) + if revocation_time < _EARLIEST_UTC_TIME: + raise ValueError( + "The revocation_time must be on or after" + " 1950 January 1." + ) + + if revocation_reason is not None and not isinstance( + revocation_reason, x509.ReasonFlags + ): + raise TypeError( + "revocation_reason must be an item from the ReasonFlags " + "enum or None" + ) + + self._cert_status = cert_status + self._revocation_time = revocation_time + self._revocation_reason = revocation_reason + + +class OCSPRequest(metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def issuer_key_hash(self) -> bytes: + """ + The hash of the issuer public key + """ + + @property + @abc.abstractmethod + def issuer_name_hash(self) -> bytes: + """ + The hash of the issuer name + """ + + @property + @abc.abstractmethod + def hash_algorithm(self) -> hashes.HashAlgorithm: + """ + The hash algorithm used in the issuer name and key hashes + """ + + @property + @abc.abstractmethod + def serial_number(self) -> int: + """ + The serial number of the cert whose status is being checked + """ + + @abc.abstractmethod + def public_bytes(self, encoding: serialization.Encoding) -> bytes: + """ + Serializes the request to DER + """ + + @property + @abc.abstractmethod + def extensions(self) -> x509.Extensions: + """ + The list of request extensions. Not single request extensions. + """ + + +class OCSPSingleResponse(metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def certificate_status(self) -> OCSPCertStatus: + """ + The status of the certificate (an element from the OCSPCertStatus enum) + """ + + @property + @abc.abstractmethod + def revocation_time(self) -> datetime.datetime | None: + """ + The date of when the certificate was revoked or None if not + revoked. + """ + + @property + @abc.abstractmethod + def revocation_reason(self) -> x509.ReasonFlags | None: + """ + The reason the certificate was revoked or None if not specified or + not revoked. + """ + + @property + @abc.abstractmethod + def this_update(self) -> datetime.datetime: + """ + The most recent time at which the status being indicated is known by + the responder to have been correct + """ + + @property + @abc.abstractmethod + def next_update(self) -> datetime.datetime | None: + """ + The time when newer information will be available + """ + + @property + @abc.abstractmethod + def issuer_key_hash(self) -> bytes: + """ + The hash of the issuer public key + """ + + @property + @abc.abstractmethod + def issuer_name_hash(self) -> bytes: + """ + The hash of the issuer name + """ + + @property + @abc.abstractmethod + def hash_algorithm(self) -> hashes.HashAlgorithm: + """ + The hash algorithm used in the issuer name and key hashes + """ + + @property + @abc.abstractmethod + def serial_number(self) -> int: + """ + The serial number of the cert whose status is being checked + """ + + +class OCSPResponse(metaclass=abc.ABCMeta): + @property + @abc.abstractmethod + def responses(self) -> typing.Iterator[OCSPSingleResponse]: + """ + An iterator over the individual SINGLERESP structures in the + response + """ + + @property + @abc.abstractmethod + def response_status(self) -> OCSPResponseStatus: + """ + The status of the response. This is a value from the OCSPResponseStatus + enumeration + """ + + @property + @abc.abstractmethod + def signature_algorithm_oid(self) -> x509.ObjectIdentifier: + """ + The ObjectIdentifier of the signature algorithm + """ + + @property + @abc.abstractmethod + def signature_hash_algorithm( + self, + ) -> hashes.HashAlgorithm | None: + """ + Returns a HashAlgorithm corresponding to the type of the digest signed + """ + + @property + @abc.abstractmethod + def signature(self) -> bytes: + """ + The signature bytes + """ + + @property + @abc.abstractmethod + def tbs_response_bytes(self) -> bytes: + """ + The tbsResponseData bytes + """ + + @property + @abc.abstractmethod + def certificates(self) -> list[x509.Certificate]: + """ + A list of certificates used to help build a chain to verify the OCSP + response. This situation occurs when the OCSP responder uses a delegate + certificate. + """ + + @property + @abc.abstractmethod + def responder_key_hash(self) -> bytes | None: + """ + The responder's key hash or None + """ + + @property + @abc.abstractmethod + def responder_name(self) -> x509.Name | None: + """ + The responder's Name or None + """ + + @property + @abc.abstractmethod + def produced_at(self) -> datetime.datetime: + """ + The time the response was produced + """ + + @property + @abc.abstractmethod + def certificate_status(self) -> OCSPCertStatus: + """ + The status of the certificate (an element from the OCSPCertStatus enum) + """ + + @property + @abc.abstractmethod + def revocation_time(self) -> datetime.datetime | None: + """ + The date of when the certificate was revoked or None if not + revoked. + """ + + @property + @abc.abstractmethod + def revocation_reason(self) -> x509.ReasonFlags | None: + """ + The reason the certificate was revoked or None if not specified or + not revoked. + """ + + @property + @abc.abstractmethod + def this_update(self) -> datetime.datetime: + """ + The most recent time at which the status being indicated is known by + the responder to have been correct + """ + + @property + @abc.abstractmethod + def next_update(self) -> datetime.datetime | None: + """ + The time when newer information will be available + """ + + @property + @abc.abstractmethod + def issuer_key_hash(self) -> bytes: + """ + The hash of the issuer public key + """ + + @property + @abc.abstractmethod + def issuer_name_hash(self) -> bytes: + """ + The hash of the issuer name + """ + + @property + @abc.abstractmethod + def hash_algorithm(self) -> hashes.HashAlgorithm: + """ + The hash algorithm used in the issuer name and key hashes + """ + + @property + @abc.abstractmethod + def serial_number(self) -> int: + """ + The serial number of the cert whose status is being checked + """ + + @property + @abc.abstractmethod + def extensions(self) -> x509.Extensions: + """ + The list of response extensions. Not single response extensions. + """ + + @property + @abc.abstractmethod + def single_extensions(self) -> x509.Extensions: + """ + The list of single response extensions. Not response extensions. + """ + + @abc.abstractmethod + def public_bytes(self, encoding: serialization.Encoding) -> bytes: + """ + Serializes the response to DER + """ + + +class OCSPRequestBuilder: + def __init__( + self, + request: tuple[ + x509.Certificate, x509.Certificate, hashes.HashAlgorithm + ] + | None = None, + request_hash: tuple[bytes, bytes, int, hashes.HashAlgorithm] + | None = None, + extensions: list[x509.Extension[x509.ExtensionType]] = [], + ) -> None: + self._request = request + self._request_hash = request_hash + self._extensions = extensions + + def add_certificate( + self, + cert: x509.Certificate, + issuer: x509.Certificate, + algorithm: hashes.HashAlgorithm, + ) -> OCSPRequestBuilder: + if self._request is not None or self._request_hash is not None: + raise ValueError("Only one certificate can be added to a request") + + _verify_algorithm(algorithm) + if not isinstance(cert, x509.Certificate) or not isinstance( + issuer, x509.Certificate + ): + raise TypeError("cert and issuer must be a Certificate") + + return OCSPRequestBuilder( + (cert, issuer, algorithm), self._request_hash, self._extensions + ) + + def add_certificate_by_hash( + self, + issuer_name_hash: bytes, + issuer_key_hash: bytes, + serial_number: int, + algorithm: hashes.HashAlgorithm, + ) -> OCSPRequestBuilder: + if self._request is not None or self._request_hash is not None: + raise ValueError("Only one certificate can be added to a request") + + if not isinstance(serial_number, int): + raise TypeError("serial_number must be an integer") + + _verify_algorithm(algorithm) + utils._check_bytes("issuer_name_hash", issuer_name_hash) + utils._check_bytes("issuer_key_hash", issuer_key_hash) + if algorithm.digest_size != len( + issuer_name_hash + ) or algorithm.digest_size != len(issuer_key_hash): + raise ValueError( + "issuer_name_hash and issuer_key_hash must be the same length " + "as the digest size of the algorithm" + ) + + return OCSPRequestBuilder( + self._request, + (issuer_name_hash, issuer_key_hash, serial_number, algorithm), + self._extensions, + ) + + def add_extension( + self, extval: x509.ExtensionType, critical: bool + ) -> OCSPRequestBuilder: + if not isinstance(extval, x509.ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = x509.Extension(extval.oid, critical, extval) + _reject_duplicate_extension(extension, self._extensions) + + return OCSPRequestBuilder( + self._request, self._request_hash, [*self._extensions, extension] + ) + + def build(self) -> OCSPRequest: + if self._request is None and self._request_hash is None: + raise ValueError("You must add a certificate before building") + + return ocsp.create_ocsp_request(self) + + +class OCSPResponseBuilder: + def __init__( + self, + response: _SingleResponse | None = None, + responder_id: tuple[x509.Certificate, OCSPResponderEncoding] + | None = None, + certs: list[x509.Certificate] | None = None, + extensions: list[x509.Extension[x509.ExtensionType]] = [], + ): + self._response = response + self._responder_id = responder_id + self._certs = certs + self._extensions = extensions + + def add_response( + self, + cert: x509.Certificate, + issuer: x509.Certificate, + algorithm: hashes.HashAlgorithm, + cert_status: OCSPCertStatus, + this_update: datetime.datetime, + next_update: datetime.datetime | None, + revocation_time: datetime.datetime | None, + revocation_reason: x509.ReasonFlags | None, + ) -> OCSPResponseBuilder: + if self._response is not None: + raise ValueError("Only one response per OCSPResponse.") + + singleresp = _SingleResponse( + cert, + issuer, + algorithm, + cert_status, + this_update, + next_update, + revocation_time, + revocation_reason, + ) + return OCSPResponseBuilder( + singleresp, + self._responder_id, + self._certs, + self._extensions, + ) + + def responder_id( + self, encoding: OCSPResponderEncoding, responder_cert: x509.Certificate + ) -> OCSPResponseBuilder: + if self._responder_id is not None: + raise ValueError("responder_id can only be set once") + if not isinstance(responder_cert, x509.Certificate): + raise TypeError("responder_cert must be a Certificate") + if not isinstance(encoding, OCSPResponderEncoding): + raise TypeError( + "encoding must be an element from OCSPResponderEncoding" + ) + + return OCSPResponseBuilder( + self._response, + (responder_cert, encoding), + self._certs, + self._extensions, + ) + + def certificates( + self, certs: typing.Iterable[x509.Certificate] + ) -> OCSPResponseBuilder: + if self._certs is not None: + raise ValueError("certificates may only be set once") + certs = list(certs) + if len(certs) == 0: + raise ValueError("certs must not be an empty list") + if not all(isinstance(x, x509.Certificate) for x in certs): + raise TypeError("certs must be a list of Certificates") + return OCSPResponseBuilder( + self._response, + self._responder_id, + certs, + self._extensions, + ) + + def add_extension( + self, extval: x509.ExtensionType, critical: bool + ) -> OCSPResponseBuilder: + if not isinstance(extval, x509.ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = x509.Extension(extval.oid, critical, extval) + _reject_duplicate_extension(extension, self._extensions) + + return OCSPResponseBuilder( + self._response, + self._responder_id, + self._certs, + [*self._extensions, extension], + ) + + def sign( + self, + private_key: CertificateIssuerPrivateKeyTypes, + algorithm: hashes.HashAlgorithm | None, + ) -> OCSPResponse: + if self._response is None: + raise ValueError("You must add a response before signing") + if self._responder_id is None: + raise ValueError("You must add a responder_id before signing") + + return ocsp.create_ocsp_response( + OCSPResponseStatus.SUCCESSFUL, self, private_key, algorithm + ) + + @classmethod + def build_unsuccessful( + cls, response_status: OCSPResponseStatus + ) -> OCSPResponse: + if not isinstance(response_status, OCSPResponseStatus): + raise TypeError( + "response_status must be an item from OCSPResponseStatus" + ) + if response_status is OCSPResponseStatus.SUCCESSFUL: + raise ValueError("response_status cannot be SUCCESSFUL") + + return ocsp.create_ocsp_response(response_status, None, None, None) + + +load_der_ocsp_request = ocsp.load_der_ocsp_request +load_der_ocsp_response = ocsp.load_der_ocsp_response diff --git a/.venv/Lib/site-packages/cryptography/x509/oid.py b/.venv/Lib/site-packages/cryptography/x509/oid.py new file mode 100644 index 00000000..cda50cce --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/x509/oid.py @@ -0,0 +1,33 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +from cryptography.hazmat._oid import ( + AttributeOID, + AuthorityInformationAccessOID, + CertificatePoliciesOID, + CRLEntryExtensionOID, + ExtendedKeyUsageOID, + ExtensionOID, + NameOID, + ObjectIdentifier, + OCSPExtensionOID, + SignatureAlgorithmOID, + SubjectInformationAccessOID, +) + +__all__ = [ + "AttributeOID", + "AuthorityInformationAccessOID", + "CRLEntryExtensionOID", + "CertificatePoliciesOID", + "ExtendedKeyUsageOID", + "ExtensionOID", + "NameOID", + "OCSPExtensionOID", + "ObjectIdentifier", + "SignatureAlgorithmOID", + "SubjectInformationAccessOID", +] diff --git a/.venv/Lib/site-packages/cryptography/x509/verification.py b/.venv/Lib/site-packages/cryptography/x509/verification.py new file mode 100644 index 00000000..ab1a37ae --- /dev/null +++ b/.venv/Lib/site-packages/cryptography/x509/verification.py @@ -0,0 +1,24 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import typing + +from cryptography.hazmat.bindings._rust import x509 as rust_x509 +from cryptography.x509.general_name import DNSName, IPAddress + +__all__ = [ + "Store", + "Subject", + "ServerVerifier", + "PolicyBuilder", + "VerificationError", +] + +Store = rust_x509.Store +Subject = typing.Union[DNSName, IPAddress] +ServerVerifier = rust_x509.ServerVerifier +PolicyBuilder = rust_x509.PolicyBuilder +VerificationError = rust_x509.VerificationError diff --git a/.venv/Lib/site-packages/dotenv/__init__.py b/.venv/Lib/site-packages/dotenv/__init__.py new file mode 100644 index 00000000..7f4c631b --- /dev/null +++ b/.venv/Lib/site-packages/dotenv/__init__.py @@ -0,0 +1,49 @@ +from typing import Any, Optional + +from .main import (dotenv_values, find_dotenv, get_key, load_dotenv, set_key, + unset_key) + + +def load_ipython_extension(ipython: Any) -> None: + from .ipython import load_ipython_extension + load_ipython_extension(ipython) + + +def get_cli_string( + path: Optional[str] = None, + action: Optional[str] = None, + key: Optional[str] = None, + value: Optional[str] = None, + quote: Optional[str] = None, +): + """Returns a string suitable for running as a shell script. + + Useful for converting a arguments passed to a fabric task + to be passed to a `local` or `run` command. + """ + command = ['dotenv'] + if quote: + command.append(f'-q {quote}') + if path: + command.append(f'-f {path}') + if action: + command.append(action) + if key: + command.append(key) + if value: + if ' ' in value: + command.append(f'"{value}"') + else: + command.append(value) + + return ' '.join(command).strip() + + +__all__ = ['get_cli_string', + 'load_dotenv', + 'dotenv_values', + 'get_key', + 'set_key', + 'unset_key', + 'find_dotenv', + 'load_ipython_extension'] diff --git a/.venv/Lib/site-packages/dotenv/__main__.py b/.venv/Lib/site-packages/dotenv/__main__.py new file mode 100644 index 00000000..3977f55a --- /dev/null +++ b/.venv/Lib/site-packages/dotenv/__main__.py @@ -0,0 +1,6 @@ +"""Entry point for cli, enables execution with `python -m dotenv`""" + +from .cli import cli + +if __name__ == "__main__": + cli() diff --git a/.venv/Lib/site-packages/dotenv/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/dotenv/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..76edf42013b50278fd09c0574b4f75cb95b8f9ba GIT binary patch literal 2030 zcmb_d&1)M+6rcTGX(icB6xXp6dx_;xrNjxC(ooz&Ng$!LD&*rLRMzXAk-f=&D6=b5 zhc)=%LkWh6USbFV(?i;jo(laxq$23DP%!kA+k$UC_07t1YCGXIwhWml;y zu3A^!Ts;SRk#JbTa#O_0rdZGC(D1<{SS38s&JQCYoIA$nkMY_uzHpRp=5cXTsuz|K zF8##Si&(ygs-th2|0a!e{GMeK*fTQycqr%i%HYuX+*2C_t1 zCZX|&tR z8pd2}Z4iJ(QCN_V0X9%9Uh5v6u{hBcC$>NBi8Fn1raPQ_V2%>8Wriz>Y+9`PiNJ~~ zWhGCf$89(Pi={dojLzz{2{mE$TISZJNTlPDv@^6h^2K~4zCbVe<8_SCf2McwjU*YxmQW}nD|E`B0heXIjC^?eTJrK$ie*lH0EC*nij_7aKZ z(yGezEM!Z|49+naWAGtBq8vC5WZ+mPx=ue}iW0jVEXOtm<)AtU+0QZf3t$7K<7jmJ zhld-tW2KNHPP!bcBhN}tOP%%Y2c7lKdQYA0tFv8oHdZvIpB?I>?fadm6ZOQt9b z_*1*|hjyu_Rr*?`D^}VoUzwnM(4m%*BK zelQA{3LMA9NbkOHrXt5pLFxZDPJ-Q_2W5Gg}u^g>fnZ-Oa7f(;VaSL+;Q`=4${8iUzKS Ku%WOgtJpuT?AI&+ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/dotenv/__pycache__/__main__.cpython-311.pyc b/.venv/Lib/site-packages/dotenv/__pycache__/__main__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..859d8966dab1fa1b218681bdedb977e82b58552d GIT binary patch literal 394 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/dotenv/__pycache__/ipython.cpython-311.pyc b/.venv/Lib/site-packages/dotenv/__pycache__/ipython.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3c2548afb04cbbb1985ca6cb0f05e188f4b597a0 GIT binary patch literal 2310 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 Ry11$2CoF1wJ-|ra{{{;40e1iZ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/dotenv/__pycache__/parser.cpython-311.pyc b/.venv/Lib/site-packages/dotenv/__pycache__/parser.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7a372982cf1e2b06678bd722279eb30602566784 GIT binary patch literal 11367 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 X)&h=4y07q)^{Yz%7)kF4h!Fk{rmdaW literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/dotenv/__pycache__/variables.cpython-311.pyc b/.venv/Lib/site-packages/dotenv/__pycache__/variables.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8a8be986a65e1dccd0369f4b190458a63ecf0d3c GIT binary patch literal 5528 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 X`GCX+W=2NF8+@V-+#p!Q0u%xOicvSw literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/dotenv/cli.py b/.venv/Lib/site-packages/dotenv/cli.py new file mode 100644 index 00000000..65ead461 --- /dev/null +++ b/.venv/Lib/site-packages/dotenv/cli.py @@ -0,0 +1,199 @@ +import json +import os +import shlex +import sys +from contextlib import contextmanager +from subprocess import Popen +from typing import Any, Dict, IO, Iterator, List + +try: + import click +except ImportError: + sys.stderr.write('It seems python-dotenv is not installed with cli option. \n' + 'Run pip install "python-dotenv[cli]" to fix this.') + sys.exit(1) + +from .main import dotenv_values, set_key, unset_key +from .version import __version__ + + +def enumerate_env(): + """ + Return a path for the ${pwd}/.env file. + + If pwd does not exist, return None. + """ + try: + cwd = os.getcwd() + except FileNotFoundError: + return None + path = os.path.join(cwd, '.env') + return path + + +@click.group() +@click.option('-f', '--file', default=enumerate_env(), + type=click.Path(file_okay=True), + help="Location of the .env file, defaults to .env file in current working directory.") +@click.option('-q', '--quote', default='always', + type=click.Choice(['always', 'never', 'auto']), + help="Whether to quote or not the variable values. Default mode is always. This does not affect parsing.") +@click.option('-e', '--export', default=False, + type=click.BOOL, + help="Whether to write the dot file as an executable bash script.") +@click.version_option(version=__version__) +@click.pass_context +def cli(ctx: click.Context, file: Any, quote: Any, export: Any) -> None: + """This script is used to set, get or unset values from a .env file.""" + ctx.obj = {'QUOTE': quote, 'EXPORT': export, 'FILE': file} + + +@contextmanager +def stream_file(path: os.PathLike) -> Iterator[IO[str]]: + """ + Open a file and yield the corresponding (decoded) stream. + + Exits with error code 2 if the file cannot be opened. + """ + + try: + with open(path) as stream: + yield stream + except OSError as exc: + print(f"Error opening env file: {exc}", file=sys.stderr) + exit(2) + + +@cli.command() +@click.pass_context +@click.option('--format', default='simple', + type=click.Choice(['simple', 'json', 'shell', 'export']), + help="The format in which to display the list. Default format is simple, " + "which displays name=value without quotes.") +def list(ctx: click.Context, format: bool) -> None: + """Display all the stored key/value.""" + file = ctx.obj['FILE'] + + with stream_file(file) as stream: + values = dotenv_values(stream=stream) + + if format == 'json': + click.echo(json.dumps(values, indent=2, sort_keys=True)) + else: + prefix = 'export ' if format == 'export' else '' + for k in sorted(values): + v = values[k] + if v is not None: + if format in ('export', 'shell'): + v = shlex.quote(v) + click.echo(f'{prefix}{k}={v}') + + +@cli.command() +@click.pass_context +@click.argument('key', required=True) +@click.argument('value', required=True) +def set(ctx: click.Context, key: Any, value: Any) -> None: + """Store the given key/value.""" + file = ctx.obj['FILE'] + quote = ctx.obj['QUOTE'] + export = ctx.obj['EXPORT'] + success, key, value = set_key(file, key, value, quote, export) + if success: + click.echo(f'{key}={value}') + else: + exit(1) + + +@cli.command() +@click.pass_context +@click.argument('key', required=True) +def get(ctx: click.Context, key: Any) -> None: + """Retrieve the value for the given key.""" + file = ctx.obj['FILE'] + + with stream_file(file) as stream: + values = dotenv_values(stream=stream) + + stored_value = values.get(key) + if stored_value: + click.echo(stored_value) + else: + exit(1) + + +@cli.command() +@click.pass_context +@click.argument('key', required=True) +def unset(ctx: click.Context, key: Any) -> None: + """Removes the given key.""" + file = ctx.obj['FILE'] + quote = ctx.obj['QUOTE'] + success, key = unset_key(file, key, quote) + if success: + click.echo(f"Successfully removed {key}") + else: + exit(1) + + +@cli.command(context_settings={'ignore_unknown_options': True}) +@click.pass_context +@click.option( + "--override/--no-override", + default=True, + help="Override variables from the environment file with those from the .env file.", +) +@click.argument('commandline', nargs=-1, type=click.UNPROCESSED) +def run(ctx: click.Context, override: bool, commandline: List[str]) -> None: + """Run command with environment variables present.""" + file = ctx.obj['FILE'] + if not os.path.isfile(file): + raise click.BadParameter( + f'Invalid value for \'-f\' "{file}" does not exist.', + ctx=ctx + ) + dotenv_as_dict = { + k: v + for (k, v) in dotenv_values(file).items() + if v is not None and (override or k not in os.environ) + } + + if not commandline: + click.echo('No command given.') + exit(1) + ret = run_command(commandline, dotenv_as_dict) + exit(ret) + + +def run_command(command: List[str], env: Dict[str, str]) -> int: + """Run command in sub process. + + Runs the command in a sub process with the variables from `env` + added in the current environment variables. + + Parameters + ---------- + command: List[str] + The command and it's parameters + env: Dict + The additional environment variables + + Returns + ------- + int + The return code of the command + + """ + # copy the current environment variables and add the vales from + # `env` + cmd_env = os.environ.copy() + cmd_env.update(env) + + p = Popen(command, + universal_newlines=True, + bufsize=0, + shell=False, + env=cmd_env) + _, _ = p.communicate() + + return p.returncode diff --git a/.venv/Lib/site-packages/dotenv/ipython.py b/.venv/Lib/site-packages/dotenv/ipython.py new file mode 100644 index 00000000..7df727cd --- /dev/null +++ b/.venv/Lib/site-packages/dotenv/ipython.py @@ -0,0 +1,39 @@ +from IPython.core.magic import Magics, line_magic, magics_class # type: ignore +from IPython.core.magic_arguments import (argument, magic_arguments, # type: ignore + parse_argstring) # type: ignore + +from .main import find_dotenv, load_dotenv + + +@magics_class +class IPythonDotEnv(Magics): + + @magic_arguments() + @argument( + '-o', '--override', action='store_true', + help="Indicate to override existing variables" + ) + @argument( + '-v', '--verbose', action='store_true', + help="Indicate function calls to be verbose" + ) + @argument('dotenv_path', nargs='?', type=str, default='.env', + help='Search in increasingly higher folders for the `dotenv_path`') + @line_magic + def dotenv(self, line): + args = parse_argstring(self.dotenv, line) + # Locate the .env file + dotenv_path = args.dotenv_path + try: + dotenv_path = find_dotenv(dotenv_path, True, True) + except IOError: + print("cannot find .env file") + return + + # Load the .env file + load_dotenv(dotenv_path, verbose=args.verbose, override=args.override) + + +def load_ipython_extension(ipython): + """Register the %dotenv magic.""" + ipython.register_magics(IPythonDotEnv) diff --git a/.venv/Lib/site-packages/dotenv/main.py b/.venv/Lib/site-packages/dotenv/main.py new file mode 100644 index 00000000..7bc54285 --- /dev/null +++ b/.venv/Lib/site-packages/dotenv/main.py @@ -0,0 +1,392 @@ +import io +import logging +import os +import pathlib +import shutil +import sys +import tempfile +from collections import OrderedDict +from contextlib import contextmanager +from typing import (IO, Dict, Iterable, Iterator, Mapping, Optional, Tuple, + Union) + +from .parser import Binding, parse_stream +from .variables import parse_variables + +# A type alias for a string path to be used for the paths in this file. +# These paths may flow to `open()` and `shutil.move()`; `shutil.move()` +# only accepts string paths, not byte paths or file descriptors. See +# https://github.com/python/typeshed/pull/6832. +StrPath = Union[str, 'os.PathLike[str]'] + +logger = logging.getLogger(__name__) + + +def with_warn_for_invalid_lines(mappings: Iterator[Binding]) -> Iterator[Binding]: + for mapping in mappings: + if mapping.error: + logger.warning( + "Python-dotenv could not parse statement starting at line %s", + mapping.original.line, + ) + yield mapping + + +class DotEnv: + def __init__( + self, + dotenv_path: Optional[StrPath], + stream: Optional[IO[str]] = None, + verbose: bool = False, + encoding: Optional[str] = None, + interpolate: bool = True, + override: bool = True, + ) -> None: + self.dotenv_path: Optional[StrPath] = dotenv_path + self.stream: Optional[IO[str]] = stream + self._dict: Optional[Dict[str, Optional[str]]] = None + self.verbose: bool = verbose + self.encoding: Optional[str] = encoding + self.interpolate: bool = interpolate + self.override: bool = override + + @contextmanager + def _get_stream(self) -> Iterator[IO[str]]: + if self.dotenv_path and os.path.isfile(self.dotenv_path): + with open(self.dotenv_path, encoding=self.encoding) as stream: + yield stream + elif self.stream is not None: + yield self.stream + else: + if self.verbose: + logger.info( + "Python-dotenv could not find configuration file %s.", + self.dotenv_path or '.env', + ) + yield io.StringIO('') + + def dict(self) -> Dict[str, Optional[str]]: + """Return dotenv as dict""" + if self._dict: + return self._dict + + raw_values = self.parse() + + if self.interpolate: + self._dict = OrderedDict(resolve_variables(raw_values, override=self.override)) + else: + self._dict = OrderedDict(raw_values) + + return self._dict + + def parse(self) -> Iterator[Tuple[str, Optional[str]]]: + with self._get_stream() as stream: + for mapping in with_warn_for_invalid_lines(parse_stream(stream)): + if mapping.key is not None: + yield mapping.key, mapping.value + + def set_as_environment_variables(self) -> bool: + """ + Load the current dotenv as system environment variable. + """ + if not self.dict(): + return False + + for k, v in self.dict().items(): + if k in os.environ and not self.override: + continue + if v is not None: + os.environ[k] = v + + return True + + def get(self, key: str) -> Optional[str]: + """ + """ + data = self.dict() + + if key in data: + return data[key] + + if self.verbose: + logger.warning("Key %s not found in %s.", key, self.dotenv_path) + + return None + + +def get_key( + dotenv_path: StrPath, + key_to_get: str, + encoding: Optional[str] = "utf-8", +) -> Optional[str]: + """ + Get the value of a given key from the given .env. + + Returns `None` if the key isn't found or doesn't have a value. + """ + return DotEnv(dotenv_path, verbose=True, encoding=encoding).get(key_to_get) + + +@contextmanager +def rewrite( + path: StrPath, + encoding: Optional[str], +) -> Iterator[Tuple[IO[str], IO[str]]]: + pathlib.Path(path).touch() + + with tempfile.NamedTemporaryFile(mode="w", encoding=encoding, delete=False) as dest: + error = None + try: + with open(path, encoding=encoding) as source: + yield (source, dest) + except BaseException as err: + error = err + + if error is None: + shutil.move(dest.name, path) + else: + os.unlink(dest.name) + raise error from None + + +def set_key( + dotenv_path: StrPath, + key_to_set: str, + value_to_set: str, + quote_mode: str = "always", + export: bool = False, + encoding: Optional[str] = "utf-8", +) -> Tuple[Optional[bool], str, str]: + """ + Adds or Updates a key/value to the given .env + + If the .env path given doesn't exist, fails instead of risking creating + an orphan .env somewhere in the filesystem + """ + if quote_mode not in ("always", "auto", "never"): + raise ValueError(f"Unknown quote_mode: {quote_mode}") + + quote = ( + quote_mode == "always" + or (quote_mode == "auto" and not value_to_set.isalnum()) + ) + + if quote: + value_out = "'{}'".format(value_to_set.replace("'", "\\'")) + else: + value_out = value_to_set + if export: + line_out = f'export {key_to_set}={value_out}\n' + else: + line_out = f"{key_to_set}={value_out}\n" + + with rewrite(dotenv_path, encoding=encoding) as (source, dest): + replaced = False + missing_newline = False + for mapping in with_warn_for_invalid_lines(parse_stream(source)): + if mapping.key == key_to_set: + dest.write(line_out) + replaced = True + else: + dest.write(mapping.original.string) + missing_newline = not mapping.original.string.endswith("\n") + if not replaced: + if missing_newline: + dest.write("\n") + dest.write(line_out) + + return True, key_to_set, value_to_set + + +def unset_key( + dotenv_path: StrPath, + key_to_unset: str, + quote_mode: str = "always", + encoding: Optional[str] = "utf-8", +) -> Tuple[Optional[bool], str]: + """ + Removes a given key from the given `.env` file. + + If the .env path given doesn't exist, fails. + If the given key doesn't exist in the .env, fails. + """ + if not os.path.exists(dotenv_path): + logger.warning("Can't delete from %s - it doesn't exist.", dotenv_path) + return None, key_to_unset + + removed = False + with rewrite(dotenv_path, encoding=encoding) as (source, dest): + for mapping in with_warn_for_invalid_lines(parse_stream(source)): + if mapping.key == key_to_unset: + removed = True + else: + dest.write(mapping.original.string) + + if not removed: + logger.warning("Key %s not removed from %s - key doesn't exist.", key_to_unset, dotenv_path) + return None, key_to_unset + + return removed, key_to_unset + + +def resolve_variables( + values: Iterable[Tuple[str, Optional[str]]], + override: bool, +) -> Mapping[str, Optional[str]]: + new_values: Dict[str, Optional[str]] = {} + + for (name, value) in values: + if value is None: + result = None + else: + atoms = parse_variables(value) + env: Dict[str, Optional[str]] = {} + if override: + env.update(os.environ) # type: ignore + env.update(new_values) + else: + env.update(new_values) + env.update(os.environ) # type: ignore + result = "".join(atom.resolve(env) for atom in atoms) + + new_values[name] = result + + return new_values + + +def _walk_to_root(path: str) -> Iterator[str]: + """ + Yield directories starting from the given directory up to the root + """ + if not os.path.exists(path): + raise IOError('Starting path not found') + + if os.path.isfile(path): + path = os.path.dirname(path) + + last_dir = None + current_dir = os.path.abspath(path) + while last_dir != current_dir: + yield current_dir + parent_dir = os.path.abspath(os.path.join(current_dir, os.path.pardir)) + last_dir, current_dir = current_dir, parent_dir + + +def find_dotenv( + filename: str = '.env', + raise_error_if_not_found: bool = False, + usecwd: bool = False, +) -> str: + """ + Search in increasingly higher folders for the given file + + Returns path to the file if found, or an empty string otherwise + """ + + def _is_interactive(): + """ Decide whether this is running in a REPL or IPython notebook """ + try: + main = __import__('__main__', None, None, fromlist=['__file__']) + except ModuleNotFoundError: + return False + return not hasattr(main, '__file__') + + if usecwd or _is_interactive() or getattr(sys, 'frozen', False): + # Should work without __file__, e.g. in REPL or IPython notebook. + path = os.getcwd() + else: + # will work for .py files + frame = sys._getframe() + current_file = __file__ + + while frame.f_code.co_filename == current_file or not os.path.exists( + frame.f_code.co_filename + ): + assert frame.f_back is not None + frame = frame.f_back + frame_filename = frame.f_code.co_filename + path = os.path.dirname(os.path.abspath(frame_filename)) + + for dirname in _walk_to_root(path): + check_path = os.path.join(dirname, filename) + if os.path.isfile(check_path): + return check_path + + if raise_error_if_not_found: + raise IOError('File not found') + + return '' + + +def load_dotenv( + dotenv_path: Optional[StrPath] = None, + stream: Optional[IO[str]] = None, + verbose: bool = False, + override: bool = False, + interpolate: bool = True, + encoding: Optional[str] = "utf-8", +) -> bool: + """Parse a .env file and then load all the variables found as environment variables. + + Parameters: + dotenv_path: Absolute or relative path to .env file. + stream: Text stream (such as `io.StringIO`) with .env content, used if + `dotenv_path` is `None`. + verbose: Whether to output a warning the .env file is missing. + override: Whether to override the system environment variables with the variables + from the `.env` file. + encoding: Encoding to be used to read the file. + Returns: + Bool: True if at least one environment variable is set else False + + If both `dotenv_path` and `stream` are `None`, `find_dotenv()` is used to find the + .env file. + """ + if dotenv_path is None and stream is None: + dotenv_path = find_dotenv() + + dotenv = DotEnv( + dotenv_path=dotenv_path, + stream=stream, + verbose=verbose, + interpolate=interpolate, + override=override, + encoding=encoding, + ) + return dotenv.set_as_environment_variables() + + +def dotenv_values( + dotenv_path: Optional[StrPath] = None, + stream: Optional[IO[str]] = None, + verbose: bool = False, + interpolate: bool = True, + encoding: Optional[str] = "utf-8", +) -> Dict[str, Optional[str]]: + """ + Parse a .env file and return its content as a dict. + + The returned dict will have `None` values for keys without values in the .env file. + For example, `foo=bar` results in `{"foo": "bar"}` whereas `foo` alone results in + `{"foo": None}` + + Parameters: + dotenv_path: Absolute or relative path to the .env file. + stream: `StringIO` object with .env content, used if `dotenv_path` is `None`. + verbose: Whether to output a warning if the .env file is missing. + encoding: Encoding to be used to read the file. + + If both `dotenv_path` and `stream` are `None`, `find_dotenv()` is used to find the + .env file. + """ + if dotenv_path is None and stream is None: + dotenv_path = find_dotenv() + + return DotEnv( + dotenv_path=dotenv_path, + stream=stream, + verbose=verbose, + interpolate=interpolate, + override=True, + encoding=encoding, + ).dict() diff --git a/.venv/Lib/site-packages/dotenv/parser.py b/.venv/Lib/site-packages/dotenv/parser.py new file mode 100644 index 00000000..735f14a3 --- /dev/null +++ b/.venv/Lib/site-packages/dotenv/parser.py @@ -0,0 +1,175 @@ +import codecs +import re +from typing import (IO, Iterator, Match, NamedTuple, Optional, # noqa:F401 + Pattern, Sequence, Tuple) + + +def make_regex(string: str, extra_flags: int = 0) -> Pattern[str]: + return re.compile(string, re.UNICODE | extra_flags) + + +_newline = make_regex(r"(\r\n|\n|\r)") +_multiline_whitespace = make_regex(r"\s*", extra_flags=re.MULTILINE) +_whitespace = make_regex(r"[^\S\r\n]*") +_export = make_regex(r"(?:export[^\S\r\n]+)?") +_single_quoted_key = make_regex(r"'([^']+)'") +_unquoted_key = make_regex(r"([^=\#\s]+)") +_equal_sign = make_regex(r"(=[^\S\r\n]*)") +_single_quoted_value = make_regex(r"'((?:\\'|[^'])*)'") +_double_quoted_value = make_regex(r'"((?:\\"|[^"])*)"') +_unquoted_value = make_regex(r"([^\r\n]*)") +_comment = make_regex(r"(?:[^\S\r\n]*#[^\r\n]*)?") +_end_of_line = make_regex(r"[^\S\r\n]*(?:\r\n|\n|\r|$)") +_rest_of_line = make_regex(r"[^\r\n]*(?:\r|\n|\r\n)?") +_double_quote_escapes = make_regex(r"\\[\\'\"abfnrtv]") +_single_quote_escapes = make_regex(r"\\[\\']") + + +class Original(NamedTuple): + string: str + line: int + + +class Binding(NamedTuple): + key: Optional[str] + value: Optional[str] + original: Original + error: bool + + +class Position: + def __init__(self, chars: int, line: int) -> None: + self.chars = chars + self.line = line + + @classmethod + def start(cls) -> "Position": + return cls(chars=0, line=1) + + def set(self, other: "Position") -> None: + self.chars = other.chars + self.line = other.line + + def advance(self, string: str) -> None: + self.chars += len(string) + self.line += len(re.findall(_newline, string)) + + +class Error(Exception): + pass + + +class Reader: + def __init__(self, stream: IO[str]) -> None: + self.string = stream.read() + self.position = Position.start() + self.mark = Position.start() + + def has_next(self) -> bool: + return self.position.chars < len(self.string) + + def set_mark(self) -> None: + self.mark.set(self.position) + + def get_marked(self) -> Original: + return Original( + string=self.string[self.mark.chars:self.position.chars], + line=self.mark.line, + ) + + def peek(self, count: int) -> str: + return self.string[self.position.chars:self.position.chars + count] + + def read(self, count: int) -> str: + result = self.string[self.position.chars:self.position.chars + count] + if len(result) < count: + raise Error("read: End of string") + self.position.advance(result) + return result + + def read_regex(self, regex: Pattern[str]) -> Sequence[str]: + match = regex.match(self.string, self.position.chars) + if match is None: + raise Error("read_regex: Pattern not found") + self.position.advance(self.string[match.start():match.end()]) + return match.groups() + + +def decode_escapes(regex: Pattern[str], string: str) -> str: + def decode_match(match: Match[str]) -> str: + return codecs.decode(match.group(0), 'unicode-escape') # type: ignore + + return regex.sub(decode_match, string) + + +def parse_key(reader: Reader) -> Optional[str]: + char = reader.peek(1) + if char == "#": + return None + elif char == "'": + (key,) = reader.read_regex(_single_quoted_key) + else: + (key,) = reader.read_regex(_unquoted_key) + return key + + +def parse_unquoted_value(reader: Reader) -> str: + (part,) = reader.read_regex(_unquoted_value) + return re.sub(r"\s+#.*", "", part).rstrip() + + +def parse_value(reader: Reader) -> str: + char = reader.peek(1) + if char == u"'": + (value,) = reader.read_regex(_single_quoted_value) + return decode_escapes(_single_quote_escapes, value) + elif char == u'"': + (value,) = reader.read_regex(_double_quoted_value) + return decode_escapes(_double_quote_escapes, value) + elif char in (u"", u"\n", u"\r"): + return u"" + else: + return parse_unquoted_value(reader) + + +def parse_binding(reader: Reader) -> Binding: + reader.set_mark() + try: + reader.read_regex(_multiline_whitespace) + if not reader.has_next(): + return Binding( + key=None, + value=None, + original=reader.get_marked(), + error=False, + ) + reader.read_regex(_export) + key = parse_key(reader) + reader.read_regex(_whitespace) + if reader.peek(1) == "=": + reader.read_regex(_equal_sign) + value: Optional[str] = parse_value(reader) + else: + value = None + reader.read_regex(_comment) + reader.read_regex(_end_of_line) + return Binding( + key=key, + value=value, + original=reader.get_marked(), + error=False, + ) + except Error: + reader.read_regex(_rest_of_line) + return Binding( + key=None, + value=None, + original=reader.get_marked(), + error=True, + ) + + +def parse_stream(stream: IO[str]) -> Iterator[Binding]: + reader = Reader(stream) + while reader.has_next(): + yield parse_binding(reader) diff --git a/.venv/Lib/site-packages/dotenv/py.typed b/.venv/Lib/site-packages/dotenv/py.typed new file mode 100644 index 00000000..7632ecf7 --- /dev/null +++ b/.venv/Lib/site-packages/dotenv/py.typed @@ -0,0 +1 @@ +# Marker file for PEP 561 diff --git a/.venv/Lib/site-packages/dotenv/variables.py b/.venv/Lib/site-packages/dotenv/variables.py new file mode 100644 index 00000000..667f2f26 --- /dev/null +++ b/.venv/Lib/site-packages/dotenv/variables.py @@ -0,0 +1,86 @@ +import re +from abc import ABCMeta, abstractmethod +from typing import Iterator, Mapping, Optional, Pattern + +_posix_variable: Pattern[str] = re.compile( + r""" + \$\{ + (?P[^\}:]*) + (?::- + (?P[^\}]*) + )? + \} + """, + re.VERBOSE, +) + + +class Atom(metaclass=ABCMeta): + def __ne__(self, other: object) -> bool: + result = self.__eq__(other) + if result is NotImplemented: + return NotImplemented + return not result + + @abstractmethod + def resolve(self, env: Mapping[str, Optional[str]]) -> str: ... + + +class Literal(Atom): + def __init__(self, value: str) -> None: + self.value = value + + def __repr__(self) -> str: + return f"Literal(value={self.value})" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, self.__class__): + return NotImplemented + return self.value == other.value + + def __hash__(self) -> int: + return hash((self.__class__, self.value)) + + def resolve(self, env: Mapping[str, Optional[str]]) -> str: + return self.value + + +class Variable(Atom): + def __init__(self, name: str, default: Optional[str]) -> None: + self.name = name + self.default = default + + def __repr__(self) -> str: + return f"Variable(name={self.name}, default={self.default})" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, self.__class__): + return NotImplemented + return (self.name, self.default) == (other.name, other.default) + + def __hash__(self) -> int: + return hash((self.__class__, self.name, self.default)) + + def resolve(self, env: Mapping[str, Optional[str]]) -> str: + default = self.default if self.default is not None else "" + result = env.get(self.name, default) + return result if result is not None else "" + + +def parse_variables(value: str) -> Iterator[Atom]: + cursor = 0 + + for match in _posix_variable.finditer(value): + (start, end) = match.span() + name = match["name"] + default = match["default"] + + if start > cursor: + yield Literal(value=value[cursor:start]) + + yield Variable(name=name, default=default) + cursor = end + + length = len(value) + if cursor < length: + yield Literal(value=value[cursor:length]) diff --git a/.venv/Lib/site-packages/dotenv/version.py b/.venv/Lib/site-packages/dotenv/version.py new file mode 100644 index 00000000..5c4105cd --- /dev/null +++ b/.venv/Lib/site-packages/dotenv/version.py @@ -0,0 +1 @@ +__version__ = "1.0.1" diff --git a/.venv/Lib/site-packages/pycparser-2.21.dist-info/INSTALLER b/.venv/Lib/site-packages/pycparser-2.21.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/.venv/Lib/site-packages/pycparser-2.21.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/Lib/site-packages/pycparser-2.21.dist-info/LICENSE b/.venv/Lib/site-packages/pycparser-2.21.dist-info/LICENSE new file mode 100644 index 00000000..ea215f2d --- /dev/null +++ b/.venv/Lib/site-packages/pycparser-2.21.dist-info/LICENSE @@ -0,0 +1,27 @@ +pycparser -- A C parser in Python + +Copyright (c) 2008-2020, Eli Bendersky +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* Neither the name of Eli Bendersky 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/.venv/Lib/site-packages/pycparser-2.21.dist-info/METADATA b/.venv/Lib/site-packages/pycparser-2.21.dist-info/METADATA new file mode 100644 index 00000000..1d0fbd65 --- /dev/null +++ b/.venv/Lib/site-packages/pycparser-2.21.dist-info/METADATA @@ -0,0 +1,31 @@ +Metadata-Version: 2.1 +Name: pycparser +Version: 2.21 +Summary: C parser in Python +Home-page: https://github.com/eliben/pycparser +Author: Eli Bendersky +Author-email: eliben@gmail.com +Maintainer: Eli Bendersky +License: BSD +Platform: Cross Platform +Classifier: Development Status :: 5 - Production/Stable +Classifier: License :: OSI Approved :: BSD License +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* + + +pycparser is a complete parser of the C language, written in +pure Python using the PLY parsing library. +It parses C code into an AST and can serve as a front-end for +C compilers or analysis tools. + + diff --git a/.venv/Lib/site-packages/pycparser-2.21.dist-info/RECORD b/.venv/Lib/site-packages/pycparser-2.21.dist-info/RECORD new file mode 100644 index 00000000..20497073 --- /dev/null +++ b/.venv/Lib/site-packages/pycparser-2.21.dist-info/RECORD @@ -0,0 +1,41 @@ +pycparser-2.21.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pycparser-2.21.dist-info/LICENSE,sha256=Pn3yW437ZYyakVAZMNTZQ7BQh6g0fH4rQyVhavU1BHs,1536 +pycparser-2.21.dist-info/METADATA,sha256=GvTEQA9yKj0nvP4mknfoGpMvjaJXCQjQANcQHrRrAxc,1108 +pycparser-2.21.dist-info/RECORD,, +pycparser-2.21.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 +pycparser-2.21.dist-info/top_level.txt,sha256=c-lPcS74L_8KoH7IE6PQF5ofyirRQNV4VhkbSFIPeWM,10 +pycparser/__init__.py,sha256=WUEp5D0fuHBH9Q8c1fYvR2eKWfj-CNghLf2MMlQLI1I,2815 +pycparser/__pycache__/__init__.cpython-311.pyc,, +pycparser/__pycache__/_ast_gen.cpython-311.pyc,, +pycparser/__pycache__/_build_tables.cpython-311.pyc,, +pycparser/__pycache__/ast_transforms.cpython-311.pyc,, +pycparser/__pycache__/c_ast.cpython-311.pyc,, +pycparser/__pycache__/c_generator.cpython-311.pyc,, +pycparser/__pycache__/c_lexer.cpython-311.pyc,, +pycparser/__pycache__/c_parser.cpython-311.pyc,, +pycparser/__pycache__/lextab.cpython-311.pyc,, +pycparser/__pycache__/plyparser.cpython-311.pyc,, +pycparser/__pycache__/yacctab.cpython-311.pyc,, +pycparser/_ast_gen.py,sha256=0JRVnDW-Jw-3IjVlo8je9rbAcp6Ko7toHAnB5zi7h0Q,10555 +pycparser/_build_tables.py,sha256=oZCd3Plhq-vkV-QuEsaahcf-jUI6-HgKsrAL9gvFzuU,1039 +pycparser/_c_ast.cfg,sha256=ld5ezE9yzIJFIVAUfw7ezJSlMi4nXKNCzfmqjOyQTNo,4255 +pycparser/ast_transforms.py,sha256=GTMYlUgWmXd5wJVyovXY1qzzAqjxzCpVVg0664dKGBs,5691 +pycparser/c_ast.py,sha256=HWeOrfYdCY0u5XaYhE1i60uVyE3yMWdcxzECUX-DqJw,31445 +pycparser/c_generator.py,sha256=yi6Mcqxv88J5ue8k5-mVGxh3iJ37iD4QyF-sWcGjC-8,17772 +pycparser/c_lexer.py,sha256=xCpjIb6vOUebBJpdifidb08y7XgAsO3T1gNGXJT93-w,17167 +pycparser/c_parser.py,sha256=_8y3i52bL6SUK21KmEEl0qzHxe-0eZRzjZGkWg8gQ4A,73680 +pycparser/lextab.py,sha256=fIxBAHYRC418oKF52M7xb8_KMj3K-tHx0TzZiKwxjPM,8504 +pycparser/ply/__init__.py,sha256=q4s86QwRsYRa20L9ueSxfh-hPihpftBjDOvYa2_SS2Y,102 +pycparser/ply/__pycache__/__init__.cpython-311.pyc,, +pycparser/ply/__pycache__/cpp.cpython-311.pyc,, +pycparser/ply/__pycache__/ctokens.cpython-311.pyc,, +pycparser/ply/__pycache__/lex.cpython-311.pyc,, +pycparser/ply/__pycache__/yacc.cpython-311.pyc,, +pycparser/ply/__pycache__/ygen.cpython-311.pyc,, +pycparser/ply/cpp.py,sha256=UtC3ylTWp5_1MKA-PLCuwKQR8zSOnlGuGGIdzj8xS98,33282 +pycparser/ply/ctokens.py,sha256=MKksnN40TehPhgVfxCJhjj_BjL943apreABKYz-bl0Y,3177 +pycparser/ply/lex.py,sha256=7Qol57x702HZwjA3ZLp-84CUEWq1EehW-N67Wzghi-M,42918 +pycparser/ply/yacc.py,sha256=eatSDkRLgRr6X3-hoDk_SQQv065R0BdL2K7fQ54CgVM,137323 +pycparser/ply/ygen.py,sha256=2JYNeYtrPz1JzLSLO3d4GsS8zJU8jY_I_CR1VI9gWrA,2251 +pycparser/plyparser.py,sha256=8tLOoEytcapvWrr1JfCf7Dog-wulBtS1YrDs8S7JfMo,4875 +pycparser/yacctab.py,sha256=j_fVNIyDWDRVk7eWMqQtlBw2AwUSV5JTrtT58l7zis0,205652 diff --git a/.venv/Lib/site-packages/pycparser-2.21.dist-info/WHEEL b/.venv/Lib/site-packages/pycparser-2.21.dist-info/WHEEL new file mode 100644 index 00000000..ef99c6cf --- /dev/null +++ b/.venv/Lib/site-packages/pycparser-2.21.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/.venv/Lib/site-packages/pycparser-2.21.dist-info/top_level.txt b/.venv/Lib/site-packages/pycparser-2.21.dist-info/top_level.txt new file mode 100644 index 00000000..dc1c9e10 --- /dev/null +++ b/.venv/Lib/site-packages/pycparser-2.21.dist-info/top_level.txt @@ -0,0 +1 @@ +pycparser diff --git a/.venv/Lib/site-packages/pycparser/__init__.py b/.venv/Lib/site-packages/pycparser/__init__.py new file mode 100644 index 00000000..d82eb2d6 --- /dev/null +++ b/.venv/Lib/site-packages/pycparser/__init__.py @@ -0,0 +1,90 @@ +#----------------------------------------------------------------- +# pycparser: __init__.py +# +# This package file exports some convenience functions for +# interacting with pycparser +# +# Eli Bendersky [https://eli.thegreenplace.net/] +# License: BSD +#----------------------------------------------------------------- +__all__ = ['c_lexer', 'c_parser', 'c_ast'] +__version__ = '2.21' + +import io +from subprocess import check_output +from .c_parser import CParser + + +def preprocess_file(filename, cpp_path='cpp', cpp_args=''): + """ Preprocess a file using cpp. + + filename: + Name of the file you want to preprocess. + + cpp_path: + cpp_args: + Refer to the documentation of parse_file for the meaning of these + arguments. + + When successful, returns the preprocessed file's contents. + Errors from cpp will be printed out. + """ + path_list = [cpp_path] + if isinstance(cpp_args, list): + path_list += cpp_args + elif cpp_args != '': + path_list += [cpp_args] + path_list += [filename] + + try: + # Note the use of universal_newlines to treat all newlines + # as \n for Python's purpose + text = check_output(path_list, universal_newlines=True) + except OSError as e: + raise RuntimeError("Unable to invoke 'cpp'. " + + 'Make sure its path was passed correctly\n' + + ('Original error: %s' % e)) + + return text + + +def parse_file(filename, use_cpp=False, cpp_path='cpp', cpp_args='', + parser=None): + """ Parse a C file using pycparser. + + filename: + Name of the file you want to parse. + + use_cpp: + Set to True if you want to execute the C pre-processor + on the file prior to parsing it. + + cpp_path: + If use_cpp is True, this is the path to 'cpp' on your + system. If no path is provided, it attempts to just + execute 'cpp', so it must be in your PATH. + + cpp_args: + If use_cpp is True, set this to the command line arguments strings + to cpp. Be careful with quotes - it's best to pass a raw string + (r'') here. For example: + r'-I../utils/fake_libc_include' + If several arguments are required, pass a list of strings. + + parser: + Optional parser object to be used instead of the default CParser + + When successful, an AST is returned. ParseError can be + thrown if the file doesn't parse successfully. + + Errors from cpp will be printed out. + """ + if use_cpp: + text = preprocess_file(filename, cpp_path, cpp_args) + else: + with io.open(filename) as f: + text = f.read() + + if parser is None: + parser = CParser() + return parser.parse(text, filename) diff --git a/.venv/Lib/site-packages/pycparser/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/pycparser/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b9ceb43803c12a66e4c283ed5fb9d6ffe6cf3f3b GIT binary patch literal 3231 zcma)8-)kJl9iP43y`MUrrP!^bD(VO&JzZ;`NlJq;BJSC)8_`B~Y=tyJu&j3HbZhVJ zUS?)>k~oEH>4OM`DkWgQ6igr71{Ycag}mxNkU$S&K@bRi$lDpGCHN)%es}Mu5x@DL`ZfmcVUwidSoOY?Cgkx5XS$7RTkc~ioslX@hX zJNBQ1P~9UfWnI}(CBE1#t%U431tSlk{ixsP$(GtmZ08BtQN6KN!dC7^*zx$f5rku^vZovnhS!b8} zBlutmMyOwz7^D& zCr#=29?lo7w-J%8`d|h&b!K`VyUEuSqD~9NYk@esJV`i9QRO|x^X*V9**4#Jn7U~)GH;! zbZ?d6Om){OZsGcb86;pJOsGk=DMN(`#EU{fpT2$V(yHa#um-E|_|@e%P3x{$y~XOR zzQ#Bc76TTmkJA%-zdB66w42$@9A_r>Zhbhj zJA;F@y_LiC_hC@W@6GQ`9ctfeFLtz)KL4*IIW>KM@w1l?3YQNHmyZgUceP#Z>yz9h z0?rSrlkuqzQKm0`o}YbCIn2NESWiqBACp93{wu6HB$1i_8cIin*YKVtW2f4`5Z?vP zpH5UXvae+;^XmTinaZ5HKc_?cx-}#L1cMq0(7&O90>mdr5{2(qVmrwpp=2B&eg->ARixmK+ZhT+F%GklL7ZA9BsiL)QQ`0ZF_ z?-xE?xUb!>9p;Khx#EFV6c~h0&Q!AMepaiDr}ifls7ncs--yxYM@hRr=q!~oVahN} z*ENhVXBhZR0-MS(_!QWOSrM#t#Vq<{;FvC=s7LF;F<76FCs30pl26kMb>9wL_69G) z7=C$*Uqc0PP?XMTlKas?_J?q_Q^(_{+qut4rXBr`$=t!{bxdA57`-~l8Rb-mj8<0^ Yaz(kO9Dir3qZSp&x&Ni&KL8g00X}_ShX4Qo literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/pycparser/__pycache__/_ast_gen.cpython-311.pyc b/.venv/Lib/site-packages/pycparser/__pycache__/_ast_gen.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..42498397381e33583d02ce212e864d4582d0a01f GIT binary patch literal 13454 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 avcFvn;F7wyb0hkiZ)f0ED}7jy^Zx+R86)HX literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/pycparser/__pycache__/_build_tables.cpython-311.pyc b/.venv/Lib/site-packages/pycparser/__pycache__/_build_tables.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7086bc0d1cd6f3b336cf6c370b9a30de7580f957 GIT binary patch literal 790 zcmY*WF>ljA6n zQpRjBb_znU@&ot>DT;)36A}}fQJFGv=QLIO-rc+J`M&qQJKv{LNds>4oo~3B0r)MF zrRC1R>5PL9K!Fk$44@K~+Y-V7SrYjUyq6k0zTIMq5D_4o9`ZAsimT0EKD=i- z9_{qn<_mAH`Pg<|h30eYVz-3>h7R@|H0wv$J2IbiT4vbk<87al>^6qxx#k_Kb=YyK z#rwM$*8Ra;ZFD_)=;Hlgoy&;#4Zrh{$b^vO29QFe36J&4n2rmP{7xO|qr0Q4Z%auI zNOcOgE{<5+m}(mz8zjw!SmU?&54>sAsQ>@~ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/pycparser/__pycache__/ast_transforms.cpython-311.pyc b/.venv/Lib/site-packages/pycparser/__pycache__/ast_transforms.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..66172b645f136053e9c89bd7089435ced01ce14f GIT binary patch literal 5544 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/pycparser/__pycache__/c_ast.cpython-311.pyc b/.venv/Lib/site-packages/pycparser/__pycache__/c_ast.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6e7fbbe44582e1d37a4bcd949a5e3c45ba6f8a98 GIT binary patch literal 53264 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 K9ZtN2u>TJd1izC2 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/pycparser/__pycache__/c_generator.cpython-311.pyc b/.venv/Lib/site-packages/pycparser/__pycache__/c_generator.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..30750e370cc85c8e066647fb776a89bdb2092bf3 GIT binary patch literal 30966 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/pycparser/__pycache__/c_lexer.cpython-311.pyc b/.venv/Lib/site-packages/pycparser/__pycache__/c_lexer.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a1e94ea46542a7b2051c0c673056ba8a883f72b6 GIT binary patch literal 18615 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 m$MEktQuM%m5GqH*py#P%M};l`_(@$O89 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%0AAw6`XzeO`Hj#ItU5}sr>KwTXi`DS7r zFERhdFF}|`(Js!2F|^mjmuD17L}(&m7xFZS)l8@?SyXso{dR8g8BoORNk&aJH&dAj zj;vGBHIBe!*Zwon2U&^CV5?a>*YeKQn^)td-+FWQ&6z7KsuqE?YrN~5zp_wzH*%*a z73Pq3Lj&=+ABDTa&J0*H(4}lMx5ZT-GnZ&yS#I=;CXgG3k4hsF4&K|F z@E=k9M}DEVn75SXPPehpbBOz7Y;*HOBhk8ok!UT#NQ6_5#B&LM zm*VgG)sBQ|%C-UJut*HLn?^^uCmaMO=NUmf@gVG8!657|Nk0ht6aH?+-~Fo{grPL> zByzCsX_V#`H#!(6HuTwsplt<1&{mBhkn@P*+VNylobvPM^ykw6iNRHyGHW1zn!DUU zd*ic%cFzhxyQeNavpKJ2y z1W1zzHsmW)V920gR>UAg>x=Yb8igBgU*jreTZ}|U_d1OP=x5M=3aR=r^451I{3jLv z$zMIR`&SNa7isGRb`qt7av9O|lL5Uo1E9BV0?@;$f&SdbgAC~XiogF?5A+i&2fAIb zI>DQy=4XQU?hN3)ds}*V@Bdh0@E%b71HXEB53C&CjHT#GjHcp@7<;K0-U{Zd_)Ji5 z%K++a&j9LjMQZWbjq!J9%+^`)uEq~7)squ#O#wACcyv@$6HIi?!9{m-XR>=TfW)3X z#AG+)Rn1H`lDXOP_an(prvRW}bqkVA!!s_?boA5V`!tbmZw8>=yWbt@{(fNCw_+G# zUa7VxNJ;>b4)&R-c3%bn+;=!VuRQQ^gz?Hj#Xp#eSE8kiLyzU)6Ru|Q{y_Vg!IL^t z8QvlLQ7q8kb+l(-u*=9hu~#zA#4t;R65}##yX$2%+?QcxS~a}0t2@KmLxacqyV^U4 zdQWz=_v-g>`k4kG-7@bH_;Jy1#K4bBl}=(zYA6wj1DPihrw=Aa`;ExGj@G0S_w@Dl z^mXZPXpDvV2>FA3C;Phw&j|2N4-KRT*%c2lJ;;8wk2ppG5Vl)!dgPSkgV||n#FNb4 zI+m|PYP{`3^~})|Y^{NsrYNT1J`HZeMGIfm*zJf!kUV>`r!y@aIaC47BPUN9cx8sQ z^;ay=ajZQv0-_A>fnz882Q%(SPhaMBdr$Tq&A8$2-jnT_H{E&i%#q&oXsCk^d9kN@ zyI#(?Hv>IK`?@k8o-=(bykTevfNW`fR__oe4$6$;rVDbIV6}RL%qE*N9BPeOFEa2; z6cuiD21!)x!!zIo%1&aLfzM75O|uouQ?<&kb^EZnOHs z^y=vuV2O1|qcw($-P|3ChEHYwt5?GO2QlQ|2pE#ts{eyf(oPS@xhACJS z!xwm7^m)545W_muK6vs(PluMa&R&Bp;11WF3DMUEwQ32x)!E zY&2ue;zDf53VAU$WW6>{@YAh$%(3#`kY=)%^NVO>9a^+~t`-|$C~O0aW&cx~tnoV> z?~MQs0Mv1^Zy+`6BfSX8xIG=|s+~RA3xy~RXM{N6L-GWesdwClnfjF}0W*tNf|-{v z(q=jB8r&=c<_VJn2@j3jk&9jmXO3F}plqgx7;XC+R)ewU2oQfkuB-Wq4k)_n_K8{V z;z3hBCBv;j`ELomN#)=P*3&qGSqmz&hvcdz9kUvu4F->}Jcjk)I>zI%%INbwjZN|P zALQQ7op1bMQM`ypL1(YbmEMfZUU>WZ%=LxFh4v4d7OGM)dfgVAL~pGlCWe*8JTlu@ zYU?7?I0>USj+m%*VFc9RK3kgJnHN28g)~M?vv4Qml!IkNq>;nib^1(u?*MB|-850Z zmk-IewQ=cV`5%lYVTLhFJa&#ym)ge2SpC~}={IO(p2aiNgyOl_YGl&dr}wW%A%XcoaJl{tm_8k!onrBDdQ9o{4GJE$4=)h2@T0P*aDr8#$@xK~>Jl zJnCF0w`NyDSg^ue9wJ&{E>&&-GkY&&3YiX;81=>&T{*kH#8BSUJz7%=!7)t`)J zze=ks$!!Mz*$rW?*Z2H;(NC0@|Sf6*%?iSSa7fPF2U2; z&8uVY=L*l0p9!A&OFKc4vRpnR6k9WbV(a(ap{U1_yHjH23Z3O`DWIn227mx&W<~&UJzLvW0$3B`W>X$h`|6%ZvX0 zgg;$OQ3vo58-N)=1?EQprGIc`0Zom?)d5t|ta~mcP}BRr4FJlWj&dLs`1WK3zCC|P z;M*#IuZ$=5#jh^NA7y>qzvw@e@Sjrrr&1|TI<0I7b^HmP{RD+Lg)y0PnO4*?dpqhWaA10#pbE4^Hwv=fz1lwqoWdmCS^hXJ z>$q#F1WPt9G=AtylJZ-Ta6DZucNNvz=z^z#T~BrVIl)> z4cH`3>Ub(GW0vF}TT#atN@(krVGf*^u|O^|y|592dP&pHwW+vjmEqBeaAwQAkd~j~ zG5m?<<~TN!^P-PuZyzU?FioKUDGJ~(!)0b96GF?qxV{1uZp{pZTmOPknC4%kK;Z{P ztHnhh9+ub4?qRbCYMkag^HCltVD)10S5PerYIBcFcYFk#B=X1i^ulS0GiO$s|y zmMZvIQj&#b9=a<_#S~wA%ODY9rg;kDTftMB^MhXpkgO;wPzkvhtO(rG`T3BF6S0_| zdBG`S11qHU-I>w)?q#C&_c*N= zvsH-g;>wxUt7fm<9HhDWDo0c|53?F}W-U*jc6#1-TcP8`-?V(Q+^G_KlZ zm2Ofla#>{>i0fIjQP1?J!JBMSO+km7Gq^K=ud z8kAKH@y4Z98x~h>z@`9LRvv4|V|T&BGo26owR25aguO7~-=_Gn;(GR~eVB7QTQFPj zNnN8-_sl{?qHeEJw|BOHt(mSq_(ApBcUR@~RRfOX!pDzV}|rp=a# z^K0pjiuumP>Xt-xi&EXPSk@i#+6Rp<oJk@*!vWoGSikwK!(wjdfgFUT^h=-u>Re*z_ zB3d9N!U?iW)DncX_8=GOpFOT;sGcT>lT^%$PCG!Hkkx=WLeR)@bXtg0*Z(wJwSFT> zGwr=RBZP)iz5v0)hLL+)nzQ)?c>)pNi^mp{a2(jy)C1ePp9YrJqcm%h?cdlxvwyj+ zelB>cbDphvxmezcKSO7P{JGUP-?mV(5V<#)s5_$69r^gm;_3dsiY%57;?JmQXGppy zWE2lJV})CuE;LSe=bOc|U~}q;RCU6VNl4?{)pzDZI?r#6*Wxy_KG;mz7gjxm7mSS% zTOWjZ!ED2XtTl5kBLcU=iU!te9W+4tiU!z0B0ATI)i;`;gxD8A^dD0Ehf>jFMv%8g zCOjrbP|0)x(TlpFNHW7vBxXPqKZYYxzNmPn59n9S+ z26J~G4W^y|ClJjO4=9AM*AlQ7pMvPycNzML1dW|5bQ0IO zs55FA6*(_pI^L7qxh?Sv&H#(K#y8Fc&mWnBg7rfo6Z+C2~ZJ4YGO<~E!bS9i)+7nl{4GKMO7 z?KC4W7%ikl}sf`rK)@cwgK74Q)#s+7?dV^CmXzS2keP zkOPYUKt@uZk}=F9Xk#B5^J>Y2d8J&1-#XG@Y(|*=de(SG>->YE2+Rj~rL#wXM*k2) zGh>oj2V_g%(ooqxm<6GG263$W10;yU!q7B8mz_~g)J5tRJ6j0H(ey;`vF=p zTLpXt{n`fFQjjlEJSVXYD4UmRn&%tmPbX@2DK)!3&BtpH2K*DdAO&7He7H2<2i^H3uHu#$gxG5_#Ge{CvcCj_DYk29F_XiT6+ zZa4-J*{6oBr;m%3iNx594(GZ8cW|-40e<5dBKVE7uLJx>%mrB@Z_$8e^>rJm!1N z7LWDXb<^9M-bB~JP5~g9W|I(eFwA~4VdI(}dxFd5Ifu8OoERC$ZW`&J@NM)+00q3; zSLuvRJ+K4AWR_Tf(faE|iOpzHakNPgtb3#?bUN%}4^o8*}Gx2jNZZHGG*g^~rEf{kEuG9WPtWD~z_#r*OXd#x3y%k_^ z8A)Zh&i7WJ)o=@<*Ha9uBUT1_kMy^99Pb*m%o}8;1g-ZKKx&}20EMuGJ6-8lZ#4+& zuhDgG+!!u!Y_c$p)5&aUWDIe$kujEh$``dptd4n+iB)hC%n|gDf_7OBUhBjXwS2W( zVsY5$XD?MIrGxKbo*k6sFu{%lC*N4x74vqd$GqL|qOI_6qdi8YYwG7tf4AyZRlM=t zHFIlbOKHP|*^2qH#gf*AteG67Qu`}zOwbOkSpKv9yScY=ZeUu{j>?IzhNdDQ8W6ZRWSTcWj>#q2AJ^9nI=!y|q---6%16uPv~ zLd=JFwH3b$Sx}EWOhwUOJ~@8#r94)K=5`b(By;;IHlRoU2FedKkDSsKKqkGaxytbVOM<<4Zqv1n1Kzp>V{-J+D^z}UMhmPU#)@(G2 z<&uhDWP2L7&A0ueA`#fD1okf09Klw}zI%iBx{Ye=h&c|pYnFU^Cb-}M94-MIsBkH| zj%_MCJzvbFspx-*y{zBKzL9sM7;oK!O6=7k{@L5+g{RI_Z`mq)CS&Hay!Ic{Yd?!; zvDdD|7Uf>Gn7jB9*00un-D_I*moNI)J<9e}ty%W3!y*4;Z`>y{77G$VHa>7c{w5XE z_z5;k?=8>L2{O-^Mu=T(bat66rnkaw9W+BFEdMrDd@pUh0ZU!3TKDu>sjjo;0v>KUt7M`qgV})z3L1Y3MrU;zSQ(v=K>HQjq-B=5 zCMX+*AJsackhvddOl=?ZRA?cVWlaSlcCKeoBZU5SG{@8dP1u)I-puDS zsOBQ~*FCee?wN(sh4#d{y~?`1iIROv$-d==b>w7%b1lGjy!$D)g#`-^xY5_ z!zv^;!q9>lYUl+9B3m=D86puRZ6C89VW6UvqlN?eMNijPj*GtxuNTy9^Q2T+GSvYq-iq%qSg^b}#=v@GqIm-YCp9h*e#qqa%~yk?<*c zP1*1rTGjZZkCxp^=J11|o6*fL*vcg@0?55JJ8XjdxQ z7ug@%%!`~Xs_Ku$bfNkmR{V!k`B;d%6Jb84g*;Mwrp##XX7B>#1sO)BF`VsLHinQb zrl;DR`8ldt+=A8wqxHHk<}+BtS5}L^%-23xjnq-!5TOA3nA^cGeZCY+G1Y$|nPx1Y zdCv9+xR7BJZ_Sf&i3W6IRivs|>U*@d^?SLH`ZhY*2d(j|_%`T&DSDq| z-l>SpOxZrIwy2w_@xJj8Q_!gE$%065WR!6RtAbX5t(v%-Fj{J;;OeP=M@auoJcGIL zXwF^ZQb}XHF@8ExvRNtF44XCJsjj;@1`m4s-KP1i3+wN-eKfULbs|x9La912Q)EnW z;CVUR_de6JT($BWBnc7VbSvL+PSsd4S|jBukzv6R^Pd^BNcnm^LG9f zhRCc{*oa>9g>{?9!SEV5PmdHCiNPEok%_h0J~V=6MrKY7F#mE$6AQG%*R8-orht zYdnu(0rgT0>pEO61~kL3pk=1K>N7VuUGq@=jpO%=8SjVnIp*GW)oqnP4BKMJhc*2Dv9u zD>fk3U<`;BY(omVju#>>X~!-&mAWAT!KU$Y-2Zw&e%sAe~7*M{MpD zDyH$1wpwP~@7L+tCsdG+nlFX&A8};z!6o6`H}Fs(EOQ9XrAjj~L|r@5cGQJhKihpH z20gyunFoBP%f^Ljr^%ez-g->lMgiwk{Vw>b>YkbDoUM8rj1imiZeH?lrcgk6HP4=z zJ^aq$n}-+6Hehy3$rfyMSptt2iiaCF{X8eDWJ@YGN|q^Oqql)?ziQkTrL~!=%=n9m zmyE^AUvs}h#D7Eb+uGrR;Y+R>fr+-A+Z1CJ=Jw?_v`fAd+XvJt`Xfy74JqFmodCUB z=EI54#Js|B6VK888B!6TSZw%UBy#r&agfO>(|tPskn;IIb95yI_p)#k?8XTKcpv}y z2XRLe9AS=m;=1=lt3}^rn3*{r?xpw-H^TDa30aLry&cIe6-Nr5hfoR*o3_#vtu#j_ z(vJ=?*1_0`x^^PtC#&ho+bHhj@Fh^bN+-Tc1!F|y*k~@YvYS4-9;4z*ROs9%nLh|F zM{CLQoPgiNRg=~B4pnCn%&+6fYNxq!DpLU55oANHdx%qwgGa)SLx#9MAMi7Cs$Z<8 z%+ClhyhKr*QdBp0WvM8zSQPltzUjV~x0U-+nfX=B&o#x4YB z?w4#@D%li|%y-|8EgVrc?^8BEe=n$Pej!oPu9URHAl%gLeOO+7zkJ(L`8IX?O}6B- zc?(W(!;0;+?eDYTh852~eD*nT!-@kloim;2TtzLm4z48bJGb}dD8AGriN(r}@142z zYxA88P4|5Fq(ps(Qs3dkqlsc|Nr#a5Of8T{}4)raYmQ%qN<=B(~6GfTh%3M^|Sizj;gEt6VeQ9nklV(s<&Xv zbhcbNgHe<3Q9JDzK2!P#jU^k;IviL9D;OG6<|Im|@I`lsYqtUdj=2!V+mOuSDve7v zo}Vw#sxAf#jiuVK>}jD<{lXCSKS|Bm`mZa!GYQc?=d5T#eGa<#6GbszWTNCY(cZbC>Zt#dMolA^c5U1&qN$J$$572sjyUc2djW-ZadkEHhGaKSSdTy^h2DQ+5qi?4!vqa`c7zoovB0UW{+^Sa zf}UjoLMrrOGXgYVnr8%PXMdC4IziC1y|wO^uqWRNE;Zy@iHuiFH;{ai@9P3nmVBry zxWp``FL5*Wq5J5c&GglUkXDnvsZFymfU6B}C78aHZ_b<*;(hF1N{|qHC>ZAEHc^i| zG{IbMkCm3I0rT0bH@DASp?^1bQNlV8 zs4tct{$Ay+hI!w-w9t94DN%b^sXgqR%w9ps>=l&EUa@T^{}Hy9!7KxEoXzK}!Ktes zZciTpHxgg)erEMZ#6t-x23)upXCc|zeWrnB2Ksit@>;GXujSf|jO5R0s!Vr!P-|H@ z4)3pzg2mqKlWE;YyBXjD=GJszZv6p)xtW2PoHkE1e?}M28Q7cMV#87e^y(T;#%{qfbTy4Xg11i5ur22gnW|o+G^jb3y0`Y&?zG8|2fc0eZX|uVh95*Bpx#&SElI`#LgU4-)pzj4-0xDCP4-e}a9! zlbcHAq>h;o7HG#)kIC_tAHAFg?Q{j2DJ}LaFK17kGtTkcV=^9W*f))nP_$Tl0Nquy z>ve5Ql-Vo`Y$d3LMBCi6 zNJ2L^dN>VY>D(_MgbZv))|A0y z3c{|>!k~0>k=VQ&CSeo=&+^llCxI3-V<0vhOln<`w zFvE|H{50T=N!7&iWH#u!c4N1TQ*(uV8IJS5e@o+h(qWt(^cE+w&wM`^dMje{k0lgl zvbT(^KAIknS+8JA2MBC|ZTl+x<}0clMEh#Y_-NofCcR!BqB*lX95g(N^h*i{>GWs! z=!PRf)JND{uOoW0e}`z)#-!oNH6A5;a*eZpOQ3E==fHsTJvHkw51{>a(+9pp^$w+a z$D;o^zCr6uWTAZ__+jV5-c(K=f+T|`Ef8acra5$`t-v3qb>RePNeC3GQ^c$@97|AB zWR|A;)Rp-4NHpTjLjs(c8y_B5}5mwfRh~H}b)^D`NkX=^RM>xT_*%nT) zT>3j2j&?pAg`V0vb;W?jcZ=qV;#cNNZ$}n<^H+cPR{Sk(T<*2s3;t>6M=c+n{`0nf zc0ASS=pKbp+vpg|l6f@1qXfLiZR!WLEV{Okes*c|v-e8xwI?U^=)n8eqI=8Y7?+LSAR+LU3v{vJ$B8PE88C{RH(EJcX0Ob#;w|v+=?E8}}}4 z+`Dk)USne8L1p8?g#UTP|9mQV>l*Eok^x&_(M=*)(tj=5u4cfJ`z|+nJP-!|8D=Rk z27|$}h27d3n#NK>nxo#8EwRz~YZ?ecCAy=og_+fJ!DTcMxp3$MSd$PcbF5Hqrh_-; zytMp0AD4LNeAE4{2bQ)TfLy+k*xIgaZBO`*DE=cEjmvM~C7y&m5pEk^{}fUpvoXqL z#^$*v7$ajWyL!RW(hu3sNGmahtxx_>j+(5?V3`7LPJ`82O@nnnCm-`*v9)KPWWaR4 z)31INJv;Shaq*P>d`-3kFT5#~@+GXy9pK z4r2>{i_ZTHqv`n>@k7;EQyr^?sFBR4?f$ldOWO|KJN=P2vF(Vm?Fh-( zP9|eJQ_5J~@$?$H;D%;4gd&*PJ`Tf;dZyU}qN5`acx?(^3_~l0&*|vN!IQKCI%nN3 zT-$ea0-L@#dz6saZf+IAQAljJUTY!X@4}mK;A>{H?|z_VDbRwH#?y(wJ|(a(;eS@~ zKbwkN33r$m<5e8E!qMGjXLS*Qlf94s{6mlxoYV~tkUP@f)qY%s8^h>n+^QSDIY;DB z@N&j5Gc7Z1fm!Pwf>|?K=P-M7uI>KX?MrL7&!1lKCf2qpYg-fk-HLzrKNM&+IzX%A zWZz&<-f8+I)A=@1HI))z+PlyD&}yYsOYQm|7IVV$$lgD9)g16olDI zs>dJO;fzg2t_^6h1Q)gg=fBXXE(S#Bzti;&V_4L!RA&xiW)W?FWA}2Fzo3-AAWSe? z!OXpb0HB$VJ7m@o08(zBBzhc(iyKN)#7Fn?kFmD6*)1C0D$=u2%iIzVVj3-{n7zlO zi23fc^Xg2BpP8dL%&`-f)fpGChJvY%sidxqAST|;=h3BZz>*)%m(tND&rJZ*+!vDH z1yp95+{<+CV~n%Q_Dr<ve%CBWYCJ+w@BV~u=XQ{G(0 z3FD_GE7(JFnin{Iy7mUP{tF`ImoTL&iXfNXm;ux1HX~;ni4mzQzk~sh|5qBrc8r3_ zv!M%2%3(5-vRgziWdy^bqTRLFHXtiey{%^RiKNhlAvUE53md+2stc+uH%+e*>P@5Q zlebXkZK2WCe4dYXf3(Vg38jc==f6Psr+XR{{|0V$#=94q?zeULgRVlz}R_^RM zn`zY(Cp$B(daC!#K&Ew1z*fn)a__*gp6pj$wZ{CZcloY4pWyLKfc8Va~Al zh7Olw8A!ONz^xHi6qQvIw-(e^P_ZzH1iwT-ph>|s)KwR5%_Et&TzE2Z>+>TPj+>UW ziOi88X1xzN1AUz*Pnk7Jb$9Mm^1z8*vxq_;>`r}RNwQ!tBvVgMPP(vc>=W-Sd7{ET z@y<1-3BlF8+I-8lpAH%(t=!1t416=tD+{G}BMYY&u6#K7;kksx9G?(<9s>{0XpncYN_|> zylOx&7@OgzL>=lOna+{40i=0AKf zQGQq{Km3&Jm}paA*eqh8#n{Zo^r|o*Vrd6)ECC|6i@)!#B>qE5@HpTA8r7r3CcQ8> zi5ly-yq}t2PC;4$cAC4Hl4;%2IvoJnnhKDuKPJ@D9V&VvtvB9y8&h)cZ`!xCY2Q8X zy_UqL=ao&*r{Cvq1x9dms~uIKjL>o<;mC!NHw48c16!kFa>$B!z@a*Ws_a+acSj;z z;kNt*9AxH8Gy87LzYOcboHmDAq7Ut!3qVLeVLFQS9Wv0Hm_ov}k|(&E-=f*3R*cpk z&#{!nucra9J}u)l?@UTF!D-A|Q;u2d9}&Lpz%$^}VcX=GlZ}`WaCc3@-=_H6QaS!~ zF7byM53m@UusH{_TqX)xR~>LqPO-RKZHOXfRQ_`pL>cHg*LAYnc2OTEQP&rbV*&L} z7Y3C<14He-JxBZS@N`XZT=^-$F1XLNNqx^F!jvke>4Y)6Q)0~SKOu}!y?`8J)YbGJ zR8-G--|4>DJs14e@!8`f5^rEtU+z&}#GTEW2Q?-ov{h$bnmWWS(o|tQAx)jWlY?n$^omskVddiU!j27QmJ$_qY%pK>2;(L< zIYv5G0^_Yt;)H~ZJThi+Z>R4*Vz_qU1TiB_;BvbDKhmo>2W@cWGYcBQ&77g2IqC)! zyX4iU?;CCeebGNvEHhf3#*66rH~DNcO2RY zI?r~9!XlggJ&J!%Dhky>K8uzzlkHE$`r$c*d>03Y@RogS%$+Bd(2Tg;=&cnDj=G|h zd~u4V;|dxRpDAjYPc5>1@fbU~I1D^*+tLK5k-x@U@OU!|>S;+S`Q6wXuOm1*%2_yz zH`~HF&SSqj&Dif=qOm`W=dxf9?T^Pt|AUSN@15?u-3!4#I6i+|-NmKz-XNca`se!- z{yxRumkJ+rAK+i0^~~@gMGmo5j60>IW*0otLb`(w zZR0=x;4V=`_@&dBIxE-e0-Zgn1rH&NBciCc^LTGcapBrTdw>7QmyihgS?;zx-&kK* zR5R4gTlB?5k_7`1d1^SKu`1YDdjU?ij&L&P!boUTGOr%tjJ<7Xu(xfQuvb+=ial8I zD9whfGdXN+B)-d#np(YwFFE-kSX{cvbvlb1#ml&%v}9TMRGqdiqMiv6Q^*z(@!nhk z;;DAclMTCJ+35H4^`Ds?La9oOIrYg0NvX_`5A8`al6(F)8c99}lBdaCpBvy2i0_`8 z7h({1qY3|h#lJrl=Yiv%3x5i&xDAt8hL|~pIem)w28%KCnbrToWguJ>ba4W_bwO

    `sveofk~Gam>Q=oiD_j5d1U+|R4SSl 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 SIZ=l{K!E9zE`B9ozN{*NO2Po!l-)5Xk; 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/pycparser/__pycache__/yacctab.cpython-311.pyc b/.venv/Lib/site-packages/pycparser/__pycache__/yacctab.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e7417b0097830783a9de3cdd914ee94eb303d17d GIT binary patch literal 193304 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: ') + else: + buf.write(lead + self.__class__.__name__+ ': ') + + if self.attr_names: + if attrnames: + nvlist = [(n, getattr(self,n)) for n in self.attr_names] + attrstr = ', '.join('%s=%s' % nv for nv in nvlist) + else: + vlist = [getattr(self, n) for n in self.attr_names] + attrstr = ', '.join('%s' % v for v in vlist) + buf.write(attrstr) + + if showcoord: + buf.write(' (at %s)' % self.coord) + buf.write('\n') + + for (child_name, child) in self.children(): + child.show( + buf, + offset=offset + 2, + attrnames=attrnames, + nodenames=nodenames, + showcoord=showcoord, + _my_node_name=child_name) + + +class NodeVisitor(object): + """ A base NodeVisitor class for visiting c_ast nodes. + Subclass it and define your own visit_XXX methods, where + XXX is the class name you want to visit with these + methods. + + For example: + + class ConstantVisitor(NodeVisitor): + def __init__(self): + self.values = [] + + def visit_Constant(self, node): + self.values.append(node.value) + + Creates a list of values of all the constant nodes + encountered below the given node. To use it: + + cv = ConstantVisitor() + cv.visit(node) + + Notes: + + * generic_visit() will be called for AST nodes for which + no visit_XXX method was defined. + * The children of nodes for which a visit_XXX was + defined will not be visited - if you need this, call + generic_visit() on the node. + You can use: + NodeVisitor.generic_visit(self, node) + * Modeled after Python's own AST visiting facilities + (the ast module of Python 3.0) + """ + + _method_cache = None + + def visit(self, node): + """ Visit a node. + """ + + if self._method_cache is None: + self._method_cache = {} + + visitor = self._method_cache.get(node.__class__.__name__, None) + if visitor is None: + method = 'visit_' + node.__class__.__name__ + visitor = getattr(self, method, self.generic_visit) + self._method_cache[node.__class__.__name__] = visitor + + return visitor(node) + + def generic_visit(self, node): + """ Called if no explicit visitor function exists for a + node. Implements preorder visiting of the node. + """ + for c in node: + self.visit(c) + +''' diff --git a/.venv/Lib/site-packages/pycparser/_build_tables.py b/.venv/Lib/site-packages/pycparser/_build_tables.py new file mode 100644 index 00000000..958381ad --- /dev/null +++ b/.venv/Lib/site-packages/pycparser/_build_tables.py @@ -0,0 +1,37 @@ +#----------------------------------------------------------------- +# pycparser: _build_tables.py +# +# A dummy for generating the lexing/parsing tables and and +# compiling them into .pyc for faster execution in optimized mode. +# Also generates AST code from the configuration file. +# Should be called from the pycparser directory. +# +# Eli Bendersky [https://eli.thegreenplace.net/] +# License: BSD +#----------------------------------------------------------------- + +# Insert '.' and '..' as first entries to the search path for modules. +# Restricted environments like embeddable python do not include the +# current working directory on startup. +import sys +sys.path[0:0] = ['.', '..'] + +# Generate c_ast.py +from _ast_gen import ASTCodeGenerator +ast_gen = ASTCodeGenerator('_c_ast.cfg') +ast_gen.generate(open('c_ast.py', 'w')) + +from pycparser import c_parser + +# Generates the tables +# +c_parser.CParser( + lex_optimize=True, + yacc_debug=False, + yacc_optimize=True) + +# Load to compile into .pyc +# +import lextab +import yacctab +import c_ast diff --git a/.venv/Lib/site-packages/pycparser/_c_ast.cfg b/.venv/Lib/site-packages/pycparser/_c_ast.cfg new file mode 100644 index 00000000..0626533e --- /dev/null +++ b/.venv/Lib/site-packages/pycparser/_c_ast.cfg @@ -0,0 +1,195 @@ +#----------------------------------------------------------------- +# pycparser: _c_ast.cfg +# +# Defines the AST Node classes used in pycparser. +# +# Each entry is a Node sub-class name, listing the attributes +# and child nodes of the class: +# * - a child node +# ** - a sequence of child nodes +# - an attribute +# +# Eli Bendersky [https://eli.thegreenplace.net/] +# License: BSD +#----------------------------------------------------------------- + +# ArrayDecl is a nested declaration of an array with the given type. +# dim: the dimension (for example, constant 42) +# dim_quals: list of dimension qualifiers, to support C99's allowing 'const' +# and 'static' within the array dimension in function declarations. +ArrayDecl: [type*, dim*, dim_quals] + +ArrayRef: [name*, subscript*] + +# op: =, +=, /= etc. +# +Assignment: [op, lvalue*, rvalue*] + +Alignas: [alignment*] + +BinaryOp: [op, left*, right*] + +Break: [] + +Case: [expr*, stmts**] + +Cast: [to_type*, expr*] + +# Compound statement in C99 is a list of block items (declarations or +# statements). +# +Compound: [block_items**] + +# Compound literal (anonymous aggregate) for C99. +# (type-name) {initializer_list} +# type: the typename +# init: InitList for the initializer list +# +CompoundLiteral: [type*, init*] + +# type: int, char, float, string, etc. +# +Constant: [type, value] + +Continue: [] + +# name: the variable being declared +# quals: list of qualifiers (const, volatile) +# funcspec: list function specifiers (i.e. inline in C99) +# storage: list of storage specifiers (extern, register, etc.) +# type: declaration type (probably nested with all the modifiers) +# init: initialization value, or None +# bitsize: bit field size, or None +# +Decl: [name, quals, align, storage, funcspec, type*, init*, bitsize*] + +DeclList: [decls**] + +Default: [stmts**] + +DoWhile: [cond*, stmt*] + +# Represents the ellipsis (...) parameter in a function +# declaration +# +EllipsisParam: [] + +# An empty statement (a semicolon ';' on its own) +# +EmptyStatement: [] + +# Enumeration type specifier +# name: an optional ID +# values: an EnumeratorList +# +Enum: [name, values*] + +# A name/value pair for enumeration values +# +Enumerator: [name, value*] + +# A list of enumerators +# +EnumeratorList: [enumerators**] + +# A list of expressions separated by the comma operator. +# +ExprList: [exprs**] + +# This is the top of the AST, representing a single C file (a +# translation unit in K&R jargon). It contains a list of +# "external-declaration"s, which is either declarations (Decl), +# Typedef or function definitions (FuncDef). +# +FileAST: [ext**] + +# for (init; cond; next) stmt +# +For: [init*, cond*, next*, stmt*] + +# name: Id +# args: ExprList +# +FuncCall: [name*, args*] + +# type (args) +# +FuncDecl: [args*, type*] + +# Function definition: a declarator for the function name and +# a body, which is a compound statement. +# There's an optional list of parameter declarations for old +# K&R-style definitions +# +FuncDef: [decl*, param_decls**, body*] + +Goto: [name] + +ID: [name] + +# Holder for types that are a simple identifier (e.g. the built +# ins void, char etc. and typedef-defined types) +# +IdentifierType: [names] + +If: [cond*, iftrue*, iffalse*] + +# An initialization list used for compound literals. +# +InitList: [exprs**] + +Label: [name, stmt*] + +# A named initializer for C99. +# The name of a NamedInitializer is a sequence of Nodes, because +# names can be hierarchical and contain constant expressions. +# +NamedInitializer: [name**, expr*] + +# a list of comma separated function parameter declarations +# +ParamList: [params**] + +PtrDecl: [quals, type*] + +Return: [expr*] + +StaticAssert: [cond*, message*] + +# name: struct tag name +# decls: declaration of members +# +Struct: [name, decls**] + +# type: . or -> +# name.field or name->field +# +StructRef: [name*, type, field*] + +Switch: [cond*, stmt*] + +# cond ? iftrue : iffalse +# +TernaryOp: [cond*, iftrue*, iffalse*] + +# A base type declaration +# +TypeDecl: [declname, quals, align, type*] + +# A typedef declaration. +# Very similar to Decl, but without some attributes +# +Typedef: [name, quals, storage, type*] + +Typename: [name, quals, align, type*] + +UnaryOp: [op, expr*] + +# name: union tag name +# decls: declaration of members +# +Union: [name, decls**] + +While: [cond*, stmt*] + +Pragma: [string] diff --git a/.venv/Lib/site-packages/pycparser/ast_transforms.py b/.venv/Lib/site-packages/pycparser/ast_transforms.py new file mode 100644 index 00000000..367dcf54 --- /dev/null +++ b/.venv/Lib/site-packages/pycparser/ast_transforms.py @@ -0,0 +1,164 @@ +#------------------------------------------------------------------------------ +# pycparser: ast_transforms.py +# +# Some utilities used by the parser to create a friendlier AST. +# +# Eli Bendersky [https://eli.thegreenplace.net/] +# License: BSD +#------------------------------------------------------------------------------ + +from . import c_ast + + +def fix_switch_cases(switch_node): + """ The 'case' statements in a 'switch' come out of parsing with one + child node, so subsequent statements are just tucked to the parent + Compound. Additionally, consecutive (fall-through) case statements + come out messy. This is a peculiarity of the C grammar. The following: + + switch (myvar) { + case 10: + k = 10; + p = k + 1; + return 10; + case 20: + case 30: + return 20; + default: + break; + } + + Creates this tree (pseudo-dump): + + Switch + ID: myvar + Compound: + Case 10: + k = 10 + p = k + 1 + return 10 + Case 20: + Case 30: + return 20 + Default: + break + + The goal of this transform is to fix this mess, turning it into the + following: + + Switch + ID: myvar + Compound: + Case 10: + k = 10 + p = k + 1 + return 10 + Case 20: + Case 30: + return 20 + Default: + break + + A fixed AST node is returned. The argument may be modified. + """ + assert isinstance(switch_node, c_ast.Switch) + if not isinstance(switch_node.stmt, c_ast.Compound): + return switch_node + + # The new Compound child for the Switch, which will collect children in the + # correct order + new_compound = c_ast.Compound([], switch_node.stmt.coord) + + # The last Case/Default node + last_case = None + + # Goes over the children of the Compound below the Switch, adding them + # either directly below new_compound or below the last Case as appropriate + # (for `switch(cond) {}`, block_items would have been None) + for child in (switch_node.stmt.block_items or []): + if isinstance(child, (c_ast.Case, c_ast.Default)): + # If it's a Case/Default: + # 1. Add it to the Compound and mark as "last case" + # 2. If its immediate child is also a Case or Default, promote it + # to a sibling. + new_compound.block_items.append(child) + _extract_nested_case(child, new_compound.block_items) + last_case = new_compound.block_items[-1] + else: + # Other statements are added as children to the last case, if it + # exists. + if last_case is None: + new_compound.block_items.append(child) + else: + last_case.stmts.append(child) + + switch_node.stmt = new_compound + return switch_node + + +def _extract_nested_case(case_node, stmts_list): + """ Recursively extract consecutive Case statements that are made nested + by the parser and add them to the stmts_list. + """ + if isinstance(case_node.stmts[0], (c_ast.Case, c_ast.Default)): + stmts_list.append(case_node.stmts.pop()) + _extract_nested_case(stmts_list[-1], stmts_list) + + +def fix_atomic_specifiers(decl): + """ Atomic specifiers like _Atomic(type) are unusually structured, + conferring a qualifier upon the contained type. + + This function fixes a decl with atomic specifiers to have a sane AST + structure, by removing spurious Typename->TypeDecl pairs and attaching + the _Atomic qualifier in the right place. + """ + # There can be multiple levels of _Atomic in a decl; fix them until a + # fixed point is reached. + while True: + decl, found = _fix_atomic_specifiers_once(decl) + if not found: + break + + # Make sure to add an _Atomic qual on the topmost decl if needed. Also + # restore the declname on the innermost TypeDecl (it gets placed in the + # wrong place during construction). + typ = decl + while not isinstance(typ, c_ast.TypeDecl): + try: + typ = typ.type + except AttributeError: + return decl + if '_Atomic' in typ.quals and '_Atomic' not in decl.quals: + decl.quals.append('_Atomic') + if typ.declname is None: + typ.declname = decl.name + + return decl + + +def _fix_atomic_specifiers_once(decl): + """ Performs one 'fix' round of atomic specifiers. + Returns (modified_decl, found) where found is True iff a fix was made. + """ + parent = decl + grandparent = None + node = decl.type + while node is not None: + if isinstance(node, c_ast.Typename) and '_Atomic' in node.quals: + break + try: + grandparent = parent + parent = node + node = node.type + except AttributeError: + # If we've reached a node without a `type` field, it means we won't + # find what we're looking for at this point; give up the search + # and return the original decl unmodified. + return decl, False + + assert isinstance(parent, c_ast.TypeDecl) + grandparent.type = node.type + if '_Atomic' not in node.type.quals: + node.type.quals.append('_Atomic') + return decl, True diff --git a/.venv/Lib/site-packages/pycparser/c_ast.py b/.venv/Lib/site-packages/pycparser/c_ast.py new file mode 100644 index 00000000..6575a2ad --- /dev/null +++ b/.venv/Lib/site-packages/pycparser/c_ast.py @@ -0,0 +1,1125 @@ +#----------------------------------------------------------------- +# ** ATTENTION ** +# This code was automatically generated from the file: +# _c_ast.cfg +# +# Do not modify it directly. Modify the configuration file and +# run the generator again. +# ** ** *** ** ** +# +# pycparser: c_ast.py +# +# AST Node classes. +# +# Eli Bendersky [https://eli.thegreenplace.net/] +# License: BSD +#----------------------------------------------------------------- + + +import sys + +def _repr(obj): + """ + Get the representation of an object, with dedicated pprint-like format for lists. + """ + if isinstance(obj, list): + return '[' + (',\n '.join((_repr(e).replace('\n', '\n ') for e in obj))) + '\n]' + else: + return repr(obj) + +class Node(object): + __slots__ = () + """ Abstract base class for AST nodes. + """ + def __repr__(self): + """ Generates a python representation of the current node + """ + result = self.__class__.__name__ + '(' + + indent = '' + separator = '' + for name in self.__slots__[:-2]: + result += separator + result += indent + result += name + '=' + (_repr(getattr(self, name)).replace('\n', '\n ' + (' ' * (len(name) + len(self.__class__.__name__))))) + + separator = ',' + indent = '\n ' + (' ' * len(self.__class__.__name__)) + + result += indent + ')' + + return result + + def children(self): + """ A sequence of all children that are Nodes + """ + pass + + def show(self, buf=sys.stdout, offset=0, attrnames=False, nodenames=False, showcoord=False, _my_node_name=None): + """ Pretty print the Node and all its attributes and + children (recursively) to a buffer. + + buf: + Open IO buffer into which the Node is printed. + + offset: + Initial offset (amount of leading spaces) + + attrnames: + True if you want to see the attribute names in + name=value pairs. False to only see the values. + + nodenames: + True if you want to see the actual node names + within their parents. + + showcoord: + Do you want the coordinates of each Node to be + displayed. + """ + lead = ' ' * offset + if nodenames and _my_node_name is not None: + buf.write(lead + self.__class__.__name__+ ' <' + _my_node_name + '>: ') + else: + buf.write(lead + self.__class__.__name__+ ': ') + + if self.attr_names: + if attrnames: + nvlist = [(n, getattr(self,n)) for n in self.attr_names] + attrstr = ', '.join('%s=%s' % nv for nv in nvlist) + else: + vlist = [getattr(self, n) for n in self.attr_names] + attrstr = ', '.join('%s' % v for v in vlist) + buf.write(attrstr) + + if showcoord: + buf.write(' (at %s)' % self.coord) + buf.write('\n') + + for (child_name, child) in self.children(): + child.show( + buf, + offset=offset + 2, + attrnames=attrnames, + nodenames=nodenames, + showcoord=showcoord, + _my_node_name=child_name) + + +class NodeVisitor(object): + """ A base NodeVisitor class for visiting c_ast nodes. + Subclass it and define your own visit_XXX methods, where + XXX is the class name you want to visit with these + methods. + + For example: + + class ConstantVisitor(NodeVisitor): + def __init__(self): + self.values = [] + + def visit_Constant(self, node): + self.values.append(node.value) + + Creates a list of values of all the constant nodes + encountered below the given node. To use it: + + cv = ConstantVisitor() + cv.visit(node) + + Notes: + + * generic_visit() will be called for AST nodes for which + no visit_XXX method was defined. + * The children of nodes for which a visit_XXX was + defined will not be visited - if you need this, call + generic_visit() on the node. + You can use: + NodeVisitor.generic_visit(self, node) + * Modeled after Python's own AST visiting facilities + (the ast module of Python 3.0) + """ + + _method_cache = None + + def visit(self, node): + """ Visit a node. + """ + + if self._method_cache is None: + self._method_cache = {} + + visitor = self._method_cache.get(node.__class__.__name__, None) + if visitor is None: + method = 'visit_' + node.__class__.__name__ + visitor = getattr(self, method, self.generic_visit) + self._method_cache[node.__class__.__name__] = visitor + + return visitor(node) + + def generic_visit(self, node): + """ Called if no explicit visitor function exists for a + node. Implements preorder visiting of the node. + """ + for c in node: + self.visit(c) + +class ArrayDecl(Node): + __slots__ = ('type', 'dim', 'dim_quals', 'coord', '__weakref__') + def __init__(self, type, dim, dim_quals, coord=None): + self.type = type + self.dim = dim + self.dim_quals = dim_quals + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + if self.dim is not None: nodelist.append(("dim", self.dim)) + return tuple(nodelist) + + def __iter__(self): + if self.type is not None: + yield self.type + if self.dim is not None: + yield self.dim + + attr_names = ('dim_quals', ) + +class ArrayRef(Node): + __slots__ = ('name', 'subscript', 'coord', '__weakref__') + def __init__(self, name, subscript, coord=None): + self.name = name + self.subscript = subscript + self.coord = coord + + def children(self): + nodelist = [] + if self.name is not None: nodelist.append(("name", self.name)) + if self.subscript is not None: nodelist.append(("subscript", self.subscript)) + return tuple(nodelist) + + def __iter__(self): + if self.name is not None: + yield self.name + if self.subscript is not None: + yield self.subscript + + attr_names = () + +class Assignment(Node): + __slots__ = ('op', 'lvalue', 'rvalue', 'coord', '__weakref__') + def __init__(self, op, lvalue, rvalue, coord=None): + self.op = op + self.lvalue = lvalue + self.rvalue = rvalue + self.coord = coord + + def children(self): + nodelist = [] + if self.lvalue is not None: nodelist.append(("lvalue", self.lvalue)) + if self.rvalue is not None: nodelist.append(("rvalue", self.rvalue)) + return tuple(nodelist) + + def __iter__(self): + if self.lvalue is not None: + yield self.lvalue + if self.rvalue is not None: + yield self.rvalue + + attr_names = ('op', ) + +class Alignas(Node): + __slots__ = ('alignment', 'coord', '__weakref__') + def __init__(self, alignment, coord=None): + self.alignment = alignment + self.coord = coord + + def children(self): + nodelist = [] + if self.alignment is not None: nodelist.append(("alignment", self.alignment)) + return tuple(nodelist) + + def __iter__(self): + if self.alignment is not None: + yield self.alignment + + attr_names = () + +class BinaryOp(Node): + __slots__ = ('op', 'left', 'right', 'coord', '__weakref__') + def __init__(self, op, left, right, coord=None): + self.op = op + self.left = left + self.right = right + self.coord = coord + + def children(self): + nodelist = [] + if self.left is not None: nodelist.append(("left", self.left)) + if self.right is not None: nodelist.append(("right", self.right)) + return tuple(nodelist) + + def __iter__(self): + if self.left is not None: + yield self.left + if self.right is not None: + yield self.right + + attr_names = ('op', ) + +class Break(Node): + __slots__ = ('coord', '__weakref__') + def __init__(self, coord=None): + self.coord = coord + + def children(self): + return () + + def __iter__(self): + return + yield + + attr_names = () + +class Case(Node): + __slots__ = ('expr', 'stmts', 'coord', '__weakref__') + def __init__(self, expr, stmts, coord=None): + self.expr = expr + self.stmts = stmts + self.coord = coord + + def children(self): + nodelist = [] + if self.expr is not None: nodelist.append(("expr", self.expr)) + for i, child in enumerate(self.stmts or []): + nodelist.append(("stmts[%d]" % i, child)) + return tuple(nodelist) + + def __iter__(self): + if self.expr is not None: + yield self.expr + for child in (self.stmts or []): + yield child + + attr_names = () + +class Cast(Node): + __slots__ = ('to_type', 'expr', 'coord', '__weakref__') + def __init__(self, to_type, expr, coord=None): + self.to_type = to_type + self.expr = expr + self.coord = coord + + def children(self): + nodelist = [] + if self.to_type is not None: nodelist.append(("to_type", self.to_type)) + if self.expr is not None: nodelist.append(("expr", self.expr)) + return tuple(nodelist) + + def __iter__(self): + if self.to_type is not None: + yield self.to_type + if self.expr is not None: + yield self.expr + + attr_names = () + +class Compound(Node): + __slots__ = ('block_items', 'coord', '__weakref__') + def __init__(self, block_items, coord=None): + self.block_items = block_items + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.block_items or []): + nodelist.append(("block_items[%d]" % i, child)) + return tuple(nodelist) + + def __iter__(self): + for child in (self.block_items or []): + yield child + + attr_names = () + +class CompoundLiteral(Node): + __slots__ = ('type', 'init', 'coord', '__weakref__') + def __init__(self, type, init, coord=None): + self.type = type + self.init = init + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + if self.init is not None: nodelist.append(("init", self.init)) + return tuple(nodelist) + + def __iter__(self): + if self.type is not None: + yield self.type + if self.init is not None: + yield self.init + + attr_names = () + +class Constant(Node): + __slots__ = ('type', 'value', 'coord', '__weakref__') + def __init__(self, type, value, coord=None): + self.type = type + self.value = value + self.coord = coord + + def children(self): + nodelist = [] + return tuple(nodelist) + + def __iter__(self): + return + yield + + attr_names = ('type', 'value', ) + +class Continue(Node): + __slots__ = ('coord', '__weakref__') + def __init__(self, coord=None): + self.coord = coord + + def children(self): + return () + + def __iter__(self): + return + yield + + attr_names = () + +class Decl(Node): + __slots__ = ('name', 'quals', 'align', 'storage', 'funcspec', 'type', 'init', 'bitsize', 'coord', '__weakref__') + def __init__(self, name, quals, align, storage, funcspec, type, init, bitsize, coord=None): + self.name = name + self.quals = quals + self.align = align + self.storage = storage + self.funcspec = funcspec + self.type = type + self.init = init + self.bitsize = bitsize + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + if self.init is not None: nodelist.append(("init", self.init)) + if self.bitsize is not None: nodelist.append(("bitsize", self.bitsize)) + return tuple(nodelist) + + def __iter__(self): + if self.type is not None: + yield self.type + if self.init is not None: + yield self.init + if self.bitsize is not None: + yield self.bitsize + + attr_names = ('name', 'quals', 'align', 'storage', 'funcspec', ) + +class DeclList(Node): + __slots__ = ('decls', 'coord', '__weakref__') + def __init__(self, decls, coord=None): + self.decls = decls + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.decls or []): + nodelist.append(("decls[%d]" % i, child)) + return tuple(nodelist) + + def __iter__(self): + for child in (self.decls or []): + yield child + + attr_names = () + +class Default(Node): + __slots__ = ('stmts', 'coord', '__weakref__') + def __init__(self, stmts, coord=None): + self.stmts = stmts + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.stmts or []): + nodelist.append(("stmts[%d]" % i, child)) + return tuple(nodelist) + + def __iter__(self): + for child in (self.stmts or []): + yield child + + attr_names = () + +class DoWhile(Node): + __slots__ = ('cond', 'stmt', 'coord', '__weakref__') + def __init__(self, cond, stmt, coord=None): + self.cond = cond + self.stmt = stmt + self.coord = coord + + def children(self): + nodelist = [] + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.stmt is not None: nodelist.append(("stmt", self.stmt)) + return tuple(nodelist) + + def __iter__(self): + if self.cond is not None: + yield self.cond + if self.stmt is not None: + yield self.stmt + + attr_names = () + +class EllipsisParam(Node): + __slots__ = ('coord', '__weakref__') + def __init__(self, coord=None): + self.coord = coord + + def children(self): + return () + + def __iter__(self): + return + yield + + attr_names = () + +class EmptyStatement(Node): + __slots__ = ('coord', '__weakref__') + def __init__(self, coord=None): + self.coord = coord + + def children(self): + return () + + def __iter__(self): + return + yield + + attr_names = () + +class Enum(Node): + __slots__ = ('name', 'values', 'coord', '__weakref__') + def __init__(self, name, values, coord=None): + self.name = name + self.values = values + self.coord = coord + + def children(self): + nodelist = [] + if self.values is not None: nodelist.append(("values", self.values)) + return tuple(nodelist) + + def __iter__(self): + if self.values is not None: + yield self.values + + attr_names = ('name', ) + +class Enumerator(Node): + __slots__ = ('name', 'value', 'coord', '__weakref__') + def __init__(self, name, value, coord=None): + self.name = name + self.value = value + self.coord = coord + + def children(self): + nodelist = [] + if self.value is not None: nodelist.append(("value", self.value)) + return tuple(nodelist) + + def __iter__(self): + if self.value is not None: + yield self.value + + attr_names = ('name', ) + +class EnumeratorList(Node): + __slots__ = ('enumerators', 'coord', '__weakref__') + def __init__(self, enumerators, coord=None): + self.enumerators = enumerators + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.enumerators or []): + nodelist.append(("enumerators[%d]" % i, child)) + return tuple(nodelist) + + def __iter__(self): + for child in (self.enumerators or []): + yield child + + attr_names = () + +class ExprList(Node): + __slots__ = ('exprs', 'coord', '__weakref__') + def __init__(self, exprs, coord=None): + self.exprs = exprs + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.exprs or []): + nodelist.append(("exprs[%d]" % i, child)) + return tuple(nodelist) + + def __iter__(self): + for child in (self.exprs or []): + yield child + + attr_names = () + +class FileAST(Node): + __slots__ = ('ext', 'coord', '__weakref__') + def __init__(self, ext, coord=None): + self.ext = ext + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.ext or []): + nodelist.append(("ext[%d]" % i, child)) + return tuple(nodelist) + + def __iter__(self): + for child in (self.ext or []): + yield child + + attr_names = () + +class For(Node): + __slots__ = ('init', 'cond', 'next', 'stmt', 'coord', '__weakref__') + def __init__(self, init, cond, next, stmt, coord=None): + self.init = init + self.cond = cond + self.next = next + self.stmt = stmt + self.coord = coord + + def children(self): + nodelist = [] + if self.init is not None: nodelist.append(("init", self.init)) + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.next is not None: nodelist.append(("next", self.next)) + if self.stmt is not None: nodelist.append(("stmt", self.stmt)) + return tuple(nodelist) + + def __iter__(self): + if self.init is not None: + yield self.init + if self.cond is not None: + yield self.cond + if self.next is not None: + yield self.next + if self.stmt is not None: + yield self.stmt + + attr_names = () + +class FuncCall(Node): + __slots__ = ('name', 'args', 'coord', '__weakref__') + def __init__(self, name, args, coord=None): + self.name = name + self.args = args + self.coord = coord + + def children(self): + nodelist = [] + if self.name is not None: nodelist.append(("name", self.name)) + if self.args is not None: nodelist.append(("args", self.args)) + return tuple(nodelist) + + def __iter__(self): + if self.name is not None: + yield self.name + if self.args is not None: + yield self.args + + attr_names = () + +class FuncDecl(Node): + __slots__ = ('args', 'type', 'coord', '__weakref__') + def __init__(self, args, type, coord=None): + self.args = args + self.type = type + self.coord = coord + + def children(self): + nodelist = [] + if self.args is not None: nodelist.append(("args", self.args)) + if self.type is not None: nodelist.append(("type", self.type)) + return tuple(nodelist) + + def __iter__(self): + if self.args is not None: + yield self.args + if self.type is not None: + yield self.type + + attr_names = () + +class FuncDef(Node): + __slots__ = ('decl', 'param_decls', 'body', 'coord', '__weakref__') + def __init__(self, decl, param_decls, body, coord=None): + self.decl = decl + self.param_decls = param_decls + self.body = body + self.coord = coord + + def children(self): + nodelist = [] + if self.decl is not None: nodelist.append(("decl", self.decl)) + if self.body is not None: nodelist.append(("body", self.body)) + for i, child in enumerate(self.param_decls or []): + nodelist.append(("param_decls[%d]" % i, child)) + return tuple(nodelist) + + def __iter__(self): + if self.decl is not None: + yield self.decl + if self.body is not None: + yield self.body + for child in (self.param_decls or []): + yield child + + attr_names = () + +class Goto(Node): + __slots__ = ('name', 'coord', '__weakref__') + def __init__(self, name, coord=None): + self.name = name + self.coord = coord + + def children(self): + nodelist = [] + return tuple(nodelist) + + def __iter__(self): + return + yield + + attr_names = ('name', ) + +class ID(Node): + __slots__ = ('name', 'coord', '__weakref__') + def __init__(self, name, coord=None): + self.name = name + self.coord = coord + + def children(self): + nodelist = [] + return tuple(nodelist) + + def __iter__(self): + return + yield + + attr_names = ('name', ) + +class IdentifierType(Node): + __slots__ = ('names', 'coord', '__weakref__') + def __init__(self, names, coord=None): + self.names = names + self.coord = coord + + def children(self): + nodelist = [] + return tuple(nodelist) + + def __iter__(self): + return + yield + + attr_names = ('names', ) + +class If(Node): + __slots__ = ('cond', 'iftrue', 'iffalse', 'coord', '__weakref__') + def __init__(self, cond, iftrue, iffalse, coord=None): + self.cond = cond + self.iftrue = iftrue + self.iffalse = iffalse + self.coord = coord + + def children(self): + nodelist = [] + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.iftrue is not None: nodelist.append(("iftrue", self.iftrue)) + if self.iffalse is not None: nodelist.append(("iffalse", self.iffalse)) + return tuple(nodelist) + + def __iter__(self): + if self.cond is not None: + yield self.cond + if self.iftrue is not None: + yield self.iftrue + if self.iffalse is not None: + yield self.iffalse + + attr_names = () + +class InitList(Node): + __slots__ = ('exprs', 'coord', '__weakref__') + def __init__(self, exprs, coord=None): + self.exprs = exprs + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.exprs or []): + nodelist.append(("exprs[%d]" % i, child)) + return tuple(nodelist) + + def __iter__(self): + for child in (self.exprs or []): + yield child + + attr_names = () + +class Label(Node): + __slots__ = ('name', 'stmt', 'coord', '__weakref__') + def __init__(self, name, stmt, coord=None): + self.name = name + self.stmt = stmt + self.coord = coord + + def children(self): + nodelist = [] + if self.stmt is not None: nodelist.append(("stmt", self.stmt)) + return tuple(nodelist) + + def __iter__(self): + if self.stmt is not None: + yield self.stmt + + attr_names = ('name', ) + +class NamedInitializer(Node): + __slots__ = ('name', 'expr', 'coord', '__weakref__') + def __init__(self, name, expr, coord=None): + self.name = name + self.expr = expr + self.coord = coord + + def children(self): + nodelist = [] + if self.expr is not None: nodelist.append(("expr", self.expr)) + for i, child in enumerate(self.name or []): + nodelist.append(("name[%d]" % i, child)) + return tuple(nodelist) + + def __iter__(self): + if self.expr is not None: + yield self.expr + for child in (self.name or []): + yield child + + attr_names = () + +class ParamList(Node): + __slots__ = ('params', 'coord', '__weakref__') + def __init__(self, params, coord=None): + self.params = params + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.params or []): + nodelist.append(("params[%d]" % i, child)) + return tuple(nodelist) + + def __iter__(self): + for child in (self.params or []): + yield child + + attr_names = () + +class PtrDecl(Node): + __slots__ = ('quals', 'type', 'coord', '__weakref__') + def __init__(self, quals, type, coord=None): + self.quals = quals + self.type = type + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + return tuple(nodelist) + + def __iter__(self): + if self.type is not None: + yield self.type + + attr_names = ('quals', ) + +class Return(Node): + __slots__ = ('expr', 'coord', '__weakref__') + def __init__(self, expr, coord=None): + self.expr = expr + self.coord = coord + + def children(self): + nodelist = [] + if self.expr is not None: nodelist.append(("expr", self.expr)) + return tuple(nodelist) + + def __iter__(self): + if self.expr is not None: + yield self.expr + + attr_names = () + +class StaticAssert(Node): + __slots__ = ('cond', 'message', 'coord', '__weakref__') + def __init__(self, cond, message, coord=None): + self.cond = cond + self.message = message + self.coord = coord + + def children(self): + nodelist = [] + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.message is not None: nodelist.append(("message", self.message)) + return tuple(nodelist) + + def __iter__(self): + if self.cond is not None: + yield self.cond + if self.message is not None: + yield self.message + + attr_names = () + +class Struct(Node): + __slots__ = ('name', 'decls', 'coord', '__weakref__') + def __init__(self, name, decls, coord=None): + self.name = name + self.decls = decls + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.decls or []): + nodelist.append(("decls[%d]" % i, child)) + return tuple(nodelist) + + def __iter__(self): + for child in (self.decls or []): + yield child + + attr_names = ('name', ) + +class StructRef(Node): + __slots__ = ('name', 'type', 'field', 'coord', '__weakref__') + def __init__(self, name, type, field, coord=None): + self.name = name + self.type = type + self.field = field + self.coord = coord + + def children(self): + nodelist = [] + if self.name is not None: nodelist.append(("name", self.name)) + if self.field is not None: nodelist.append(("field", self.field)) + return tuple(nodelist) + + def __iter__(self): + if self.name is not None: + yield self.name + if self.field is not None: + yield self.field + + attr_names = ('type', ) + +class Switch(Node): + __slots__ = ('cond', 'stmt', 'coord', '__weakref__') + def __init__(self, cond, stmt, coord=None): + self.cond = cond + self.stmt = stmt + self.coord = coord + + def children(self): + nodelist = [] + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.stmt is not None: nodelist.append(("stmt", self.stmt)) + return tuple(nodelist) + + def __iter__(self): + if self.cond is not None: + yield self.cond + if self.stmt is not None: + yield self.stmt + + attr_names = () + +class TernaryOp(Node): + __slots__ = ('cond', 'iftrue', 'iffalse', 'coord', '__weakref__') + def __init__(self, cond, iftrue, iffalse, coord=None): + self.cond = cond + self.iftrue = iftrue + self.iffalse = iffalse + self.coord = coord + + def children(self): + nodelist = [] + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.iftrue is not None: nodelist.append(("iftrue", self.iftrue)) + if self.iffalse is not None: nodelist.append(("iffalse", self.iffalse)) + return tuple(nodelist) + + def __iter__(self): + if self.cond is not None: + yield self.cond + if self.iftrue is not None: + yield self.iftrue + if self.iffalse is not None: + yield self.iffalse + + attr_names = () + +class TypeDecl(Node): + __slots__ = ('declname', 'quals', 'align', 'type', 'coord', '__weakref__') + def __init__(self, declname, quals, align, type, coord=None): + self.declname = declname + self.quals = quals + self.align = align + self.type = type + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + return tuple(nodelist) + + def __iter__(self): + if self.type is not None: + yield self.type + + attr_names = ('declname', 'quals', 'align', ) + +class Typedef(Node): + __slots__ = ('name', 'quals', 'storage', 'type', 'coord', '__weakref__') + def __init__(self, name, quals, storage, type, coord=None): + self.name = name + self.quals = quals + self.storage = storage + self.type = type + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + return tuple(nodelist) + + def __iter__(self): + if self.type is not None: + yield self.type + + attr_names = ('name', 'quals', 'storage', ) + +class Typename(Node): + __slots__ = ('name', 'quals', 'align', 'type', 'coord', '__weakref__') + def __init__(self, name, quals, align, type, coord=None): + self.name = name + self.quals = quals + self.align = align + self.type = type + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + return tuple(nodelist) + + def __iter__(self): + if self.type is not None: + yield self.type + + attr_names = ('name', 'quals', 'align', ) + +class UnaryOp(Node): + __slots__ = ('op', 'expr', 'coord', '__weakref__') + def __init__(self, op, expr, coord=None): + self.op = op + self.expr = expr + self.coord = coord + + def children(self): + nodelist = [] + if self.expr is not None: nodelist.append(("expr", self.expr)) + return tuple(nodelist) + + def __iter__(self): + if self.expr is not None: + yield self.expr + + attr_names = ('op', ) + +class Union(Node): + __slots__ = ('name', 'decls', 'coord', '__weakref__') + def __init__(self, name, decls, coord=None): + self.name = name + self.decls = decls + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.decls or []): + nodelist.append(("decls[%d]" % i, child)) + return tuple(nodelist) + + def __iter__(self): + for child in (self.decls or []): + yield child + + attr_names = ('name', ) + +class While(Node): + __slots__ = ('cond', 'stmt', 'coord', '__weakref__') + def __init__(self, cond, stmt, coord=None): + self.cond = cond + self.stmt = stmt + self.coord = coord + + def children(self): + nodelist = [] + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.stmt is not None: nodelist.append(("stmt", self.stmt)) + return tuple(nodelist) + + def __iter__(self): + if self.cond is not None: + yield self.cond + if self.stmt is not None: + yield self.stmt + + attr_names = () + +class Pragma(Node): + __slots__ = ('string', 'coord', '__weakref__') + def __init__(self, string, coord=None): + self.string = string + self.coord = coord + + def children(self): + nodelist = [] + return tuple(nodelist) + + def __iter__(self): + return + yield + + attr_names = ('string', ) + diff --git a/.venv/Lib/site-packages/pycparser/c_generator.py b/.venv/Lib/site-packages/pycparser/c_generator.py new file mode 100644 index 00000000..1057b2c6 --- /dev/null +++ b/.venv/Lib/site-packages/pycparser/c_generator.py @@ -0,0 +1,502 @@ +#------------------------------------------------------------------------------ +# pycparser: c_generator.py +# +# C code generator from pycparser AST nodes. +# +# Eli Bendersky [https://eli.thegreenplace.net/] +# License: BSD +#------------------------------------------------------------------------------ +from . import c_ast + + +class CGenerator(object): + """ Uses the same visitor pattern as c_ast.NodeVisitor, but modified to + return a value from each visit method, using string accumulation in + generic_visit. + """ + def __init__(self, reduce_parentheses=False): + """ Constructs C-code generator + + reduce_parentheses: + if True, eliminates needless parentheses on binary operators + """ + # Statements start with indentation of self.indent_level spaces, using + # the _make_indent method. + self.indent_level = 0 + self.reduce_parentheses = reduce_parentheses + + def _make_indent(self): + return ' ' * self.indent_level + + def visit(self, node): + method = 'visit_' + node.__class__.__name__ + return getattr(self, method, self.generic_visit)(node) + + def generic_visit(self, node): + if node is None: + return '' + else: + return ''.join(self.visit(c) for c_name, c in node.children()) + + def visit_Constant(self, n): + return n.value + + def visit_ID(self, n): + return n.name + + def visit_Pragma(self, n): + ret = '#pragma' + if n.string: + ret += ' ' + n.string + return ret + + def visit_ArrayRef(self, n): + arrref = self._parenthesize_unless_simple(n.name) + return arrref + '[' + self.visit(n.subscript) + ']' + + def visit_StructRef(self, n): + sref = self._parenthesize_unless_simple(n.name) + return sref + n.type + self.visit(n.field) + + def visit_FuncCall(self, n): + fref = self._parenthesize_unless_simple(n.name) + return fref + '(' + self.visit(n.args) + ')' + + def visit_UnaryOp(self, n): + if n.op == 'sizeof': + # Always parenthesize the argument of sizeof since it can be + # a name. + return 'sizeof(%s)' % self.visit(n.expr) + else: + operand = self._parenthesize_unless_simple(n.expr) + if n.op == 'p++': + return '%s++' % operand + elif n.op == 'p--': + return '%s--' % operand + else: + return '%s%s' % (n.op, operand) + + # Precedence map of binary operators: + precedence_map = { + # Should be in sync with c_parser.CParser.precedence + # Higher numbers are stronger binding + '||': 0, # weakest binding + '&&': 1, + '|': 2, + '^': 3, + '&': 4, + '==': 5, '!=': 5, + '>': 6, '>=': 6, '<': 6, '<=': 6, + '>>': 7, '<<': 7, + '+': 8, '-': 8, + '*': 9, '/': 9, '%': 9 # strongest binding + } + + def visit_BinaryOp(self, n): + # Note: all binary operators are left-to-right associative + # + # If `n.left.op` has a stronger or equally binding precedence in + # comparison to `n.op`, no parenthesis are needed for the left: + # e.g., `(a*b) + c` is equivalent to `a*b + c`, as well as + # `(a+b) - c` is equivalent to `a+b - c` (same precedence). + # If the left operator is weaker binding than the current, then + # parentheses are necessary: + # e.g., `(a+b) * c` is NOT equivalent to `a+b * c`. + lval_str = self._parenthesize_if( + n.left, + lambda d: not (self._is_simple_node(d) or + self.reduce_parentheses and isinstance(d, c_ast.BinaryOp) and + self.precedence_map[d.op] >= self.precedence_map[n.op])) + # If `n.right.op` has a stronger -but not equal- binding precedence, + # parenthesis can be omitted on the right: + # e.g., `a + (b*c)` is equivalent to `a + b*c`. + # If the right operator is weaker or equally binding, then parentheses + # are necessary: + # e.g., `a * (b+c)` is NOT equivalent to `a * b+c` and + # `a - (b+c)` is NOT equivalent to `a - b+c` (same precedence). + rval_str = self._parenthesize_if( + n.right, + lambda d: not (self._is_simple_node(d) or + self.reduce_parentheses and isinstance(d, c_ast.BinaryOp) and + self.precedence_map[d.op] > self.precedence_map[n.op])) + return '%s %s %s' % (lval_str, n.op, rval_str) + + def visit_Assignment(self, n): + rval_str = self._parenthesize_if( + n.rvalue, + lambda n: isinstance(n, c_ast.Assignment)) + return '%s %s %s' % (self.visit(n.lvalue), n.op, rval_str) + + def visit_IdentifierType(self, n): + return ' '.join(n.names) + + def _visit_expr(self, n): + if isinstance(n, c_ast.InitList): + return '{' + self.visit(n) + '}' + elif isinstance(n, c_ast.ExprList): + return '(' + self.visit(n) + ')' + else: + return self.visit(n) + + def visit_Decl(self, n, no_type=False): + # no_type is used when a Decl is part of a DeclList, where the type is + # explicitly only for the first declaration in a list. + # + s = n.name if no_type else self._generate_decl(n) + if n.bitsize: s += ' : ' + self.visit(n.bitsize) + if n.init: + s += ' = ' + self._visit_expr(n.init) + return s + + def visit_DeclList(self, n): + s = self.visit(n.decls[0]) + if len(n.decls) > 1: + s += ', ' + ', '.join(self.visit_Decl(decl, no_type=True) + for decl in n.decls[1:]) + return s + + def visit_Typedef(self, n): + s = '' + if n.storage: s += ' '.join(n.storage) + ' ' + s += self._generate_type(n.type) + return s + + def visit_Cast(self, n): + s = '(' + self._generate_type(n.to_type, emit_declname=False) + ')' + return s + ' ' + self._parenthesize_unless_simple(n.expr) + + def visit_ExprList(self, n): + visited_subexprs = [] + for expr in n.exprs: + visited_subexprs.append(self._visit_expr(expr)) + return ', '.join(visited_subexprs) + + def visit_InitList(self, n): + visited_subexprs = [] + for expr in n.exprs: + visited_subexprs.append(self._visit_expr(expr)) + return ', '.join(visited_subexprs) + + def visit_Enum(self, n): + return self._generate_struct_union_enum(n, name='enum') + + def visit_Alignas(self, n): + return '_Alignas({})'.format(self.visit(n.alignment)) + + def visit_Enumerator(self, n): + if not n.value: + return '{indent}{name},\n'.format( + indent=self._make_indent(), + name=n.name, + ) + else: + return '{indent}{name} = {value},\n'.format( + indent=self._make_indent(), + name=n.name, + value=self.visit(n.value), + ) + + def visit_FuncDef(self, n): + decl = self.visit(n.decl) + self.indent_level = 0 + body = self.visit(n.body) + if n.param_decls: + knrdecls = ';\n'.join(self.visit(p) for p in n.param_decls) + return decl + '\n' + knrdecls + ';\n' + body + '\n' + else: + return decl + '\n' + body + '\n' + + def visit_FileAST(self, n): + s = '' + for ext in n.ext: + if isinstance(ext, c_ast.FuncDef): + s += self.visit(ext) + elif isinstance(ext, c_ast.Pragma): + s += self.visit(ext) + '\n' + else: + s += self.visit(ext) + ';\n' + return s + + def visit_Compound(self, n): + s = self._make_indent() + '{\n' + self.indent_level += 2 + if n.block_items: + s += ''.join(self._generate_stmt(stmt) for stmt in n.block_items) + self.indent_level -= 2 + s += self._make_indent() + '}\n' + return s + + def visit_CompoundLiteral(self, n): + return '(' + self.visit(n.type) + '){' + self.visit(n.init) + '}' + + + def visit_EmptyStatement(self, n): + return ';' + + def visit_ParamList(self, n): + return ', '.join(self.visit(param) for param in n.params) + + def visit_Return(self, n): + s = 'return' + if n.expr: s += ' ' + self.visit(n.expr) + return s + ';' + + def visit_Break(self, n): + return 'break;' + + def visit_Continue(self, n): + return 'continue;' + + def visit_TernaryOp(self, n): + s = '(' + self._visit_expr(n.cond) + ') ? ' + s += '(' + self._visit_expr(n.iftrue) + ') : ' + s += '(' + self._visit_expr(n.iffalse) + ')' + return s + + def visit_If(self, n): + s = 'if (' + if n.cond: s += self.visit(n.cond) + s += ')\n' + s += self._generate_stmt(n.iftrue, add_indent=True) + if n.iffalse: + s += self._make_indent() + 'else\n' + s += self._generate_stmt(n.iffalse, add_indent=True) + return s + + def visit_For(self, n): + s = 'for (' + if n.init: s += self.visit(n.init) + s += ';' + if n.cond: s += ' ' + self.visit(n.cond) + s += ';' + if n.next: s += ' ' + self.visit(n.next) + s += ')\n' + s += self._generate_stmt(n.stmt, add_indent=True) + return s + + def visit_While(self, n): + s = 'while (' + if n.cond: s += self.visit(n.cond) + s += ')\n' + s += self._generate_stmt(n.stmt, add_indent=True) + return s + + def visit_DoWhile(self, n): + s = 'do\n' + s += self._generate_stmt(n.stmt, add_indent=True) + s += self._make_indent() + 'while (' + if n.cond: s += self.visit(n.cond) + s += ');' + return s + + def visit_StaticAssert(self, n): + s = '_Static_assert(' + s += self.visit(n.cond) + if n.message: + s += ',' + s += self.visit(n.message) + s += ')' + return s + + def visit_Switch(self, n): + s = 'switch (' + self.visit(n.cond) + ')\n' + s += self._generate_stmt(n.stmt, add_indent=True) + return s + + def visit_Case(self, n): + s = 'case ' + self.visit(n.expr) + ':\n' + for stmt in n.stmts: + s += self._generate_stmt(stmt, add_indent=True) + return s + + def visit_Default(self, n): + s = 'default:\n' + for stmt in n.stmts: + s += self._generate_stmt(stmt, add_indent=True) + return s + + def visit_Label(self, n): + return n.name + ':\n' + self._generate_stmt(n.stmt) + + def visit_Goto(self, n): + return 'goto ' + n.name + ';' + + def visit_EllipsisParam(self, n): + return '...' + + def visit_Struct(self, n): + return self._generate_struct_union_enum(n, 'struct') + + def visit_Typename(self, n): + return self._generate_type(n.type) + + def visit_Union(self, n): + return self._generate_struct_union_enum(n, 'union') + + def visit_NamedInitializer(self, n): + s = '' + for name in n.name: + if isinstance(name, c_ast.ID): + s += '.' + name.name + else: + s += '[' + self.visit(name) + ']' + s += ' = ' + self._visit_expr(n.expr) + return s + + def visit_FuncDecl(self, n): + return self._generate_type(n) + + def visit_ArrayDecl(self, n): + return self._generate_type(n, emit_declname=False) + + def visit_TypeDecl(self, n): + return self._generate_type(n, emit_declname=False) + + def visit_PtrDecl(self, n): + return self._generate_type(n, emit_declname=False) + + def _generate_struct_union_enum(self, n, name): + """ Generates code for structs, unions, and enums. name should be + 'struct', 'union', or 'enum'. + """ + if name in ('struct', 'union'): + members = n.decls + body_function = self._generate_struct_union_body + else: + assert name == 'enum' + members = None if n.values is None else n.values.enumerators + body_function = self._generate_enum_body + s = name + ' ' + (n.name or '') + if members is not None: + # None means no members + # Empty sequence means an empty list of members + s += '\n' + s += self._make_indent() + self.indent_level += 2 + s += '{\n' + s += body_function(members) + self.indent_level -= 2 + s += self._make_indent() + '}' + return s + + def _generate_struct_union_body(self, members): + return ''.join(self._generate_stmt(decl) for decl in members) + + def _generate_enum_body(self, members): + # `[:-2] + '\n'` removes the final `,` from the enumerator list + return ''.join(self.visit(value) for value in members)[:-2] + '\n' + + def _generate_stmt(self, n, add_indent=False): + """ Generation from a statement node. This method exists as a wrapper + for individual visit_* methods to handle different treatment of + some statements in this context. + """ + typ = type(n) + if add_indent: self.indent_level += 2 + indent = self._make_indent() + if add_indent: self.indent_level -= 2 + + if typ in ( + c_ast.Decl, c_ast.Assignment, c_ast.Cast, c_ast.UnaryOp, + c_ast.BinaryOp, c_ast.TernaryOp, c_ast.FuncCall, c_ast.ArrayRef, + c_ast.StructRef, c_ast.Constant, c_ast.ID, c_ast.Typedef, + c_ast.ExprList): + # These can also appear in an expression context so no semicolon + # is added to them automatically + # + return indent + self.visit(n) + ';\n' + elif typ in (c_ast.Compound,): + # No extra indentation required before the opening brace of a + # compound - because it consists of multiple lines it has to + # compute its own indentation. + # + return self.visit(n) + elif typ in (c_ast.If,): + return indent + self.visit(n) + else: + return indent + self.visit(n) + '\n' + + def _generate_decl(self, n): + """ Generation from a Decl node. + """ + s = '' + if n.funcspec: s = ' '.join(n.funcspec) + ' ' + if n.storage: s += ' '.join(n.storage) + ' ' + if n.align: s += self.visit(n.align[0]) + ' ' + s += self._generate_type(n.type) + return s + + def _generate_type(self, n, modifiers=[], emit_declname = True): + """ Recursive generation from a type node. n is the type node. + modifiers collects the PtrDecl, ArrayDecl and FuncDecl modifiers + encountered on the way down to a TypeDecl, to allow proper + generation from it. + """ + typ = type(n) + #~ print(n, modifiers) + + if typ == c_ast.TypeDecl: + s = '' + if n.quals: s += ' '.join(n.quals) + ' ' + s += self.visit(n.type) + + nstr = n.declname if n.declname and emit_declname else '' + # Resolve modifiers. + # Wrap in parens to distinguish pointer to array and pointer to + # function syntax. + # + for i, modifier in enumerate(modifiers): + if isinstance(modifier, c_ast.ArrayDecl): + if (i != 0 and + isinstance(modifiers[i - 1], c_ast.PtrDecl)): + nstr = '(' + nstr + ')' + nstr += '[' + if modifier.dim_quals: + nstr += ' '.join(modifier.dim_quals) + ' ' + nstr += self.visit(modifier.dim) + ']' + elif isinstance(modifier, c_ast.FuncDecl): + if (i != 0 and + isinstance(modifiers[i - 1], c_ast.PtrDecl)): + nstr = '(' + nstr + ')' + nstr += '(' + self.visit(modifier.args) + ')' + elif isinstance(modifier, c_ast.PtrDecl): + if modifier.quals: + nstr = '* %s%s' % (' '.join(modifier.quals), + ' ' + nstr if nstr else '') + else: + nstr = '*' + nstr + if nstr: s += ' ' + nstr + return s + elif typ == c_ast.Decl: + return self._generate_decl(n.type) + elif typ == c_ast.Typename: + return self._generate_type(n.type, emit_declname = emit_declname) + elif typ == c_ast.IdentifierType: + return ' '.join(n.names) + ' ' + elif typ in (c_ast.ArrayDecl, c_ast.PtrDecl, c_ast.FuncDecl): + return self._generate_type(n.type, modifiers + [n], + emit_declname = emit_declname) + else: + return self.visit(n) + + def _parenthesize_if(self, n, condition): + """ Visits 'n' and returns its string representation, parenthesized + if the condition function applied to the node returns True. + """ + s = self._visit_expr(n) + if condition(n): + return '(' + s + ')' + else: + return s + + def _parenthesize_unless_simple(self, n): + """ Common use case for _parenthesize_if + """ + return self._parenthesize_if(n, lambda d: not self._is_simple_node(d)) + + def _is_simple_node(self, n): + """ Returns True for nodes that are "simple" - i.e. nodes that always + have higher precedence than operators. + """ + return isinstance(n, (c_ast.Constant, c_ast.ID, c_ast.ArrayRef, + c_ast.StructRef, c_ast.FuncCall)) diff --git a/.venv/Lib/site-packages/pycparser/c_lexer.py b/.venv/Lib/site-packages/pycparser/c_lexer.py new file mode 100644 index 00000000..d68d8ebf --- /dev/null +++ b/.venv/Lib/site-packages/pycparser/c_lexer.py @@ -0,0 +1,554 @@ +#------------------------------------------------------------------------------ +# pycparser: c_lexer.py +# +# CLexer class: lexer for the C language +# +# Eli Bendersky [https://eli.thegreenplace.net/] +# License: BSD +#------------------------------------------------------------------------------ +import re + +from .ply import lex +from .ply.lex import TOKEN + + +class CLexer(object): + """ A lexer for the C language. After building it, set the + input text with input(), and call token() to get new + tokens. + + The public attribute filename can be set to an initial + filename, but the lexer will update it upon #line + directives. + """ + def __init__(self, error_func, on_lbrace_func, on_rbrace_func, + type_lookup_func): + """ Create a new Lexer. + + error_func: + An error function. Will be called with an error + message, line and column as arguments, in case of + an error during lexing. + + on_lbrace_func, on_rbrace_func: + Called when an LBRACE or RBRACE is encountered + (likely to push/pop type_lookup_func's scope) + + type_lookup_func: + A type lookup function. Given a string, it must + return True IFF this string is a name of a type + that was defined with a typedef earlier. + """ + self.error_func = error_func + self.on_lbrace_func = on_lbrace_func + self.on_rbrace_func = on_rbrace_func + self.type_lookup_func = type_lookup_func + self.filename = '' + + # Keeps track of the last token returned from self.token() + self.last_token = None + + # Allow either "# line" or "# " to support GCC's + # cpp output + # + self.line_pattern = re.compile(r'([ \t]*line\W)|([ \t]*\d+)') + self.pragma_pattern = re.compile(r'[ \t]*pragma\W') + + def build(self, **kwargs): + """ Builds the lexer from the specification. Must be + called after the lexer object is created. + + This method exists separately, because the PLY + manual warns against calling lex.lex inside + __init__ + """ + self.lexer = lex.lex(object=self, **kwargs) + + def reset_lineno(self): + """ Resets the internal line number counter of the lexer. + """ + self.lexer.lineno = 1 + + def input(self, text): + self.lexer.input(text) + + def token(self): + self.last_token = self.lexer.token() + return self.last_token + + def find_tok_column(self, token): + """ Find the column of the token in its line. + """ + last_cr = self.lexer.lexdata.rfind('\n', 0, token.lexpos) + return token.lexpos - last_cr + + ######################-- PRIVATE --###################### + + ## + ## Internal auxiliary methods + ## + def _error(self, msg, token): + location = self._make_tok_location(token) + self.error_func(msg, location[0], location[1]) + self.lexer.skip(1) + + def _make_tok_location(self, token): + return (token.lineno, self.find_tok_column(token)) + + ## + ## Reserved keywords + ## + keywords = ( + 'AUTO', 'BREAK', 'CASE', 'CHAR', 'CONST', + 'CONTINUE', 'DEFAULT', 'DO', 'DOUBLE', 'ELSE', 'ENUM', 'EXTERN', + 'FLOAT', 'FOR', 'GOTO', 'IF', 'INLINE', 'INT', 'LONG', + 'REGISTER', 'OFFSETOF', + 'RESTRICT', 'RETURN', 'SHORT', 'SIGNED', 'SIZEOF', 'STATIC', 'STRUCT', + 'SWITCH', 'TYPEDEF', 'UNION', 'UNSIGNED', 'VOID', + 'VOLATILE', 'WHILE', '__INT128', + ) + + keywords_new = ( + '_BOOL', '_COMPLEX', + '_NORETURN', '_THREAD_LOCAL', '_STATIC_ASSERT', + '_ATOMIC', '_ALIGNOF', '_ALIGNAS', + ) + + keyword_map = {} + + for keyword in keywords: + keyword_map[keyword.lower()] = keyword + + for keyword in keywords_new: + keyword_map[keyword[:2].upper() + keyword[2:].lower()] = keyword + + ## + ## All the tokens recognized by the lexer + ## + tokens = keywords + keywords_new + ( + # Identifiers + 'ID', + + # Type identifiers (identifiers previously defined as + # types with typedef) + 'TYPEID', + + # constants + 'INT_CONST_DEC', 'INT_CONST_OCT', 'INT_CONST_HEX', 'INT_CONST_BIN', 'INT_CONST_CHAR', + 'FLOAT_CONST', 'HEX_FLOAT_CONST', + 'CHAR_CONST', + 'WCHAR_CONST', + 'U8CHAR_CONST', + 'U16CHAR_CONST', + 'U32CHAR_CONST', + + # String literals + 'STRING_LITERAL', + 'WSTRING_LITERAL', + 'U8STRING_LITERAL', + 'U16STRING_LITERAL', + 'U32STRING_LITERAL', + + # Operators + 'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'MOD', + 'OR', 'AND', 'NOT', 'XOR', 'LSHIFT', 'RSHIFT', + 'LOR', 'LAND', 'LNOT', + 'LT', 'LE', 'GT', 'GE', 'EQ', 'NE', + + # Assignment + 'EQUALS', 'TIMESEQUAL', 'DIVEQUAL', 'MODEQUAL', + 'PLUSEQUAL', 'MINUSEQUAL', + 'LSHIFTEQUAL','RSHIFTEQUAL', 'ANDEQUAL', 'XOREQUAL', + 'OREQUAL', + + # Increment/decrement + 'PLUSPLUS', 'MINUSMINUS', + + # Structure dereference (->) + 'ARROW', + + # Conditional operator (?) + 'CONDOP', + + # Delimiters + 'LPAREN', 'RPAREN', # ( ) + 'LBRACKET', 'RBRACKET', # [ ] + 'LBRACE', 'RBRACE', # { } + 'COMMA', 'PERIOD', # . , + 'SEMI', 'COLON', # ; : + + # Ellipsis (...) + 'ELLIPSIS', + + # pre-processor + 'PPHASH', # '#' + 'PPPRAGMA', # 'pragma' + 'PPPRAGMASTR', + ) + + ## + ## Regexes for use in tokens + ## + ## + + # valid C identifiers (K&R2: A.2.3), plus '$' (supported by some compilers) + identifier = r'[a-zA-Z_$][0-9a-zA-Z_$]*' + + hex_prefix = '0[xX]' + hex_digits = '[0-9a-fA-F]+' + bin_prefix = '0[bB]' + bin_digits = '[01]+' + + # integer constants (K&R2: A.2.5.1) + integer_suffix_opt = r'(([uU]ll)|([uU]LL)|(ll[uU]?)|(LL[uU]?)|([uU][lL])|([lL][uU]?)|[uU])?' + decimal_constant = '(0'+integer_suffix_opt+')|([1-9][0-9]*'+integer_suffix_opt+')' + octal_constant = '0[0-7]*'+integer_suffix_opt + hex_constant = hex_prefix+hex_digits+integer_suffix_opt + bin_constant = bin_prefix+bin_digits+integer_suffix_opt + + bad_octal_constant = '0[0-7]*[89]' + + # character constants (K&R2: A.2.5.2) + # Note: a-zA-Z and '.-~^_!=&;,' are allowed as escape chars to support #line + # directives with Windows paths as filenames (..\..\dir\file) + # For the same reason, decimal_escape allows all digit sequences. We want to + # parse all correct code, even if it means to sometimes parse incorrect + # code. + # + # The original regexes were taken verbatim from the C syntax definition, + # and were later modified to avoid worst-case exponential running time. + # + # simple_escape = r"""([a-zA-Z._~!=&\^\-\\?'"])""" + # decimal_escape = r"""(\d+)""" + # hex_escape = r"""(x[0-9a-fA-F]+)""" + # bad_escape = r"""([\\][^a-zA-Z._~^!=&\^\-\\?'"x0-7])""" + # + # The following modifications were made to avoid the ambiguity that allowed backtracking: + # (https://github.com/eliben/pycparser/issues/61) + # + # - \x was removed from simple_escape, unless it was not followed by a hex digit, to avoid ambiguity with hex_escape. + # - hex_escape allows one or more hex characters, but requires that the next character(if any) is not hex + # - decimal_escape allows one or more decimal characters, but requires that the next character(if any) is not a decimal + # - bad_escape does not allow any decimals (8-9), to avoid conflicting with the permissive decimal_escape. + # + # Without this change, python's `re` module would recursively try parsing each ambiguous escape sequence in multiple ways. + # e.g. `\123` could be parsed as `\1`+`23`, `\12`+`3`, and `\123`. + + simple_escape = r"""([a-wyzA-Z._~!=&\^\-\\?'"]|x(?![0-9a-fA-F]))""" + decimal_escape = r"""(\d+)(?!\d)""" + hex_escape = r"""(x[0-9a-fA-F]+)(?![0-9a-fA-F])""" + bad_escape = r"""([\\][^a-zA-Z._~^!=&\^\-\\?'"x0-9])""" + + escape_sequence = r"""(\\("""+simple_escape+'|'+decimal_escape+'|'+hex_escape+'))' + + # This complicated regex with lookahead might be slow for strings, so because all of the valid escapes (including \x) allowed + # 0 or more non-escaped characters after the first character, simple_escape+decimal_escape+hex_escape got simplified to + + escape_sequence_start_in_string = r"""(\\[0-9a-zA-Z._~!=&\^\-\\?'"])""" + + cconst_char = r"""([^'\\\n]|"""+escape_sequence+')' + char_const = "'"+cconst_char+"'" + wchar_const = 'L'+char_const + u8char_const = 'u8'+char_const + u16char_const = 'u'+char_const + u32char_const = 'U'+char_const + multicharacter_constant = "'"+cconst_char+"{2,4}'" + unmatched_quote = "('"+cconst_char+"*\\n)|('"+cconst_char+"*$)" + bad_char_const = r"""('"""+cconst_char+"""[^'\n]+')|('')|('"""+bad_escape+r"""[^'\n]*')""" + + # string literals (K&R2: A.2.6) + string_char = r"""([^"\\\n]|"""+escape_sequence_start_in_string+')' + string_literal = '"'+string_char+'*"' + wstring_literal = 'L'+string_literal + u8string_literal = 'u8'+string_literal + u16string_literal = 'u'+string_literal + u32string_literal = 'U'+string_literal + bad_string_literal = '"'+string_char+'*'+bad_escape+string_char+'*"' + + # floating constants (K&R2: A.2.5.3) + exponent_part = r"""([eE][-+]?[0-9]+)""" + fractional_constant = r"""([0-9]*\.[0-9]+)|([0-9]+\.)""" + floating_constant = '(((('+fractional_constant+')'+exponent_part+'?)|([0-9]+'+exponent_part+'))[FfLl]?)' + binary_exponent_part = r'''([pP][+-]?[0-9]+)''' + hex_fractional_constant = '((('+hex_digits+r""")?\."""+hex_digits+')|('+hex_digits+r"""\.))""" + hex_floating_constant = '('+hex_prefix+'('+hex_digits+'|'+hex_fractional_constant+')'+binary_exponent_part+'[FfLl]?)' + + ## + ## Lexer states: used for preprocessor \n-terminated directives + ## + states = ( + # ppline: preprocessor line directives + # + ('ppline', 'exclusive'), + + # pppragma: pragma + # + ('pppragma', 'exclusive'), + ) + + def t_PPHASH(self, t): + r'[ \t]*\#' + if self.line_pattern.match(t.lexer.lexdata, pos=t.lexer.lexpos): + t.lexer.begin('ppline') + self.pp_line = self.pp_filename = None + elif self.pragma_pattern.match(t.lexer.lexdata, pos=t.lexer.lexpos): + t.lexer.begin('pppragma') + else: + t.type = 'PPHASH' + return t + + ## + ## Rules for the ppline state + ## + @TOKEN(string_literal) + def t_ppline_FILENAME(self, t): + if self.pp_line is None: + self._error('filename before line number in #line', t) + else: + self.pp_filename = t.value.lstrip('"').rstrip('"') + + @TOKEN(decimal_constant) + def t_ppline_LINE_NUMBER(self, t): + if self.pp_line is None: + self.pp_line = t.value + else: + # Ignore: GCC's cpp sometimes inserts a numeric flag + # after the file name + pass + + def t_ppline_NEWLINE(self, t): + r'\n' + if self.pp_line is None: + self._error('line number missing in #line', t) + else: + self.lexer.lineno = int(self.pp_line) + + if self.pp_filename is not None: + self.filename = self.pp_filename + + t.lexer.begin('INITIAL') + + def t_ppline_PPLINE(self, t): + r'line' + pass + + t_ppline_ignore = ' \t' + + def t_ppline_error(self, t): + self._error('invalid #line directive', t) + + ## + ## Rules for the pppragma state + ## + def t_pppragma_NEWLINE(self, t): + r'\n' + t.lexer.lineno += 1 + t.lexer.begin('INITIAL') + + def t_pppragma_PPPRAGMA(self, t): + r'pragma' + return t + + t_pppragma_ignore = ' \t' + + def t_pppragma_STR(self, t): + '.+' + t.type = 'PPPRAGMASTR' + return t + + def t_pppragma_error(self, t): + self._error('invalid #pragma directive', t) + + ## + ## Rules for the normal state + ## + t_ignore = ' \t' + + # Newlines + def t_NEWLINE(self, t): + r'\n+' + t.lexer.lineno += t.value.count("\n") + + # Operators + t_PLUS = r'\+' + t_MINUS = r'-' + t_TIMES = r'\*' + t_DIVIDE = r'/' + t_MOD = r'%' + t_OR = r'\|' + t_AND = r'&' + t_NOT = r'~' + t_XOR = r'\^' + t_LSHIFT = r'<<' + t_RSHIFT = r'>>' + t_LOR = r'\|\|' + t_LAND = r'&&' + t_LNOT = r'!' + t_LT = r'<' + t_GT = r'>' + t_LE = r'<=' + t_GE = r'>=' + t_EQ = r'==' + t_NE = r'!=' + + # Assignment operators + t_EQUALS = r'=' + t_TIMESEQUAL = r'\*=' + t_DIVEQUAL = r'/=' + t_MODEQUAL = r'%=' + t_PLUSEQUAL = r'\+=' + t_MINUSEQUAL = r'-=' + t_LSHIFTEQUAL = r'<<=' + t_RSHIFTEQUAL = r'>>=' + t_ANDEQUAL = r'&=' + t_OREQUAL = r'\|=' + t_XOREQUAL = r'\^=' + + # Increment/decrement + t_PLUSPLUS = r'\+\+' + t_MINUSMINUS = r'--' + + # -> + t_ARROW = r'->' + + # ? + t_CONDOP = r'\?' + + # Delimiters + t_LPAREN = r'\(' + t_RPAREN = r'\)' + t_LBRACKET = r'\[' + t_RBRACKET = r'\]' + t_COMMA = r',' + t_PERIOD = r'\.' + t_SEMI = r';' + t_COLON = r':' + t_ELLIPSIS = r'\.\.\.' + + # Scope delimiters + # To see why on_lbrace_func is needed, consider: + # typedef char TT; + # void foo(int TT) { TT = 10; } + # TT x = 5; + # Outside the function, TT is a typedef, but inside (starting and ending + # with the braces) it's a parameter. The trouble begins with yacc's + # lookahead token. If we open a new scope in brace_open, then TT has + # already been read and incorrectly interpreted as TYPEID. So, we need + # to open and close scopes from within the lexer. + # Similar for the TT immediately outside the end of the function. + # + @TOKEN(r'\{') + def t_LBRACE(self, t): + self.on_lbrace_func() + return t + @TOKEN(r'\}') + def t_RBRACE(self, t): + self.on_rbrace_func() + return t + + t_STRING_LITERAL = string_literal + + # The following floating and integer constants are defined as + # functions to impose a strict order (otherwise, decimal + # is placed before the others because its regex is longer, + # and this is bad) + # + @TOKEN(floating_constant) + def t_FLOAT_CONST(self, t): + return t + + @TOKEN(hex_floating_constant) + def t_HEX_FLOAT_CONST(self, t): + return t + + @TOKEN(hex_constant) + def t_INT_CONST_HEX(self, t): + return t + + @TOKEN(bin_constant) + def t_INT_CONST_BIN(self, t): + return t + + @TOKEN(bad_octal_constant) + def t_BAD_CONST_OCT(self, t): + msg = "Invalid octal constant" + self._error(msg, t) + + @TOKEN(octal_constant) + def t_INT_CONST_OCT(self, t): + return t + + @TOKEN(decimal_constant) + def t_INT_CONST_DEC(self, t): + return t + + # Must come before bad_char_const, to prevent it from + # catching valid char constants as invalid + # + @TOKEN(multicharacter_constant) + def t_INT_CONST_CHAR(self, t): + return t + + @TOKEN(char_const) + def t_CHAR_CONST(self, t): + return t + + @TOKEN(wchar_const) + def t_WCHAR_CONST(self, t): + return t + + @TOKEN(u8char_const) + def t_U8CHAR_CONST(self, t): + return t + + @TOKEN(u16char_const) + def t_U16CHAR_CONST(self, t): + return t + + @TOKEN(u32char_const) + def t_U32CHAR_CONST(self, t): + return t + + @TOKEN(unmatched_quote) + def t_UNMATCHED_QUOTE(self, t): + msg = "Unmatched '" + self._error(msg, t) + + @TOKEN(bad_char_const) + def t_BAD_CHAR_CONST(self, t): + msg = "Invalid char constant %s" % t.value + self._error(msg, t) + + @TOKEN(wstring_literal) + def t_WSTRING_LITERAL(self, t): + return t + + @TOKEN(u8string_literal) + def t_U8STRING_LITERAL(self, t): + return t + + @TOKEN(u16string_literal) + def t_U16STRING_LITERAL(self, t): + return t + + @TOKEN(u32string_literal) + def t_U32STRING_LITERAL(self, t): + return t + + # unmatched string literals are caught by the preprocessor + + @TOKEN(bad_string_literal) + def t_BAD_STRING_LITERAL(self, t): + msg = "String contains invalid escape code" + self._error(msg, t) + + @TOKEN(identifier) + def t_ID(self, t): + t.type = self.keyword_map.get(t.value, "ID") + if t.type == 'ID' and self.type_lookup_func(t.value): + t.type = "TYPEID" + return t + + def t_error(self, t): + msg = 'Illegal character %s' % repr(t.value[0]) + self._error(msg, t) diff --git a/.venv/Lib/site-packages/pycparser/c_parser.py b/.venv/Lib/site-packages/pycparser/c_parser.py new file mode 100644 index 00000000..640a7594 --- /dev/null +++ b/.venv/Lib/site-packages/pycparser/c_parser.py @@ -0,0 +1,1936 @@ +#------------------------------------------------------------------------------ +# pycparser: c_parser.py +# +# CParser class: Parser and AST builder for the C language +# +# Eli Bendersky [https://eli.thegreenplace.net/] +# License: BSD +#------------------------------------------------------------------------------ +from .ply import yacc + +from . import c_ast +from .c_lexer import CLexer +from .plyparser import PLYParser, ParseError, parameterized, template +from .ast_transforms import fix_switch_cases, fix_atomic_specifiers + + +@template +class CParser(PLYParser): + def __init__( + self, + lex_optimize=True, + lexer=CLexer, + lextab='pycparser.lextab', + yacc_optimize=True, + yacctab='pycparser.yacctab', + yacc_debug=False, + taboutputdir=''): + """ Create a new CParser. + + Some arguments for controlling the debug/optimization + level of the parser are provided. The defaults are + tuned for release/performance mode. + The simple rules for using them are: + *) When tweaking CParser/CLexer, set these to False + *) When releasing a stable parser, set to True + + lex_optimize: + Set to False when you're modifying the lexer. + Otherwise, changes in the lexer won't be used, if + some lextab.py file exists. + When releasing with a stable lexer, set to True + to save the re-generation of the lexer table on + each run. + + lexer: + Set this parameter to define the lexer to use if + you're not using the default CLexer. + + lextab: + Points to the lex table that's used for optimized + mode. Only if you're modifying the lexer and want + some tests to avoid re-generating the table, make + this point to a local lex table file (that's been + earlier generated with lex_optimize=True) + + yacc_optimize: + Set to False when you're modifying the parser. + Otherwise, changes in the parser won't be used, if + some parsetab.py file exists. + When releasing with a stable parser, set to True + to save the re-generation of the parser table on + each run. + + yacctab: + Points to the yacc table that's used for optimized + mode. Only if you're modifying the parser, make + this point to a local yacc table file + + yacc_debug: + Generate a parser.out file that explains how yacc + built the parsing table from the grammar. + + taboutputdir: + Set this parameter to control the location of generated + lextab and yacctab files. + """ + self.clex = lexer( + error_func=self._lex_error_func, + on_lbrace_func=self._lex_on_lbrace_func, + on_rbrace_func=self._lex_on_rbrace_func, + type_lookup_func=self._lex_type_lookup_func) + + self.clex.build( + optimize=lex_optimize, + lextab=lextab, + outputdir=taboutputdir) + self.tokens = self.clex.tokens + + rules_with_opt = [ + 'abstract_declarator', + 'assignment_expression', + 'declaration_list', + 'declaration_specifiers_no_type', + 'designation', + 'expression', + 'identifier_list', + 'init_declarator_list', + 'id_init_declarator_list', + 'initializer_list', + 'parameter_type_list', + 'block_item_list', + 'type_qualifier_list', + 'struct_declarator_list' + ] + + for rule in rules_with_opt: + self._create_opt_rule(rule) + + self.cparser = yacc.yacc( + module=self, + start='translation_unit_or_empty', + debug=yacc_debug, + optimize=yacc_optimize, + tabmodule=yacctab, + outputdir=taboutputdir) + + # Stack of scopes for keeping track of symbols. _scope_stack[-1] is + # the current (topmost) scope. Each scope is a dictionary that + # specifies whether a name is a type. If _scope_stack[n][name] is + # True, 'name' is currently a type in the scope. If it's False, + # 'name' is used in the scope but not as a type (for instance, if we + # saw: int name; + # If 'name' is not a key in _scope_stack[n] then 'name' was not defined + # in this scope at all. + self._scope_stack = [dict()] + + # Keeps track of the last token given to yacc (the lookahead token) + self._last_yielded_token = None + + def parse(self, text, filename='', debug=False): + """ Parses C code and returns an AST. + + text: + A string containing the C source code + + filename: + Name of the file being parsed (for meaningful + error messages) + + debug: + Debug flag to YACC + """ + self.clex.filename = filename + self.clex.reset_lineno() + self._scope_stack = [dict()] + self._last_yielded_token = None + return self.cparser.parse( + input=text, + lexer=self.clex, + debug=debug) + + ######################-- PRIVATE --###################### + + def _push_scope(self): + self._scope_stack.append(dict()) + + def _pop_scope(self): + assert len(self._scope_stack) > 1 + self._scope_stack.pop() + + def _add_typedef_name(self, name, coord): + """ Add a new typedef name (ie a TYPEID) to the current scope + """ + if not self._scope_stack[-1].get(name, True): + self._parse_error( + "Typedef %r previously declared as non-typedef " + "in this scope" % name, coord) + self._scope_stack[-1][name] = True + + def _add_identifier(self, name, coord): + """ Add a new object, function, or enum member name (ie an ID) to the + current scope + """ + if self._scope_stack[-1].get(name, False): + self._parse_error( + "Non-typedef %r previously declared as typedef " + "in this scope" % name, coord) + self._scope_stack[-1][name] = False + + def _is_type_in_scope(self, name): + """ Is *name* a typedef-name in the current scope? + """ + for scope in reversed(self._scope_stack): + # If name is an identifier in this scope it shadows typedefs in + # higher scopes. + in_scope = scope.get(name) + if in_scope is not None: return in_scope + return False + + def _lex_error_func(self, msg, line, column): + self._parse_error(msg, self._coord(line, column)) + + def _lex_on_lbrace_func(self): + self._push_scope() + + def _lex_on_rbrace_func(self): + self._pop_scope() + + def _lex_type_lookup_func(self, name): + """ Looks up types that were previously defined with + typedef. + Passed to the lexer for recognizing identifiers that + are types. + """ + is_type = self._is_type_in_scope(name) + return is_type + + def _get_yacc_lookahead_token(self): + """ We need access to yacc's lookahead token in certain cases. + This is the last token yacc requested from the lexer, so we + ask the lexer. + """ + return self.clex.last_token + + # To understand what's going on here, read sections A.8.5 and + # A.8.6 of K&R2 very carefully. + # + # A C type consists of a basic type declaration, with a list + # of modifiers. For example: + # + # int *c[5]; + # + # The basic declaration here is 'int c', and the pointer and + # the array are the modifiers. + # + # Basic declarations are represented by TypeDecl (from module c_ast) and the + # modifiers are FuncDecl, PtrDecl and ArrayDecl. + # + # The standard states that whenever a new modifier is parsed, it should be + # added to the end of the list of modifiers. For example: + # + # K&R2 A.8.6.2: Array Declarators + # + # In a declaration T D where D has the form + # D1 [constant-expression-opt] + # and the type of the identifier in the declaration T D1 is + # "type-modifier T", the type of the + # identifier of D is "type-modifier array of T" + # + # This is what this method does. The declarator it receives + # can be a list of declarators ending with TypeDecl. It + # tacks the modifier to the end of this list, just before + # the TypeDecl. + # + # Additionally, the modifier may be a list itself. This is + # useful for pointers, that can come as a chain from the rule + # p_pointer. In this case, the whole modifier list is spliced + # into the new location. + def _type_modify_decl(self, decl, modifier): + """ Tacks a type modifier on a declarator, and returns + the modified declarator. + + Note: the declarator and modifier may be modified + """ + #~ print '****' + #~ decl.show(offset=3) + #~ modifier.show(offset=3) + #~ print '****' + + modifier_head = modifier + modifier_tail = modifier + + # The modifier may be a nested list. Reach its tail. + while modifier_tail.type: + modifier_tail = modifier_tail.type + + # If the decl is a basic type, just tack the modifier onto it. + if isinstance(decl, c_ast.TypeDecl): + modifier_tail.type = decl + return modifier + else: + # Otherwise, the decl is a list of modifiers. Reach + # its tail and splice the modifier onto the tail, + # pointing to the underlying basic type. + decl_tail = decl + + while not isinstance(decl_tail.type, c_ast.TypeDecl): + decl_tail = decl_tail.type + + modifier_tail.type = decl_tail.type + decl_tail.type = modifier_head + return decl + + # Due to the order in which declarators are constructed, + # they have to be fixed in order to look like a normal AST. + # + # When a declaration arrives from syntax construction, it has + # these problems: + # * The innermost TypeDecl has no type (because the basic + # type is only known at the uppermost declaration level) + # * The declaration has no variable name, since that is saved + # in the innermost TypeDecl + # * The typename of the declaration is a list of type + # specifiers, and not a node. Here, basic identifier types + # should be separated from more complex types like enums + # and structs. + # + # This method fixes these problems. + def _fix_decl_name_type(self, decl, typename): + """ Fixes a declaration. Modifies decl. + """ + # Reach the underlying basic type + # + type = decl + while not isinstance(type, c_ast.TypeDecl): + type = type.type + + decl.name = type.declname + type.quals = decl.quals[:] + + # The typename is a list of types. If any type in this + # list isn't an IdentifierType, it must be the only + # type in the list (it's illegal to declare "int enum ..") + # If all the types are basic, they're collected in the + # IdentifierType holder. + for tn in typename: + if not isinstance(tn, c_ast.IdentifierType): + if len(typename) > 1: + self._parse_error( + "Invalid multiple types specified", tn.coord) + else: + type.type = tn + return decl + + if not typename: + # Functions default to returning int + # + if not isinstance(decl.type, c_ast.FuncDecl): + self._parse_error( + "Missing type in declaration", decl.coord) + type.type = c_ast.IdentifierType( + ['int'], + coord=decl.coord) + else: + # At this point, we know that typename is a list of IdentifierType + # nodes. Concatenate all the names into a single list. + # + type.type = c_ast.IdentifierType( + [name for id in typename for name in id.names], + coord=typename[0].coord) + return decl + + def _add_declaration_specifier(self, declspec, newspec, kind, append=False): + """ Declaration specifiers are represented by a dictionary + with the entries: + * qual: a list of type qualifiers + * storage: a list of storage type qualifiers + * type: a list of type specifiers + * function: a list of function specifiers + * alignment: a list of alignment specifiers + + This method is given a declaration specifier, and a + new specifier of a given kind. + If `append` is True, the new specifier is added to the end of + the specifiers list, otherwise it's added at the beginning. + Returns the declaration specifier, with the new + specifier incorporated. + """ + spec = declspec or dict(qual=[], storage=[], type=[], function=[], alignment=[]) + + if append: + spec[kind].append(newspec) + else: + spec[kind].insert(0, newspec) + + return spec + + def _build_declarations(self, spec, decls, typedef_namespace=False): + """ Builds a list of declarations all sharing the given specifiers. + If typedef_namespace is true, each declared name is added + to the "typedef namespace", which also includes objects, + functions, and enum constants. + """ + is_typedef = 'typedef' in spec['storage'] + declarations = [] + + # Bit-fields are allowed to be unnamed. + if decls[0].get('bitsize') is not None: + pass + + # When redeclaring typedef names as identifiers in inner scopes, a + # problem can occur where the identifier gets grouped into + # spec['type'], leaving decl as None. This can only occur for the + # first declarator. + elif decls[0]['decl'] is None: + if len(spec['type']) < 2 or len(spec['type'][-1].names) != 1 or \ + not self._is_type_in_scope(spec['type'][-1].names[0]): + coord = '?' + for t in spec['type']: + if hasattr(t, 'coord'): + coord = t.coord + break + self._parse_error('Invalid declaration', coord) + + # Make this look as if it came from "direct_declarator:ID" + decls[0]['decl'] = c_ast.TypeDecl( + declname=spec['type'][-1].names[0], + type=None, + quals=None, + align=spec['alignment'], + coord=spec['type'][-1].coord) + # Remove the "new" type's name from the end of spec['type'] + del spec['type'][-1] + + # A similar problem can occur where the declaration ends up looking + # like an abstract declarator. Give it a name if this is the case. + elif not isinstance(decls[0]['decl'], ( + c_ast.Enum, c_ast.Struct, c_ast.Union, c_ast.IdentifierType)): + decls_0_tail = decls[0]['decl'] + while not isinstance(decls_0_tail, c_ast.TypeDecl): + decls_0_tail = decls_0_tail.type + if decls_0_tail.declname is None: + decls_0_tail.declname = spec['type'][-1].names[0] + del spec['type'][-1] + + for decl in decls: + assert decl['decl'] is not None + if is_typedef: + declaration = c_ast.Typedef( + name=None, + quals=spec['qual'], + storage=spec['storage'], + type=decl['decl'], + coord=decl['decl'].coord) + else: + declaration = c_ast.Decl( + name=None, + quals=spec['qual'], + align=spec['alignment'], + storage=spec['storage'], + funcspec=spec['function'], + type=decl['decl'], + init=decl.get('init'), + bitsize=decl.get('bitsize'), + coord=decl['decl'].coord) + + if isinstance(declaration.type, ( + c_ast.Enum, c_ast.Struct, c_ast.Union, + c_ast.IdentifierType)): + fixed_decl = declaration + else: + fixed_decl = self._fix_decl_name_type(declaration, spec['type']) + + # Add the type name defined by typedef to a + # symbol table (for usage in the lexer) + if typedef_namespace: + if is_typedef: + self._add_typedef_name(fixed_decl.name, fixed_decl.coord) + else: + self._add_identifier(fixed_decl.name, fixed_decl.coord) + + fixed_decl = fix_atomic_specifiers(fixed_decl) + declarations.append(fixed_decl) + + return declarations + + def _build_function_definition(self, spec, decl, param_decls, body): + """ Builds a function definition. + """ + if 'typedef' in spec['storage']: + self._parse_error("Invalid typedef", decl.coord) + + declaration = self._build_declarations( + spec=spec, + decls=[dict(decl=decl, init=None)], + typedef_namespace=True)[0] + + return c_ast.FuncDef( + decl=declaration, + param_decls=param_decls, + body=body, + coord=decl.coord) + + def _select_struct_union_class(self, token): + """ Given a token (either STRUCT or UNION), selects the + appropriate AST class. + """ + if token == 'struct': + return c_ast.Struct + else: + return c_ast.Union + + ## + ## Precedence and associativity of operators + ## + # If this changes, c_generator.CGenerator.precedence_map needs to change as + # well + precedence = ( + ('left', 'LOR'), + ('left', 'LAND'), + ('left', 'OR'), + ('left', 'XOR'), + ('left', 'AND'), + ('left', 'EQ', 'NE'), + ('left', 'GT', 'GE', 'LT', 'LE'), + ('left', 'RSHIFT', 'LSHIFT'), + ('left', 'PLUS', 'MINUS'), + ('left', 'TIMES', 'DIVIDE', 'MOD') + ) + + ## + ## Grammar productions + ## Implementation of the BNF defined in K&R2 A.13 + ## + + # Wrapper around a translation unit, to allow for empty input. + # Not strictly part of the C99 Grammar, but useful in practice. + def p_translation_unit_or_empty(self, p): + """ translation_unit_or_empty : translation_unit + | empty + """ + if p[1] is None: + p[0] = c_ast.FileAST([]) + else: + p[0] = c_ast.FileAST(p[1]) + + def p_translation_unit_1(self, p): + """ translation_unit : external_declaration + """ + # Note: external_declaration is already a list + p[0] = p[1] + + def p_translation_unit_2(self, p): + """ translation_unit : translation_unit external_declaration + """ + p[1].extend(p[2]) + p[0] = p[1] + + # Declarations always come as lists (because they can be + # several in one line), so we wrap the function definition + # into a list as well, to make the return value of + # external_declaration homogeneous. + def p_external_declaration_1(self, p): + """ external_declaration : function_definition + """ + p[0] = [p[1]] + + def p_external_declaration_2(self, p): + """ external_declaration : declaration + """ + p[0] = p[1] + + def p_external_declaration_3(self, p): + """ external_declaration : pp_directive + | pppragma_directive + """ + p[0] = [p[1]] + + def p_external_declaration_4(self, p): + """ external_declaration : SEMI + """ + p[0] = [] + + def p_external_declaration_5(self, p): + """ external_declaration : static_assert + """ + p[0] = p[1] + + def p_static_assert_declaration(self, p): + """ static_assert : _STATIC_ASSERT LPAREN constant_expression COMMA unified_string_literal RPAREN + | _STATIC_ASSERT LPAREN constant_expression RPAREN + """ + if len(p) == 5: + p[0] = [c_ast.StaticAssert(p[3], None, self._token_coord(p, 1))] + else: + p[0] = [c_ast.StaticAssert(p[3], p[5], self._token_coord(p, 1))] + + def p_pp_directive(self, p): + """ pp_directive : PPHASH + """ + self._parse_error('Directives not supported yet', + self._token_coord(p, 1)) + + def p_pppragma_directive(self, p): + """ pppragma_directive : PPPRAGMA + | PPPRAGMA PPPRAGMASTR + """ + if len(p) == 3: + p[0] = c_ast.Pragma(p[2], self._token_coord(p, 2)) + else: + p[0] = c_ast.Pragma("", self._token_coord(p, 1)) + + # In function definitions, the declarator can be followed by + # a declaration list, for old "K&R style" function definitios. + def p_function_definition_1(self, p): + """ function_definition : id_declarator declaration_list_opt compound_statement + """ + # no declaration specifiers - 'int' becomes the default type + spec = dict( + qual=[], + alignment=[], + storage=[], + type=[c_ast.IdentifierType(['int'], + coord=self._token_coord(p, 1))], + function=[]) + + p[0] = self._build_function_definition( + spec=spec, + decl=p[1], + param_decls=p[2], + body=p[3]) + + def p_function_definition_2(self, p): + """ function_definition : declaration_specifiers id_declarator declaration_list_opt compound_statement + """ + spec = p[1] + + p[0] = self._build_function_definition( + spec=spec, + decl=p[2], + param_decls=p[3], + body=p[4]) + + # Note, according to C18 A.2.2 6.7.10 static_assert-declaration _Static_assert + # is a declaration, not a statement. We additionally recognise it as a statement + # to fix parsing of _Static_assert inside the functions. + # + def p_statement(self, p): + """ statement : labeled_statement + | expression_statement + | compound_statement + | selection_statement + | iteration_statement + | jump_statement + | pppragma_directive + | static_assert + """ + p[0] = p[1] + + # A pragma is generally considered a decorator rather than an actual + # statement. Still, for the purposes of analyzing an abstract syntax tree of + # C code, pragma's should not be ignored and were previously treated as a + # statement. This presents a problem for constructs that take a statement + # such as labeled_statements, selection_statements, and + # iteration_statements, causing a misleading structure in the AST. For + # example, consider the following C code. + # + # for (int i = 0; i < 3; i++) + # #pragma omp critical + # sum += 1; + # + # This code will compile and execute "sum += 1;" as the body of the for + # loop. Previous implementations of PyCParser would render the AST for this + # block of code as follows: + # + # For: + # DeclList: + # Decl: i, [], [], [] + # TypeDecl: i, [] + # IdentifierType: ['int'] + # Constant: int, 0 + # BinaryOp: < + # ID: i + # Constant: int, 3 + # UnaryOp: p++ + # ID: i + # Pragma: omp critical + # Assignment: += + # ID: sum + # Constant: int, 1 + # + # This AST misleadingly takes the Pragma as the body of the loop and the + # assignment then becomes a sibling of the loop. + # + # To solve edge cases like these, the pragmacomp_or_statement rule groups + # a pragma and its following statement (which would otherwise be orphaned) + # using a compound block, effectively turning the above code into: + # + # for (int i = 0; i < 3; i++) { + # #pragma omp critical + # sum += 1; + # } + def p_pragmacomp_or_statement(self, p): + """ pragmacomp_or_statement : pppragma_directive statement + | statement + """ + if isinstance(p[1], c_ast.Pragma) and len(p) == 3: + p[0] = c_ast.Compound( + block_items=[p[1], p[2]], + coord=self._token_coord(p, 1)) + else: + p[0] = p[1] + + # In C, declarations can come several in a line: + # int x, *px, romulo = 5; + # + # However, for the AST, we will split them to separate Decl + # nodes. + # + # This rule splits its declarations and always returns a list + # of Decl nodes, even if it's one element long. + # + def p_decl_body(self, p): + """ decl_body : declaration_specifiers init_declarator_list_opt + | declaration_specifiers_no_type id_init_declarator_list_opt + """ + spec = p[1] + + # p[2] (init_declarator_list_opt) is either a list or None + # + if p[2] is None: + # By the standard, you must have at least one declarator unless + # declaring a structure tag, a union tag, or the members of an + # enumeration. + # + ty = spec['type'] + s_u_or_e = (c_ast.Struct, c_ast.Union, c_ast.Enum) + if len(ty) == 1 and isinstance(ty[0], s_u_or_e): + decls = [c_ast.Decl( + name=None, + quals=spec['qual'], + align=spec['alignment'], + storage=spec['storage'], + funcspec=spec['function'], + type=ty[0], + init=None, + bitsize=None, + coord=ty[0].coord)] + + # However, this case can also occur on redeclared identifiers in + # an inner scope. The trouble is that the redeclared type's name + # gets grouped into declaration_specifiers; _build_declarations + # compensates for this. + # + else: + decls = self._build_declarations( + spec=spec, + decls=[dict(decl=None, init=None)], + typedef_namespace=True) + + else: + decls = self._build_declarations( + spec=spec, + decls=p[2], + typedef_namespace=True) + + p[0] = decls + + # The declaration has been split to a decl_body sub-rule and + # SEMI, because having them in a single rule created a problem + # for defining typedefs. + # + # If a typedef line was directly followed by a line using the + # type defined with the typedef, the type would not be + # recognized. This is because to reduce the declaration rule, + # the parser's lookahead asked for the token after SEMI, which + # was the type from the next line, and the lexer had no chance + # to see the updated type symbol table. + # + # Splitting solves this problem, because after seeing SEMI, + # the parser reduces decl_body, which actually adds the new + # type into the table to be seen by the lexer before the next + # line is reached. + def p_declaration(self, p): + """ declaration : decl_body SEMI + """ + p[0] = p[1] + + # Since each declaration is a list of declarations, this + # rule will combine all the declarations and return a single + # list + # + def p_declaration_list(self, p): + """ declaration_list : declaration + | declaration_list declaration + """ + p[0] = p[1] if len(p) == 2 else p[1] + p[2] + + # To know when declaration-specifiers end and declarators begin, + # we require declaration-specifiers to have at least one + # type-specifier, and disallow typedef-names after we've seen any + # type-specifier. These are both required by the spec. + # + def p_declaration_specifiers_no_type_1(self, p): + """ declaration_specifiers_no_type : type_qualifier declaration_specifiers_no_type_opt + """ + p[0] = self._add_declaration_specifier(p[2], p[1], 'qual') + + def p_declaration_specifiers_no_type_2(self, p): + """ declaration_specifiers_no_type : storage_class_specifier declaration_specifiers_no_type_opt + """ + p[0] = self._add_declaration_specifier(p[2], p[1], 'storage') + + def p_declaration_specifiers_no_type_3(self, p): + """ declaration_specifiers_no_type : function_specifier declaration_specifiers_no_type_opt + """ + p[0] = self._add_declaration_specifier(p[2], p[1], 'function') + + # Without this, `typedef _Atomic(T) U` will parse incorrectly because the + # _Atomic qualifier will match, instead of the specifier. + def p_declaration_specifiers_no_type_4(self, p): + """ declaration_specifiers_no_type : atomic_specifier declaration_specifiers_no_type_opt + """ + p[0] = self._add_declaration_specifier(p[2], p[1], 'type') + + def p_declaration_specifiers_no_type_5(self, p): + """ declaration_specifiers_no_type : alignment_specifier declaration_specifiers_no_type_opt + """ + p[0] = self._add_declaration_specifier(p[2], p[1], 'alignment') + + def p_declaration_specifiers_1(self, p): + """ declaration_specifiers : declaration_specifiers type_qualifier + """ + p[0] = self._add_declaration_specifier(p[1], p[2], 'qual', append=True) + + def p_declaration_specifiers_2(self, p): + """ declaration_specifiers : declaration_specifiers storage_class_specifier + """ + p[0] = self._add_declaration_specifier(p[1], p[2], 'storage', append=True) + + def p_declaration_specifiers_3(self, p): + """ declaration_specifiers : declaration_specifiers function_specifier + """ + p[0] = self._add_declaration_specifier(p[1], p[2], 'function', append=True) + + def p_declaration_specifiers_4(self, p): + """ declaration_specifiers : declaration_specifiers type_specifier_no_typeid + """ + p[0] = self._add_declaration_specifier(p[1], p[2], 'type', append=True) + + def p_declaration_specifiers_5(self, p): + """ declaration_specifiers : type_specifier + """ + p[0] = self._add_declaration_specifier(None, p[1], 'type') + + def p_declaration_specifiers_6(self, p): + """ declaration_specifiers : declaration_specifiers_no_type type_specifier + """ + p[0] = self._add_declaration_specifier(p[1], p[2], 'type', append=True) + + def p_declaration_specifiers_7(self, p): + """ declaration_specifiers : declaration_specifiers alignment_specifier + """ + p[0] = self._add_declaration_specifier(p[1], p[2], 'alignment', append=True) + + def p_storage_class_specifier(self, p): + """ storage_class_specifier : AUTO + | REGISTER + | STATIC + | EXTERN + | TYPEDEF + | _THREAD_LOCAL + """ + p[0] = p[1] + + def p_function_specifier(self, p): + """ function_specifier : INLINE + | _NORETURN + """ + p[0] = p[1] + + def p_type_specifier_no_typeid(self, p): + """ type_specifier_no_typeid : VOID + | _BOOL + | CHAR + | SHORT + | INT + | LONG + | FLOAT + | DOUBLE + | _COMPLEX + | SIGNED + | UNSIGNED + | __INT128 + """ + p[0] = c_ast.IdentifierType([p[1]], coord=self._token_coord(p, 1)) + + def p_type_specifier(self, p): + """ type_specifier : typedef_name + | enum_specifier + | struct_or_union_specifier + | type_specifier_no_typeid + | atomic_specifier + """ + p[0] = p[1] + + # See section 6.7.2.4 of the C11 standard. + def p_atomic_specifier(self, p): + """ atomic_specifier : _ATOMIC LPAREN type_name RPAREN + """ + typ = p[3] + typ.quals.append('_Atomic') + p[0] = typ + + def p_type_qualifier(self, p): + """ type_qualifier : CONST + | RESTRICT + | VOLATILE + | _ATOMIC + """ + p[0] = p[1] + + def p_init_declarator_list(self, p): + """ init_declarator_list : init_declarator + | init_declarator_list COMMA init_declarator + """ + p[0] = p[1] + [p[3]] if len(p) == 4 else [p[1]] + + # Returns a {decl= : init=} dictionary + # If there's no initializer, uses None + # + def p_init_declarator(self, p): + """ init_declarator : declarator + | declarator EQUALS initializer + """ + p[0] = dict(decl=p[1], init=(p[3] if len(p) > 2 else None)) + + def p_id_init_declarator_list(self, p): + """ id_init_declarator_list : id_init_declarator + | id_init_declarator_list COMMA init_declarator + """ + p[0] = p[1] + [p[3]] if len(p) == 4 else [p[1]] + + def p_id_init_declarator(self, p): + """ id_init_declarator : id_declarator + | id_declarator EQUALS initializer + """ + p[0] = dict(decl=p[1], init=(p[3] if len(p) > 2 else None)) + + # Require at least one type specifier in a specifier-qualifier-list + # + def p_specifier_qualifier_list_1(self, p): + """ specifier_qualifier_list : specifier_qualifier_list type_specifier_no_typeid + """ + p[0] = self._add_declaration_specifier(p[1], p[2], 'type', append=True) + + def p_specifier_qualifier_list_2(self, p): + """ specifier_qualifier_list : specifier_qualifier_list type_qualifier + """ + p[0] = self._add_declaration_specifier(p[1], p[2], 'qual', append=True) + + def p_specifier_qualifier_list_3(self, p): + """ specifier_qualifier_list : type_specifier + """ + p[0] = self._add_declaration_specifier(None, p[1], 'type') + + def p_specifier_qualifier_list_4(self, p): + """ specifier_qualifier_list : type_qualifier_list type_specifier + """ + p[0] = dict(qual=p[1], alignment=[], storage=[], type=[p[2]], function=[]) + + def p_specifier_qualifier_list_5(self, p): + """ specifier_qualifier_list : alignment_specifier + """ + p[0] = dict(qual=[], alignment=[p[1]], storage=[], type=[], function=[]) + + def p_specifier_qualifier_list_6(self, p): + """ specifier_qualifier_list : specifier_qualifier_list alignment_specifier + """ + p[0] = self._add_declaration_specifier(p[1], p[2], 'alignment') + + # TYPEID is allowed here (and in other struct/enum related tag names), because + # struct/enum tags reside in their own namespace and can be named the same as types + # + def p_struct_or_union_specifier_1(self, p): + """ struct_or_union_specifier : struct_or_union ID + | struct_or_union TYPEID + """ + klass = self._select_struct_union_class(p[1]) + # None means no list of members + p[0] = klass( + name=p[2], + decls=None, + coord=self._token_coord(p, 2)) + + def p_struct_or_union_specifier_2(self, p): + """ struct_or_union_specifier : struct_or_union brace_open struct_declaration_list brace_close + | struct_or_union brace_open brace_close + """ + klass = self._select_struct_union_class(p[1]) + if len(p) == 4: + # Empty sequence means an empty list of members + p[0] = klass( + name=None, + decls=[], + coord=self._token_coord(p, 2)) + else: + p[0] = klass( + name=None, + decls=p[3], + coord=self._token_coord(p, 2)) + + + def p_struct_or_union_specifier_3(self, p): + """ struct_or_union_specifier : struct_or_union ID brace_open struct_declaration_list brace_close + | struct_or_union ID brace_open brace_close + | struct_or_union TYPEID brace_open struct_declaration_list brace_close + | struct_or_union TYPEID brace_open brace_close + """ + klass = self._select_struct_union_class(p[1]) + if len(p) == 5: + # Empty sequence means an empty list of members + p[0] = klass( + name=p[2], + decls=[], + coord=self._token_coord(p, 2)) + else: + p[0] = klass( + name=p[2], + decls=p[4], + coord=self._token_coord(p, 2)) + + def p_struct_or_union(self, p): + """ struct_or_union : STRUCT + | UNION + """ + p[0] = p[1] + + # Combine all declarations into a single list + # + def p_struct_declaration_list(self, p): + """ struct_declaration_list : struct_declaration + | struct_declaration_list struct_declaration + """ + if len(p) == 2: + p[0] = p[1] or [] + else: + p[0] = p[1] + (p[2] or []) + + def p_struct_declaration_1(self, p): + """ struct_declaration : specifier_qualifier_list struct_declarator_list_opt SEMI + """ + spec = p[1] + assert 'typedef' not in spec['storage'] + + if p[2] is not None: + decls = self._build_declarations( + spec=spec, + decls=p[2]) + + elif len(spec['type']) == 1: + # Anonymous struct/union, gcc extension, C1x feature. + # Although the standard only allows structs/unions here, I see no + # reason to disallow other types since some compilers have typedefs + # here, and pycparser isn't about rejecting all invalid code. + # + node = spec['type'][0] + if isinstance(node, c_ast.Node): + decl_type = node + else: + decl_type = c_ast.IdentifierType(node) + + decls = self._build_declarations( + spec=spec, + decls=[dict(decl=decl_type)]) + + else: + # Structure/union members can have the same names as typedefs. + # The trouble is that the member's name gets grouped into + # specifier_qualifier_list; _build_declarations compensates. + # + decls = self._build_declarations( + spec=spec, + decls=[dict(decl=None, init=None)]) + + p[0] = decls + + def p_struct_declaration_2(self, p): + """ struct_declaration : SEMI + """ + p[0] = None + + def p_struct_declaration_3(self, p): + """ struct_declaration : pppragma_directive + """ + p[0] = [p[1]] + + def p_struct_declarator_list(self, p): + """ struct_declarator_list : struct_declarator + | struct_declarator_list COMMA struct_declarator + """ + p[0] = p[1] + [p[3]] if len(p) == 4 else [p[1]] + + # struct_declarator passes up a dict with the keys: decl (for + # the underlying declarator) and bitsize (for the bitsize) + # + def p_struct_declarator_1(self, p): + """ struct_declarator : declarator + """ + p[0] = {'decl': p[1], 'bitsize': None} + + def p_struct_declarator_2(self, p): + """ struct_declarator : declarator COLON constant_expression + | COLON constant_expression + """ + if len(p) > 3: + p[0] = {'decl': p[1], 'bitsize': p[3]} + else: + p[0] = {'decl': c_ast.TypeDecl(None, None, None, None), 'bitsize': p[2]} + + def p_enum_specifier_1(self, p): + """ enum_specifier : ENUM ID + | ENUM TYPEID + """ + p[0] = c_ast.Enum(p[2], None, self._token_coord(p, 1)) + + def p_enum_specifier_2(self, p): + """ enum_specifier : ENUM brace_open enumerator_list brace_close + """ + p[0] = c_ast.Enum(None, p[3], self._token_coord(p, 1)) + + def p_enum_specifier_3(self, p): + """ enum_specifier : ENUM ID brace_open enumerator_list brace_close + | ENUM TYPEID brace_open enumerator_list brace_close + """ + p[0] = c_ast.Enum(p[2], p[4], self._token_coord(p, 1)) + + def p_enumerator_list(self, p): + """ enumerator_list : enumerator + | enumerator_list COMMA + | enumerator_list COMMA enumerator + """ + if len(p) == 2: + p[0] = c_ast.EnumeratorList([p[1]], p[1].coord) + elif len(p) == 3: + p[0] = p[1] + else: + p[1].enumerators.append(p[3]) + p[0] = p[1] + + def p_alignment_specifier(self, p): + """ alignment_specifier : _ALIGNAS LPAREN type_name RPAREN + | _ALIGNAS LPAREN constant_expression RPAREN + """ + p[0] = c_ast.Alignas(p[3], self._token_coord(p, 1)) + + def p_enumerator(self, p): + """ enumerator : ID + | ID EQUALS constant_expression + """ + if len(p) == 2: + enumerator = c_ast.Enumerator( + p[1], None, + self._token_coord(p, 1)) + else: + enumerator = c_ast.Enumerator( + p[1], p[3], + self._token_coord(p, 1)) + self._add_identifier(enumerator.name, enumerator.coord) + + p[0] = enumerator + + def p_declarator(self, p): + """ declarator : id_declarator + | typeid_declarator + """ + p[0] = p[1] + + @parameterized(('id', 'ID'), ('typeid', 'TYPEID'), ('typeid_noparen', 'TYPEID')) + def p_xxx_declarator_1(self, p): + """ xxx_declarator : direct_xxx_declarator + """ + p[0] = p[1] + + @parameterized(('id', 'ID'), ('typeid', 'TYPEID'), ('typeid_noparen', 'TYPEID')) + def p_xxx_declarator_2(self, p): + """ xxx_declarator : pointer direct_xxx_declarator + """ + p[0] = self._type_modify_decl(p[2], p[1]) + + @parameterized(('id', 'ID'), ('typeid', 'TYPEID'), ('typeid_noparen', 'TYPEID')) + def p_direct_xxx_declarator_1(self, p): + """ direct_xxx_declarator : yyy + """ + p[0] = c_ast.TypeDecl( + declname=p[1], + type=None, + quals=None, + align=None, + coord=self._token_coord(p, 1)) + + @parameterized(('id', 'ID'), ('typeid', 'TYPEID')) + def p_direct_xxx_declarator_2(self, p): + """ direct_xxx_declarator : LPAREN xxx_declarator RPAREN + """ + p[0] = p[2] + + @parameterized(('id', 'ID'), ('typeid', 'TYPEID'), ('typeid_noparen', 'TYPEID')) + def p_direct_xxx_declarator_3(self, p): + """ direct_xxx_declarator : direct_xxx_declarator LBRACKET type_qualifier_list_opt assignment_expression_opt RBRACKET + """ + quals = (p[3] if len(p) > 5 else []) or [] + # Accept dimension qualifiers + # Per C99 6.7.5.3 p7 + arr = c_ast.ArrayDecl( + type=None, + dim=p[4] if len(p) > 5 else p[3], + dim_quals=quals, + coord=p[1].coord) + + p[0] = self._type_modify_decl(decl=p[1], modifier=arr) + + @parameterized(('id', 'ID'), ('typeid', 'TYPEID'), ('typeid_noparen', 'TYPEID')) + def p_direct_xxx_declarator_4(self, p): + """ direct_xxx_declarator : direct_xxx_declarator LBRACKET STATIC type_qualifier_list_opt assignment_expression RBRACKET + | direct_xxx_declarator LBRACKET type_qualifier_list STATIC assignment_expression RBRACKET + """ + # Using slice notation for PLY objects doesn't work in Python 3 for the + # version of PLY embedded with pycparser; see PLY Google Code issue 30. + # Work around that here by listing the two elements separately. + listed_quals = [item if isinstance(item, list) else [item] + for item in [p[3],p[4]]] + dim_quals = [qual for sublist in listed_quals for qual in sublist + if qual is not None] + arr = c_ast.ArrayDecl( + type=None, + dim=p[5], + dim_quals=dim_quals, + coord=p[1].coord) + + p[0] = self._type_modify_decl(decl=p[1], modifier=arr) + + # Special for VLAs + # + @parameterized(('id', 'ID'), ('typeid', 'TYPEID'), ('typeid_noparen', 'TYPEID')) + def p_direct_xxx_declarator_5(self, p): + """ direct_xxx_declarator : direct_xxx_declarator LBRACKET type_qualifier_list_opt TIMES RBRACKET + """ + arr = c_ast.ArrayDecl( + type=None, + dim=c_ast.ID(p[4], self._token_coord(p, 4)), + dim_quals=p[3] if p[3] is not None else [], + coord=p[1].coord) + + p[0] = self._type_modify_decl(decl=p[1], modifier=arr) + + @parameterized(('id', 'ID'), ('typeid', 'TYPEID'), ('typeid_noparen', 'TYPEID')) + def p_direct_xxx_declarator_6(self, p): + """ direct_xxx_declarator : direct_xxx_declarator LPAREN parameter_type_list RPAREN + | direct_xxx_declarator LPAREN identifier_list_opt RPAREN + """ + func = c_ast.FuncDecl( + args=p[3], + type=None, + coord=p[1].coord) + + # To see why _get_yacc_lookahead_token is needed, consider: + # typedef char TT; + # void foo(int TT) { TT = 10; } + # Outside the function, TT is a typedef, but inside (starting and + # ending with the braces) it's a parameter. The trouble begins with + # yacc's lookahead token. We don't know if we're declaring or + # defining a function until we see LBRACE, but if we wait for yacc to + # trigger a rule on that token, then TT will have already been read + # and incorrectly interpreted as TYPEID. We need to add the + # parameters to the scope the moment the lexer sees LBRACE. + # + if self._get_yacc_lookahead_token().type == "LBRACE": + if func.args is not None: + for param in func.args.params: + if isinstance(param, c_ast.EllipsisParam): break + self._add_identifier(param.name, param.coord) + + p[0] = self._type_modify_decl(decl=p[1], modifier=func) + + def p_pointer(self, p): + """ pointer : TIMES type_qualifier_list_opt + | TIMES type_qualifier_list_opt pointer + """ + coord = self._token_coord(p, 1) + # Pointer decls nest from inside out. This is important when different + # levels have different qualifiers. For example: + # + # char * const * p; + # + # Means "pointer to const pointer to char" + # + # While: + # + # char ** const p; + # + # Means "const pointer to pointer to char" + # + # So when we construct PtrDecl nestings, the leftmost pointer goes in + # as the most nested type. + nested_type = c_ast.PtrDecl(quals=p[2] or [], type=None, coord=coord) + if len(p) > 3: + tail_type = p[3] + while tail_type.type is not None: + tail_type = tail_type.type + tail_type.type = nested_type + p[0] = p[3] + else: + p[0] = nested_type + + def p_type_qualifier_list(self, p): + """ type_qualifier_list : type_qualifier + | type_qualifier_list type_qualifier + """ + p[0] = [p[1]] if len(p) == 2 else p[1] + [p[2]] + + def p_parameter_type_list(self, p): + """ parameter_type_list : parameter_list + | parameter_list COMMA ELLIPSIS + """ + if len(p) > 2: + p[1].params.append(c_ast.EllipsisParam(self._token_coord(p, 3))) + + p[0] = p[1] + + def p_parameter_list(self, p): + """ parameter_list : parameter_declaration + | parameter_list COMMA parameter_declaration + """ + if len(p) == 2: # single parameter + p[0] = c_ast.ParamList([p[1]], p[1].coord) + else: + p[1].params.append(p[3]) + p[0] = p[1] + + # From ISO/IEC 9899:TC2, 6.7.5.3.11: + # "If, in a parameter declaration, an identifier can be treated either + # as a typedef name or as a parameter name, it shall be taken as a + # typedef name." + # + # Inside a parameter declaration, once we've reduced declaration specifiers, + # if we shift in an LPAREN and see a TYPEID, it could be either an abstract + # declarator or a declarator nested inside parens. This rule tells us to + # always treat it as an abstract declarator. Therefore, we only accept + # `id_declarator`s and `typeid_noparen_declarator`s. + def p_parameter_declaration_1(self, p): + """ parameter_declaration : declaration_specifiers id_declarator + | declaration_specifiers typeid_noparen_declarator + """ + spec = p[1] + if not spec['type']: + spec['type'] = [c_ast.IdentifierType(['int'], + coord=self._token_coord(p, 1))] + p[0] = self._build_declarations( + spec=spec, + decls=[dict(decl=p[2])])[0] + + def p_parameter_declaration_2(self, p): + """ parameter_declaration : declaration_specifiers abstract_declarator_opt + """ + spec = p[1] + if not spec['type']: + spec['type'] = [c_ast.IdentifierType(['int'], + coord=self._token_coord(p, 1))] + + # Parameters can have the same names as typedefs. The trouble is that + # the parameter's name gets grouped into declaration_specifiers, making + # it look like an old-style declaration; compensate. + # + if len(spec['type']) > 1 and len(spec['type'][-1].names) == 1 and \ + self._is_type_in_scope(spec['type'][-1].names[0]): + decl = self._build_declarations( + spec=spec, + decls=[dict(decl=p[2], init=None)])[0] + + # This truly is an old-style parameter declaration + # + else: + decl = c_ast.Typename( + name='', + quals=spec['qual'], + align=None, + type=p[2] or c_ast.TypeDecl(None, None, None, None), + coord=self._token_coord(p, 2)) + typename = spec['type'] + decl = self._fix_decl_name_type(decl, typename) + + p[0] = decl + + def p_identifier_list(self, p): + """ identifier_list : identifier + | identifier_list COMMA identifier + """ + if len(p) == 2: # single parameter + p[0] = c_ast.ParamList([p[1]], p[1].coord) + else: + p[1].params.append(p[3]) + p[0] = p[1] + + def p_initializer_1(self, p): + """ initializer : assignment_expression + """ + p[0] = p[1] + + def p_initializer_2(self, p): + """ initializer : brace_open initializer_list_opt brace_close + | brace_open initializer_list COMMA brace_close + """ + if p[2] is None: + p[0] = c_ast.InitList([], self._token_coord(p, 1)) + else: + p[0] = p[2] + + def p_initializer_list(self, p): + """ initializer_list : designation_opt initializer + | initializer_list COMMA designation_opt initializer + """ + if len(p) == 3: # single initializer + init = p[2] if p[1] is None else c_ast.NamedInitializer(p[1], p[2]) + p[0] = c_ast.InitList([init], p[2].coord) + else: + init = p[4] if p[3] is None else c_ast.NamedInitializer(p[3], p[4]) + p[1].exprs.append(init) + p[0] = p[1] + + def p_designation(self, p): + """ designation : designator_list EQUALS + """ + p[0] = p[1] + + # Designators are represented as a list of nodes, in the order in which + # they're written in the code. + # + def p_designator_list(self, p): + """ designator_list : designator + | designator_list designator + """ + p[0] = [p[1]] if len(p) == 2 else p[1] + [p[2]] + + def p_designator(self, p): + """ designator : LBRACKET constant_expression RBRACKET + | PERIOD identifier + """ + p[0] = p[2] + + def p_type_name(self, p): + """ type_name : specifier_qualifier_list abstract_declarator_opt + """ + typename = c_ast.Typename( + name='', + quals=p[1]['qual'][:], + align=None, + type=p[2] or c_ast.TypeDecl(None, None, None, None), + coord=self._token_coord(p, 2)) + + p[0] = self._fix_decl_name_type(typename, p[1]['type']) + + def p_abstract_declarator_1(self, p): + """ abstract_declarator : pointer + """ + dummytype = c_ast.TypeDecl(None, None, None, None) + p[0] = self._type_modify_decl( + decl=dummytype, + modifier=p[1]) + + def p_abstract_declarator_2(self, p): + """ abstract_declarator : pointer direct_abstract_declarator + """ + p[0] = self._type_modify_decl(p[2], p[1]) + + def p_abstract_declarator_3(self, p): + """ abstract_declarator : direct_abstract_declarator + """ + p[0] = p[1] + + # Creating and using direct_abstract_declarator_opt here + # instead of listing both direct_abstract_declarator and the + # lack of it in the beginning of _1 and _2 caused two + # shift/reduce errors. + # + def p_direct_abstract_declarator_1(self, p): + """ direct_abstract_declarator : LPAREN abstract_declarator RPAREN """ + p[0] = p[2] + + def p_direct_abstract_declarator_2(self, p): + """ direct_abstract_declarator : direct_abstract_declarator LBRACKET assignment_expression_opt RBRACKET + """ + arr = c_ast.ArrayDecl( + type=None, + dim=p[3], + dim_quals=[], + coord=p[1].coord) + + p[0] = self._type_modify_decl(decl=p[1], modifier=arr) + + def p_direct_abstract_declarator_3(self, p): + """ direct_abstract_declarator : LBRACKET type_qualifier_list_opt assignment_expression_opt RBRACKET + """ + quals = (p[2] if len(p) > 4 else []) or [] + p[0] = c_ast.ArrayDecl( + type=c_ast.TypeDecl(None, None, None, None), + dim=p[3] if len(p) > 4 else p[2], + dim_quals=quals, + coord=self._token_coord(p, 1)) + + def p_direct_abstract_declarator_4(self, p): + """ direct_abstract_declarator : direct_abstract_declarator LBRACKET TIMES RBRACKET + """ + arr = c_ast.ArrayDecl( + type=None, + dim=c_ast.ID(p[3], self._token_coord(p, 3)), + dim_quals=[], + coord=p[1].coord) + + p[0] = self._type_modify_decl(decl=p[1], modifier=arr) + + def p_direct_abstract_declarator_5(self, p): + """ direct_abstract_declarator : LBRACKET TIMES RBRACKET + """ + p[0] = c_ast.ArrayDecl( + type=c_ast.TypeDecl(None, None, None, None), + dim=c_ast.ID(p[3], self._token_coord(p, 3)), + dim_quals=[], + coord=self._token_coord(p, 1)) + + def p_direct_abstract_declarator_6(self, p): + """ direct_abstract_declarator : direct_abstract_declarator LPAREN parameter_type_list_opt RPAREN + """ + func = c_ast.FuncDecl( + args=p[3], + type=None, + coord=p[1].coord) + + p[0] = self._type_modify_decl(decl=p[1], modifier=func) + + def p_direct_abstract_declarator_7(self, p): + """ direct_abstract_declarator : LPAREN parameter_type_list_opt RPAREN + """ + p[0] = c_ast.FuncDecl( + args=p[2], + type=c_ast.TypeDecl(None, None, None, None), + coord=self._token_coord(p, 1)) + + # declaration is a list, statement isn't. To make it consistent, block_item + # will always be a list + # + def p_block_item(self, p): + """ block_item : declaration + | statement + """ + p[0] = p[1] if isinstance(p[1], list) else [p[1]] + + # Since we made block_item a list, this just combines lists + # + def p_block_item_list(self, p): + """ block_item_list : block_item + | block_item_list block_item + """ + # Empty block items (plain ';') produce [None], so ignore them + p[0] = p[1] if (len(p) == 2 or p[2] == [None]) else p[1] + p[2] + + def p_compound_statement_1(self, p): + """ compound_statement : brace_open block_item_list_opt brace_close """ + p[0] = c_ast.Compound( + block_items=p[2], + coord=self._token_coord(p, 1)) + + def p_labeled_statement_1(self, p): + """ labeled_statement : ID COLON pragmacomp_or_statement """ + p[0] = c_ast.Label(p[1], p[3], self._token_coord(p, 1)) + + def p_labeled_statement_2(self, p): + """ labeled_statement : CASE constant_expression COLON pragmacomp_or_statement """ + p[0] = c_ast.Case(p[2], [p[4]], self._token_coord(p, 1)) + + def p_labeled_statement_3(self, p): + """ labeled_statement : DEFAULT COLON pragmacomp_or_statement """ + p[0] = c_ast.Default([p[3]], self._token_coord(p, 1)) + + def p_selection_statement_1(self, p): + """ selection_statement : IF LPAREN expression RPAREN pragmacomp_or_statement """ + p[0] = c_ast.If(p[3], p[5], None, self._token_coord(p, 1)) + + def p_selection_statement_2(self, p): + """ selection_statement : IF LPAREN expression RPAREN statement ELSE pragmacomp_or_statement """ + p[0] = c_ast.If(p[3], p[5], p[7], self._token_coord(p, 1)) + + def p_selection_statement_3(self, p): + """ selection_statement : SWITCH LPAREN expression RPAREN pragmacomp_or_statement """ + p[0] = fix_switch_cases( + c_ast.Switch(p[3], p[5], self._token_coord(p, 1))) + + def p_iteration_statement_1(self, p): + """ iteration_statement : WHILE LPAREN expression RPAREN pragmacomp_or_statement """ + p[0] = c_ast.While(p[3], p[5], self._token_coord(p, 1)) + + def p_iteration_statement_2(self, p): + """ iteration_statement : DO pragmacomp_or_statement WHILE LPAREN expression RPAREN SEMI """ + p[0] = c_ast.DoWhile(p[5], p[2], self._token_coord(p, 1)) + + def p_iteration_statement_3(self, p): + """ iteration_statement : FOR LPAREN expression_opt SEMI expression_opt SEMI expression_opt RPAREN pragmacomp_or_statement """ + p[0] = c_ast.For(p[3], p[5], p[7], p[9], self._token_coord(p, 1)) + + def p_iteration_statement_4(self, p): + """ iteration_statement : FOR LPAREN declaration expression_opt SEMI expression_opt RPAREN pragmacomp_or_statement """ + p[0] = c_ast.For(c_ast.DeclList(p[3], self._token_coord(p, 1)), + p[4], p[6], p[8], self._token_coord(p, 1)) + + def p_jump_statement_1(self, p): + """ jump_statement : GOTO ID SEMI """ + p[0] = c_ast.Goto(p[2], self._token_coord(p, 1)) + + def p_jump_statement_2(self, p): + """ jump_statement : BREAK SEMI """ + p[0] = c_ast.Break(self._token_coord(p, 1)) + + def p_jump_statement_3(self, p): + """ jump_statement : CONTINUE SEMI """ + p[0] = c_ast.Continue(self._token_coord(p, 1)) + + def p_jump_statement_4(self, p): + """ jump_statement : RETURN expression SEMI + | RETURN SEMI + """ + p[0] = c_ast.Return(p[2] if len(p) == 4 else None, self._token_coord(p, 1)) + + def p_expression_statement(self, p): + """ expression_statement : expression_opt SEMI """ + if p[1] is None: + p[0] = c_ast.EmptyStatement(self._token_coord(p, 2)) + else: + p[0] = p[1] + + def p_expression(self, p): + """ expression : assignment_expression + | expression COMMA assignment_expression + """ + if len(p) == 2: + p[0] = p[1] + else: + if not isinstance(p[1], c_ast.ExprList): + p[1] = c_ast.ExprList([p[1]], p[1].coord) + + p[1].exprs.append(p[3]) + p[0] = p[1] + + def p_parenthesized_compound_expression(self, p): + """ assignment_expression : LPAREN compound_statement RPAREN """ + p[0] = p[2] + + def p_typedef_name(self, p): + """ typedef_name : TYPEID """ + p[0] = c_ast.IdentifierType([p[1]], coord=self._token_coord(p, 1)) + + def p_assignment_expression(self, p): + """ assignment_expression : conditional_expression + | unary_expression assignment_operator assignment_expression + """ + if len(p) == 2: + p[0] = p[1] + else: + p[0] = c_ast.Assignment(p[2], p[1], p[3], p[1].coord) + + # K&R2 defines these as many separate rules, to encode + # precedence and associativity. Why work hard ? I'll just use + # the built in precedence/associativity specification feature + # of PLY. (see precedence declaration above) + # + def p_assignment_operator(self, p): + """ assignment_operator : EQUALS + | XOREQUAL + | TIMESEQUAL + | DIVEQUAL + | MODEQUAL + | PLUSEQUAL + | MINUSEQUAL + | LSHIFTEQUAL + | RSHIFTEQUAL + | ANDEQUAL + | OREQUAL + """ + p[0] = p[1] + + def p_constant_expression(self, p): + """ constant_expression : conditional_expression """ + p[0] = p[1] + + def p_conditional_expression(self, p): + """ conditional_expression : binary_expression + | binary_expression CONDOP expression COLON conditional_expression + """ + if len(p) == 2: + p[0] = p[1] + else: + p[0] = c_ast.TernaryOp(p[1], p[3], p[5], p[1].coord) + + def p_binary_expression(self, p): + """ binary_expression : cast_expression + | binary_expression TIMES binary_expression + | binary_expression DIVIDE binary_expression + | binary_expression MOD binary_expression + | binary_expression PLUS binary_expression + | binary_expression MINUS binary_expression + | binary_expression RSHIFT binary_expression + | binary_expression LSHIFT binary_expression + | binary_expression LT binary_expression + | binary_expression LE binary_expression + | binary_expression GE binary_expression + | binary_expression GT binary_expression + | binary_expression EQ binary_expression + | binary_expression NE binary_expression + | binary_expression AND binary_expression + | binary_expression OR binary_expression + | binary_expression XOR binary_expression + | binary_expression LAND binary_expression + | binary_expression LOR binary_expression + """ + if len(p) == 2: + p[0] = p[1] + else: + p[0] = c_ast.BinaryOp(p[2], p[1], p[3], p[1].coord) + + def p_cast_expression_1(self, p): + """ cast_expression : unary_expression """ + p[0] = p[1] + + def p_cast_expression_2(self, p): + """ cast_expression : LPAREN type_name RPAREN cast_expression """ + p[0] = c_ast.Cast(p[2], p[4], self._token_coord(p, 1)) + + def p_unary_expression_1(self, p): + """ unary_expression : postfix_expression """ + p[0] = p[1] + + def p_unary_expression_2(self, p): + """ unary_expression : PLUSPLUS unary_expression + | MINUSMINUS unary_expression + | unary_operator cast_expression + """ + p[0] = c_ast.UnaryOp(p[1], p[2], p[2].coord) + + def p_unary_expression_3(self, p): + """ unary_expression : SIZEOF unary_expression + | SIZEOF LPAREN type_name RPAREN + | _ALIGNOF LPAREN type_name RPAREN + """ + p[0] = c_ast.UnaryOp( + p[1], + p[2] if len(p) == 3 else p[3], + self._token_coord(p, 1)) + + def p_unary_operator(self, p): + """ unary_operator : AND + | TIMES + | PLUS + | MINUS + | NOT + | LNOT + """ + p[0] = p[1] + + def p_postfix_expression_1(self, p): + """ postfix_expression : primary_expression """ + p[0] = p[1] + + def p_postfix_expression_2(self, p): + """ postfix_expression : postfix_expression LBRACKET expression RBRACKET """ + p[0] = c_ast.ArrayRef(p[1], p[3], p[1].coord) + + def p_postfix_expression_3(self, p): + """ postfix_expression : postfix_expression LPAREN argument_expression_list RPAREN + | postfix_expression LPAREN RPAREN + """ + p[0] = c_ast.FuncCall(p[1], p[3] if len(p) == 5 else None, p[1].coord) + + def p_postfix_expression_4(self, p): + """ postfix_expression : postfix_expression PERIOD ID + | postfix_expression PERIOD TYPEID + | postfix_expression ARROW ID + | postfix_expression ARROW TYPEID + """ + field = c_ast.ID(p[3], self._token_coord(p, 3)) + p[0] = c_ast.StructRef(p[1], p[2], field, p[1].coord) + + def p_postfix_expression_5(self, p): + """ postfix_expression : postfix_expression PLUSPLUS + | postfix_expression MINUSMINUS + """ + p[0] = c_ast.UnaryOp('p' + p[2], p[1], p[1].coord) + + def p_postfix_expression_6(self, p): + """ postfix_expression : LPAREN type_name RPAREN brace_open initializer_list brace_close + | LPAREN type_name RPAREN brace_open initializer_list COMMA brace_close + """ + p[0] = c_ast.CompoundLiteral(p[2], p[5]) + + def p_primary_expression_1(self, p): + """ primary_expression : identifier """ + p[0] = p[1] + + def p_primary_expression_2(self, p): + """ primary_expression : constant """ + p[0] = p[1] + + def p_primary_expression_3(self, p): + """ primary_expression : unified_string_literal + | unified_wstring_literal + """ + p[0] = p[1] + + def p_primary_expression_4(self, p): + """ primary_expression : LPAREN expression RPAREN """ + p[0] = p[2] + + def p_primary_expression_5(self, p): + """ primary_expression : OFFSETOF LPAREN type_name COMMA offsetof_member_designator RPAREN + """ + coord = self._token_coord(p, 1) + p[0] = c_ast.FuncCall(c_ast.ID(p[1], coord), + c_ast.ExprList([p[3], p[5]], coord), + coord) + + def p_offsetof_member_designator(self, p): + """ offsetof_member_designator : identifier + | offsetof_member_designator PERIOD identifier + | offsetof_member_designator LBRACKET expression RBRACKET + """ + if len(p) == 2: + p[0] = p[1] + elif len(p) == 4: + p[0] = c_ast.StructRef(p[1], p[2], p[3], p[1].coord) + elif len(p) == 5: + p[0] = c_ast.ArrayRef(p[1], p[3], p[1].coord) + else: + raise NotImplementedError("Unexpected parsing state. len(p): %u" % len(p)) + + def p_argument_expression_list(self, p): + """ argument_expression_list : assignment_expression + | argument_expression_list COMMA assignment_expression + """ + if len(p) == 2: # single expr + p[0] = c_ast.ExprList([p[1]], p[1].coord) + else: + p[1].exprs.append(p[3]) + p[0] = p[1] + + def p_identifier(self, p): + """ identifier : ID """ + p[0] = c_ast.ID(p[1], self._token_coord(p, 1)) + + def p_constant_1(self, p): + """ constant : INT_CONST_DEC + | INT_CONST_OCT + | INT_CONST_HEX + | INT_CONST_BIN + | INT_CONST_CHAR + """ + uCount = 0 + lCount = 0 + for x in p[1][-3:]: + if x in ('l', 'L'): + lCount += 1 + elif x in ('u', 'U'): + uCount += 1 + t = '' + if uCount > 1: + raise ValueError('Constant cannot have more than one u/U suffix.') + elif lCount > 2: + raise ValueError('Constant cannot have more than two l/L suffix.') + prefix = 'unsigned ' * uCount + 'long ' * lCount + p[0] = c_ast.Constant( + prefix + 'int', p[1], self._token_coord(p, 1)) + + def p_constant_2(self, p): + """ constant : FLOAT_CONST + | HEX_FLOAT_CONST + """ + if 'x' in p[1].lower(): + t = 'float' + else: + if p[1][-1] in ('f', 'F'): + t = 'float' + elif p[1][-1] in ('l', 'L'): + t = 'long double' + else: + t = 'double' + + p[0] = c_ast.Constant( + t, p[1], self._token_coord(p, 1)) + + def p_constant_3(self, p): + """ constant : CHAR_CONST + | WCHAR_CONST + | U8CHAR_CONST + | U16CHAR_CONST + | U32CHAR_CONST + """ + p[0] = c_ast.Constant( + 'char', p[1], self._token_coord(p, 1)) + + # The "unified" string and wstring literal rules are for supporting + # concatenation of adjacent string literals. + # I.e. "hello " "world" is seen by the C compiler as a single string literal + # with the value "hello world" + # + def p_unified_string_literal(self, p): + """ unified_string_literal : STRING_LITERAL + | unified_string_literal STRING_LITERAL + """ + if len(p) == 2: # single literal + p[0] = c_ast.Constant( + 'string', p[1], self._token_coord(p, 1)) + else: + p[1].value = p[1].value[:-1] + p[2][1:] + p[0] = p[1] + + def p_unified_wstring_literal(self, p): + """ unified_wstring_literal : WSTRING_LITERAL + | U8STRING_LITERAL + | U16STRING_LITERAL + | U32STRING_LITERAL + | unified_wstring_literal WSTRING_LITERAL + | unified_wstring_literal U8STRING_LITERAL + | unified_wstring_literal U16STRING_LITERAL + | unified_wstring_literal U32STRING_LITERAL + """ + if len(p) == 2: # single literal + p[0] = c_ast.Constant( + 'string', p[1], self._token_coord(p, 1)) + else: + p[1].value = p[1].value.rstrip()[:-1] + p[2][2:] + p[0] = p[1] + + def p_brace_open(self, p): + """ brace_open : LBRACE + """ + p[0] = p[1] + p.set_lineno(0, p.lineno(1)) + + def p_brace_close(self, p): + """ brace_close : RBRACE + """ + p[0] = p[1] + p.set_lineno(0, p.lineno(1)) + + def p_empty(self, p): + 'empty : ' + p[0] = None + + def p_error(self, p): + # If error recovery is added here in the future, make sure + # _get_yacc_lookahead_token still works! + # + if p: + self._parse_error( + 'before: %s' % p.value, + self._coord(lineno=p.lineno, + column=self.clex.find_tok_column(p))) + else: + self._parse_error('At end of input', self.clex.filename) diff --git a/.venv/Lib/site-packages/pycparser/lextab.py b/.venv/Lib/site-packages/pycparser/lextab.py new file mode 100644 index 00000000..444b4656 --- /dev/null +++ b/.venv/Lib/site-packages/pycparser/lextab.py @@ -0,0 +1,10 @@ +# lextab.py. This file automatically created by PLY (version 3.10). Don't edit! +_tabversion = '3.10' +_lextokens = set(('INT_CONST_CHAR', 'VOID', 'LBRACKET', 'WCHAR_CONST', 'FLOAT_CONST', 'MINUS', 'RPAREN', 'STRUCT', 'LONG', 'PLUS', 'ELLIPSIS', 'U32STRING_LITERAL', 'GT', 'GOTO', 'ENUM', 'PERIOD', 'GE', 'INT_CONST_DEC', 'ARROW', '_STATIC_ASSERT', '__INT128', 'HEX_FLOAT_CONST', 'DOUBLE', 'MINUSEQUAL', 'INT_CONST_OCT', 'TIMESEQUAL', 'OR', 'SHORT', 'RETURN', 'RSHIFTEQUAL', '_ALIGNAS', 'RESTRICT', 'STATIC', 'SIZEOF', 'UNSIGNED', 'PLUSPLUS', 'COLON', 'WSTRING_LITERAL', 'DIVIDE', 'FOR', 'UNION', 'EQUALS', 'ELSE', 'ANDEQUAL', 'EQ', 'AND', 'TYPEID', 'LBRACE', 'PPHASH', 'INT', 'SIGNED', 'CONTINUE', 'NOT', 'OREQUAL', 'MOD', 'RSHIFT', 'DEFAULT', '_NORETURN', 'CHAR', 'WHILE', 'DIVEQUAL', '_ALIGNOF', 'EXTERN', 'LNOT', 'CASE', 'LAND', 'REGISTER', 'MODEQUAL', 'NE', 'SWITCH', 'INT_CONST_HEX', '_COMPLEX', 'PPPRAGMASTR', 'PLUSEQUAL', 'U32CHAR_CONST', 'CONDOP', 'U8STRING_LITERAL', 'BREAK', 'VOLATILE', 'PPPRAGMA', 'INLINE', 'INT_CONST_BIN', 'DO', 'U8CHAR_CONST', 'CONST', 'U16STRING_LITERAL', 'LOR', 'CHAR_CONST', 'LSHIFT', 'RBRACE', '_BOOL', 'LE', 'SEMI', '_THREAD_LOCAL', 'LT', 'COMMA', 'U16CHAR_CONST', 'OFFSETOF', '_ATOMIC', 'TYPEDEF', 'XOR', 'AUTO', 'TIMES', 'LPAREN', 'MINUSMINUS', 'ID', 'IF', 'STRING_LITERAL', 'FLOAT', 'XOREQUAL', 'LSHIFTEQUAL', 'RBRACKET')) +_lexreflags = 64 +_lexliterals = '' +_lexstateinfo = {'ppline': 'exclusive', 'pppragma': 'exclusive', 'INITIAL': 'inclusive'} +_lexstatere = {'ppline': [('(?P"([^"\\\\\\n]|(\\\\[0-9a-zA-Z._~!=&\\^\\-\\\\?\'"]))*")|(?P(0(([uU]ll)|([uU]LL)|(ll[uU]?)|(LL[uU]?)|([uU][lL])|([lL][uU]?)|[uU])?)|([1-9][0-9]*(([uU]ll)|([uU]LL)|(ll[uU]?)|(LL[uU]?)|([uU][lL])|([lL][uU]?)|[uU])?))|(?P\\n)|(?Pline)', [None, ('t_ppline_FILENAME', 'FILENAME'), None, None, ('t_ppline_LINE_NUMBER', 'LINE_NUMBER'), None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_ppline_NEWLINE', 'NEWLINE'), ('t_ppline_PPLINE', 'PPLINE')])], 'pppragma': [('(?P\\n)|(?Ppragma)|(?P.+)', [None, ('t_pppragma_NEWLINE', 'NEWLINE'), ('t_pppragma_PPPRAGMA', 'PPPRAGMA'), ('t_pppragma_STR', 'STR')])], 'INITIAL': [('(?P[ \\t]*\\#)|(?P\\n+)|(?P\\{)|(?P\\})|(?P((((([0-9]*\\.[0-9]+)|([0-9]+\\.))([eE][-+]?[0-9]+)?)|([0-9]+([eE][-+]?[0-9]+)))[FfLl]?))|(?P(0[xX]([0-9a-fA-F]+|((([0-9a-fA-F]+)?\\.[0-9a-fA-F]+)|([0-9a-fA-F]+\\.)))([pP][+-]?[0-9]+)[FfLl]?))|(?P0[xX][0-9a-fA-F]+(([uU]ll)|([uU]LL)|(ll[uU]?)|(LL[uU]?)|([uU][lL])|([lL][uU]?)|[uU])?)|(?P0[bB][01]+(([uU]ll)|([uU]LL)|(ll[uU]?)|(LL[uU]?)|([uU][lL])|([lL][uU]?)|[uU])?)', [None, ('t_PPHASH', 'PPHASH'), ('t_NEWLINE', 'NEWLINE'), ('t_LBRACE', 'LBRACE'), ('t_RBRACE', 'RBRACE'), ('t_FLOAT_CONST', 'FLOAT_CONST'), None, None, None, None, None, None, None, None, None, ('t_HEX_FLOAT_CONST', 'HEX_FLOAT_CONST'), None, None, None, None, None, None, None, ('t_INT_CONST_HEX', 'INT_CONST_HEX'), None, None, None, None, None, None, None, ('t_INT_CONST_BIN', 'INT_CONST_BIN')]), ('(?P0[0-7]*[89])|(?P0[0-7]*(([uU]ll)|([uU]LL)|(ll[uU]?)|(LL[uU]?)|([uU][lL])|([lL][uU]?)|[uU])?)|(?P(0(([uU]ll)|([uU]LL)|(ll[uU]?)|(LL[uU]?)|([uU][lL])|([lL][uU]?)|[uU])?)|([1-9][0-9]*(([uU]ll)|([uU]LL)|(ll[uU]?)|(LL[uU]?)|([uU][lL])|([lL][uU]?)|[uU])?))|(?P\'([^\'\\\\\\n]|(\\\\(([a-wyzA-Z._~!=&\\^\\-\\\\?\'"]|x(?![0-9a-fA-F]))|(\\d+)(?!\\d)|(x[0-9a-fA-F]+)(?![0-9a-fA-F])))){2,4}\')|(?P\'([^\'\\\\\\n]|(\\\\(([a-wyzA-Z._~!=&\\^\\-\\\\?\'"]|x(?![0-9a-fA-F]))|(\\d+)(?!\\d)|(x[0-9a-fA-F]+)(?![0-9a-fA-F]))))\')|(?PL\'([^\'\\\\\\n]|(\\\\(([a-wyzA-Z._~!=&\\^\\-\\\\?\'"]|x(?![0-9a-fA-F]))|(\\d+)(?!\\d)|(x[0-9a-fA-F]+)(?![0-9a-fA-F]))))\')|(?Pu8\'([^\'\\\\\\n]|(\\\\(([a-wyzA-Z._~!=&\\^\\-\\\\?\'"]|x(?![0-9a-fA-F]))|(\\d+)(?!\\d)|(x[0-9a-fA-F]+)(?![0-9a-fA-F]))))\')|(?Pu\'([^\'\\\\\\n]|(\\\\(([a-wyzA-Z._~!=&\\^\\-\\\\?\'"]|x(?![0-9a-fA-F]))|(\\d+)(?!\\d)|(x[0-9a-fA-F]+)(?![0-9a-fA-F]))))\')|(?PU\'([^\'\\\\\\n]|(\\\\(([a-wyzA-Z._~!=&\\^\\-\\\\?\'"]|x(?![0-9a-fA-F]))|(\\d+)(?!\\d)|(x[0-9a-fA-F]+)(?![0-9a-fA-F]))))\')', [None, ('t_BAD_CONST_OCT', 'BAD_CONST_OCT'), ('t_INT_CONST_OCT', 'INT_CONST_OCT'), None, None, None, None, None, None, None, ('t_INT_CONST_DEC', 'INT_CONST_DEC'), None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_INT_CONST_CHAR', 'INT_CONST_CHAR'), None, None, None, None, None, None, ('t_CHAR_CONST', 'CHAR_CONST'), None, None, None, None, None, None, ('t_WCHAR_CONST', 'WCHAR_CONST'), None, None, None, None, None, None, ('t_U8CHAR_CONST', 'U8CHAR_CONST'), None, None, None, None, None, None, ('t_U16CHAR_CONST', 'U16CHAR_CONST'), None, None, None, None, None, None, ('t_U32CHAR_CONST', 'U32CHAR_CONST')]), ('(?P(\'([^\'\\\\\\n]|(\\\\(([a-wyzA-Z._~!=&\\^\\-\\\\?\'"]|x(?![0-9a-fA-F]))|(\\d+)(?!\\d)|(x[0-9a-fA-F]+)(?![0-9a-fA-F]))))*\\n)|(\'([^\'\\\\\\n]|(\\\\(([a-wyzA-Z._~!=&\\^\\-\\\\?\'"]|x(?![0-9a-fA-F]))|(\\d+)(?!\\d)|(x[0-9a-fA-F]+)(?![0-9a-fA-F]))))*$))|(?P(\'([^\'\\\\\\n]|(\\\\(([a-wyzA-Z._~!=&\\^\\-\\\\?\'"]|x(?![0-9a-fA-F]))|(\\d+)(?!\\d)|(x[0-9a-fA-F]+)(?![0-9a-fA-F]))))[^\'\n]+\')|(\'\')|(\'([\\\\][^a-zA-Z._~^!=&\\^\\-\\\\?\'"x0-9])[^\'\\n]*\'))|(?PL"([^"\\\\\\n]|(\\\\[0-9a-zA-Z._~!=&\\^\\-\\\\?\'"]))*")|(?Pu8"([^"\\\\\\n]|(\\\\[0-9a-zA-Z._~!=&\\^\\-\\\\?\'"]))*")|(?Pu"([^"\\\\\\n]|(\\\\[0-9a-zA-Z._~!=&\\^\\-\\\\?\'"]))*")|(?PU"([^"\\\\\\n]|(\\\\[0-9a-zA-Z._~!=&\\^\\-\\\\?\'"]))*")|(?P"([^"\\\\\\n]|(\\\\[0-9a-zA-Z._~!=&\\^\\-\\\\?\'"]))*([\\\\][^a-zA-Z._~^!=&\\^\\-\\\\?\'"x0-9])([^"\\\\\\n]|(\\\\[0-9a-zA-Z._~!=&\\^\\-\\\\?\'"]))*")|(?P[a-zA-Z_$][0-9a-zA-Z_$]*)|(?P"([^"\\\\\\n]|(\\\\[0-9a-zA-Z._~!=&\\^\\-\\\\?\'"]))*")|(?P\\.\\.\\.)|(?P\\+\\+)|(?P\\|\\|)|(?P\\^=)|(?P\\|=)|(?P<<=)|(?P>>=)|(?P\\+=)|(?P\\*=)', [None, ('t_UNMATCHED_QUOTE', 'UNMATCHED_QUOTE'), None, None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_BAD_CHAR_CONST', 'BAD_CHAR_CONST'), None, None, None, None, None, None, None, None, None, None, ('t_WSTRING_LITERAL', 'WSTRING_LITERAL'), None, None, ('t_U8STRING_LITERAL', 'U8STRING_LITERAL'), None, None, ('t_U16STRING_LITERAL', 'U16STRING_LITERAL'), None, None, ('t_U32STRING_LITERAL', 'U32STRING_LITERAL'), None, None, ('t_BAD_STRING_LITERAL', 'BAD_STRING_LITERAL'), None, None, None, None, None, ('t_ID', 'ID'), (None, 'STRING_LITERAL'), None, None, (None, 'ELLIPSIS'), (None, 'PLUSPLUS'), (None, 'LOR'), (None, 'XOREQUAL'), (None, 'OREQUAL'), (None, 'LSHIFTEQUAL'), (None, 'RSHIFTEQUAL'), (None, 'PLUSEQUAL'), (None, 'TIMESEQUAL')]), ('(?P\\+)|(?P%=)|(?P/=)|(?P\\])|(?P\\?)|(?P\\^)|(?P<<)|(?P<=)|(?P\\()|(?P->)|(?P==)|(?P!=)|(?P--)|(?P\\|)|(?P\\*)|(?P\\[)|(?P>=)|(?P\\))|(?P&&)|(?P>>)|(?P-=)|(?P\\.)|(?P&=)|(?P=)|(?P<)|(?P,)|(?P/)|(?P&)|(?P%)|(?P;)|(?P-)|(?P>)|(?P:)|(?P~)|(?P!)', [None, (None, 'PLUS'), (None, 'MODEQUAL'), (None, 'DIVEQUAL'), (None, 'RBRACKET'), (None, 'CONDOP'), (None, 'XOR'), (None, 'LSHIFT'), (None, 'LE'), (None, 'LPAREN'), (None, 'ARROW'), (None, 'EQ'), (None, 'NE'), (None, 'MINUSMINUS'), (None, 'OR'), (None, 'TIMES'), (None, 'LBRACKET'), (None, 'GE'), (None, 'RPAREN'), (None, 'LAND'), (None, 'RSHIFT'), (None, 'MINUSEQUAL'), (None, 'PERIOD'), (None, 'ANDEQUAL'), (None, 'EQUALS'), (None, 'LT'), (None, 'COMMA'), (None, 'DIVIDE'), (None, 'AND'), (None, 'MOD'), (None, 'SEMI'), (None, 'MINUS'), (None, 'GT'), (None, 'COLON'), (None, 'NOT'), (None, 'LNOT')])]} +_lexstateignore = {'ppline': ' \t', 'pppragma': ' \t', 'INITIAL': ' \t'} +_lexstateerrorf = {'ppline': 't_ppline_error', 'pppragma': 't_pppragma_error', 'INITIAL': 't_error'} +_lexstateeoff = {} diff --git a/.venv/Lib/site-packages/pycparser/ply/__init__.py b/.venv/Lib/site-packages/pycparser/ply/__init__.py new file mode 100644 index 00000000..6e53cddc --- /dev/null +++ b/.venv/Lib/site-packages/pycparser/ply/__init__.py @@ -0,0 +1,5 @@ +# PLY package +# Author: David Beazley (dave@dabeaz.com) + +__version__ = '3.9' +__all__ = ['lex','yacc'] diff --git a/.venv/Lib/site-packages/pycparser/ply/__pycache__/__init__.cpython-311.pyc b/.venv/Lib/site-packages/pycparser/ply/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..30ef9b28cdbf0393198696e6259166d26bfabca6 GIT binary patch literal 251 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 UQjD*Dno3p+bjB^nF&p9kKg{xhXaE2J literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/pycparser/ply/__pycache__/ctokens.cpython-311.pyc b/.venv/Lib/site-packages/pycparser/ply/__pycache__/ctokens.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e9c078f9c6fc9802add1e2d1a287d7ffd1da1c66 GIT binary patch literal 2458 zcmZ`)%WoP-7~frBdFO2s+j-bdY_kx+c~))x5H%Z{W&sCq+l<$t4zsbG*w_LbC6rcs zNbgluDc7inR#DIWLn8GM&8bqQO1)XijZ=R!yWm(+)|&78eUJHO=JW8I-=ooxgs->s zr?nN4q<^^4{}dOz`xoG)v?)>PSD8puCNfosLOsMoy~Im>#79-4Qa|z20140_3DOV= z(J%?q2#L@riPB@_7(Gso(-Y(bJxNZ|Q{)sqO-|D@e07(Lm?Gx=LQ}Q{c zR`0Lq(Efa}sxRqf=DTB*vQ?&5s^xrfi3Jyzv*qk!6%p@>v07oiLcYjVHDAyxOwHxL z%I9>Z7D~BQqr{X_nR&9s9P<=QRp$8yrfO7{^LJ3O>}Zbxr`O;~UV~>T1|K?8mY|oQ z^?OVyqNaXtHEUE@NGv4`7QlKg!io+G@_jilBsS;Zu(PgfIEy<*0BgGl8+4Gr4}$sP zVp%Wf#VQNt^gi@u%jMG7%#S`4v*r6Z)JnFj7jY;@2aGS!rMr5S1Xbi>H6RPvRMVkUcX3M$c)Gd+0{sN0jLdh!oI4?4>1 zY)6@&?|99w+3hG(2#ojS*`7R)&>TV-a~R`uJ$bIAKwi^+WqGJQ(l3g?K4- zrN_|D_e_2~$b`R771Ar7|G`J)-;n*sU`8h@Np+<*u)7j|dP?V5#!ST1U9-V=nZSQJ zq-(tS{?tY{FT4r*)#mkKKs=3e1`YzpSY?`aPkE+WX z^(QT}Z0%S(53Q!vs#}e^Wu~86ji;uu_0Vi>wXM`1k~TK2mbv%5zPHhAS*Av&ic^At(#b`}K*wWu#--{)?_@emJ#xI*McYfY^m3tG@{)%aD zyc&1E4M*(dcSx0v^py8U^mGQ`<2|MFM|z}YGUUi2Q<^!brq0DOgwu-Vmw+sS zov*C)H(!FQ%QJ={j%@yo_v~Q1O#{)QcAKeA2cT<$-TdvE!*2i%!v)$km*aq3mh-l2 z;4oji#z_o{vltX-J0!V$2jnsyLY(ukhG0Fe`3zJ6^Ff05IMxLg5)23rI1ohyKUMfK z-{ZlM*p)+FzymG}JLhl$nDQPUMzMroU?&LkeNIG?0W0Dz^w|*Z0Y#$rAveM}WJfg1 z;YZBuGbC?>%Z*scL8vz1N#Frf@?6fE;=C?fqNc-_2)c}k#tF_8Ar~_mh+UMfcuzX(}U+sT=OQsF0UnV9mH+w1!i}4>HfAg-~16Fe)(FfkOv-FmJiNc z3MmItU)btFPL^V$w)%Ex*!I628sTEt4!B~(_HyKN#Rx|uJSxO_#}spg5Xlf?+7WRO zkYZxas2$<)kSj**Fh}r>+EG`C=%^j!X6QhbVi%mGFvp{|-%&wF_4jgE@^F9diNs<0 t2fQds2F7hK=0~sDyiB+ti>i?;b^zw_q>ZIKa`ZqNh{ymP`ZyA8{~w{uy0QQO literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/pycparser/ply/__pycache__/lex.cpython-311.pyc b/.venv/Lib/site-packages/pycparser/ply/__pycache__/lex.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5b2173b996616fe5081a08bd1b840c974105742f GIT binary patch literal 44018 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 F{~yYxgiHVc literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/pycparser/ply/__pycache__/ygen.cpython-311.pyc b/.venv/Lib/site-packages/pycparser/ply/__pycache__/ygen.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..055d3b152b32f647d77776842e0b9b71a52af128 GIT binary patch literal 3611 zcmb^zTWlN0aqn)AuRBtYSe7M`HWf*cS(vmf*|nnxMr(^=`~ce|GGaSa2#R;6X;UO| zcZw|bh+Y8)pad0Gf)v(I0e-nIi~>f{p#BURG$@cCo^e2k0|W%fSN>SI1q^?6_V^M- z8LffNafh?JGqbxhvore#x7&pPUPitYzjYw=1L-t@ZV=C}0Pz3`NT4$424(%zH)w&r zhi)(e0~iY!Fe};w_Kqbb@iY?IhamU3sSQye|AEy4wjar8G}&B%^e{9A+H)I4R#N~s zK}8Rt_qa7uqyDZRHk!QxEy?+*5h?4q9v~)485R zQz%Pq9^bWs{eND8oT&>`{E8J=fhhpDYQIT;fC4yLaE}Fpqy7mwC@Tp`DR9lMm=%5` z2Ml1-DP~ueMJb_(CMzpaI&ZoxW_dNO+%g@&X;A@($!5}7Q8pPRkun{!l&p817I&Ns z+JV_3xcXQ+D~NYZO!&w$LfjgVAySaP0WaU1n~5cJLOPp@UCrHGcsG%}Bgftsm&N5J zQ4-~(m`#eY&?jQ{lh~E?QcO-OVlWR(iIgbE@@vU_LXt)4cs{dsd@UtrL-{qcHzg`@ zIkzGu#kiEnrbMY9R&+y?{{%=wJ3WWC2lSpJM$ZxL-D>ZV@|fN`pXH<)P z@0+M0n(eoc?iea@TMJdL=l;yb%=+x+?04Lo&$u_sZ|hvp;DR+oIs2=8UnyK;fU4P$ zcf2jV-cxdJo$3(wKjZx6L7fX2T%cRneQ0}h{TJKUE8JuSPd#LL{C$ zA{jv>&lOpfEdxh4?1|xhKhf$qvZ0CGvR)jDSsYk};A^OwY}9MgiXo@p^#S)7fNZMG#E~#8_Mr?WVQ{aU07?w?-&HF5nw4Po}Eg-W=?NtTDt z>fAAdJ61!C^JsN=bn8wjQi@dF2Z+~>R{7!Y_|a$lXn9=cCk=kG!cV@aazhn7B)tJk zCZV-}oYu-u5@5(rtqFu~w>+@FRTXm326WoDh!kSB2Ha+w)GM^_($nOGTmd=tA>^^g ztz7n+(sZYEXOBV(@l^v}Q}dpE2~4N%)2Ik}yiBr57d(WKcI|*0Lh29dl!vU$jiHlB z#;f#Q<~mxXD0Cg_4D6Y>uK_A8;7&QKMleOZhl|~Z3o6MTF55m__M$_jRYt|1(j;c< zP;@E-O&Yx96zrXnMOVkXOK|L&=Tr`~+EvG=^eiY+UC?7yTfHYZ?;%o;_S)(H=q*?0 zej485+GlE0D%}~^Q0rgMUv0A?f$P=<8HkS->}!c+66!;NYY?HO#2u58OqW$d1aWBv z>Y7F8@=Bq%Nd>bxMS_ZBvUB0{S0kol;r*XqxO_1hNwzL79EChUNZ33l#wKZ5MTlv}UZVWm2n! zo~wBQ-UEWaVW@!Hq;s-~^9gtn*oCx|O)Nt?j>jQWi}AQ=lW(mk>5R!HbNRI?6W`9I zvnI|#W;dOZm=LTyZWUoGDVwfU3CegqyR&&IomB$7bQHE}Qa7zaU~-o6lMqo&0j@ zFK7Nb`{&uO?EmoT(;phsAL{s;fv;8YwH>GXw@aWVvys_8Q@*HsLWU>wgwdU+4Cg7R zLhRwERJFJ70rxrgnfnWOiG?Q!d)S(=&_4;wzX)oN?MJf7{UE&?E6lO!u8P zeCKsMtXGP=0{-&U7epY_$e*?UoGVYOF5kP`3-*Ss_qyu z93vIS2r-wJoV<>RxxB<&yT;nHZK`3ey)>Uzh=-6vuZ>9N@#~~{IHa>8HWxi(d z1*iRMo&x;$cMi_`m~VV|e$@WWI0cwoDH2NYc))Jjb8?7WIO#2rmVQDIdB$2d$ci<> zO)g?Q{zqh8-Fjkh%r57Im5g{!`Wdj36eZsV1Sh4a+5trMXdd!akz2FA8g^6g0&1bd uPHMP@TIk>i<*T6mT?_?)Rfe*Oc!1tzor literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/pycparser/ply/cpp.py b/.venv/Lib/site-packages/pycparser/ply/cpp.py new file mode 100644 index 00000000..86273eac --- /dev/null +++ b/.venv/Lib/site-packages/pycparser/ply/cpp.py @@ -0,0 +1,905 @@ +# ----------------------------------------------------------------------------- +# cpp.py +# +# Author: David Beazley (http://www.dabeaz.com) +# Copyright (C) 2017 +# All rights reserved +# +# This module implements an ANSI-C style lexical preprocessor for PLY. +# ----------------------------------------------------------------------------- +import sys + +# Some Python 3 compatibility shims +if sys.version_info.major < 3: + STRING_TYPES = (str, unicode) +else: + STRING_TYPES = str + xrange = range + +# ----------------------------------------------------------------------------- +# Default preprocessor lexer definitions. These tokens are enough to get +# a basic preprocessor working. Other modules may import these if they want +# ----------------------------------------------------------------------------- + +tokens = ( + 'CPP_ID','CPP_INTEGER', 'CPP_FLOAT', 'CPP_STRING', 'CPP_CHAR', 'CPP_WS', 'CPP_COMMENT1', 'CPP_COMMENT2', 'CPP_POUND','CPP_DPOUND' +) + +literals = "+-*/%|&~^<>=!?()[]{}.,;:\\\'\"" + +# Whitespace +def t_CPP_WS(t): + r'\s+' + t.lexer.lineno += t.value.count("\n") + return t + +t_CPP_POUND = r'\#' +t_CPP_DPOUND = r'\#\#' + +# Identifier +t_CPP_ID = r'[A-Za-z_][\w_]*' + +# Integer literal +def CPP_INTEGER(t): + r'(((((0x)|(0X))[0-9a-fA-F]+)|(\d+))([uU][lL]|[lL][uU]|[uU]|[lL])?)' + return t + +t_CPP_INTEGER = CPP_INTEGER + +# Floating literal +t_CPP_FLOAT = r'((\d+)(\.\d+)(e(\+|-)?(\d+))? | (\d+)e(\+|-)?(\d+))([lL]|[fF])?' + +# String literal +def t_CPP_STRING(t): + r'\"([^\\\n]|(\\(.|\n)))*?\"' + t.lexer.lineno += t.value.count("\n") + return t + +# Character constant 'c' or L'c' +def t_CPP_CHAR(t): + r'(L)?\'([^\\\n]|(\\(.|\n)))*?\'' + t.lexer.lineno += t.value.count("\n") + return t + +# Comment +def t_CPP_COMMENT1(t): + r'(/\*(.|\n)*?\*/)' + ncr = t.value.count("\n") + t.lexer.lineno += ncr + # replace with one space or a number of '\n' + t.type = 'CPP_WS'; t.value = '\n' * ncr if ncr else ' ' + return t + +# Line comment +def t_CPP_COMMENT2(t): + r'(//.*?(\n|$))' + # replace with '/n' + t.type = 'CPP_WS'; t.value = '\n' + return t + +def t_error(t): + t.type = t.value[0] + t.value = t.value[0] + t.lexer.skip(1) + return t + +import re +import copy +import time +import os.path + +# ----------------------------------------------------------------------------- +# trigraph() +# +# Given an input string, this function replaces all trigraph sequences. +# The following mapping is used: +# +# ??= # +# ??/ \ +# ??' ^ +# ??( [ +# ??) ] +# ??! | +# ??< { +# ??> } +# ??- ~ +# ----------------------------------------------------------------------------- + +_trigraph_pat = re.compile(r'''\?\?[=/\'\(\)\!<>\-]''') +_trigraph_rep = { + '=':'#', + '/':'\\', + "'":'^', + '(':'[', + ')':']', + '!':'|', + '<':'{', + '>':'}', + '-':'~' +} + +def trigraph(input): + return _trigraph_pat.sub(lambda g: _trigraph_rep[g.group()[-1]],input) + +# ------------------------------------------------------------------ +# Macro object +# +# This object holds information about preprocessor macros +# +# .name - Macro name (string) +# .value - Macro value (a list of tokens) +# .arglist - List of argument names +# .variadic - Boolean indicating whether or not variadic macro +# .vararg - Name of the variadic parameter +# +# When a macro is created, the macro replacement token sequence is +# pre-scanned and used to create patch lists that are later used +# during macro expansion +# ------------------------------------------------------------------ + +class Macro(object): + def __init__(self,name,value,arglist=None,variadic=False): + self.name = name + self.value = value + self.arglist = arglist + self.variadic = variadic + if variadic: + self.vararg = arglist[-1] + self.source = None + +# ------------------------------------------------------------------ +# Preprocessor object +# +# Object representing a preprocessor. Contains macro definitions, +# include directories, and other information +# ------------------------------------------------------------------ + +class Preprocessor(object): + def __init__(self,lexer=None): + if lexer is None: + lexer = lex.lexer + self.lexer = lexer + self.macros = { } + self.path = [] + self.temp_path = [] + + # Probe the lexer for selected tokens + self.lexprobe() + + tm = time.localtime() + self.define("__DATE__ \"%s\"" % time.strftime("%b %d %Y",tm)) + self.define("__TIME__ \"%s\"" % time.strftime("%H:%M:%S",tm)) + self.parser = None + + # ----------------------------------------------------------------------------- + # tokenize() + # + # Utility function. Given a string of text, tokenize into a list of tokens + # ----------------------------------------------------------------------------- + + def tokenize(self,text): + tokens = [] + self.lexer.input(text) + while True: + tok = self.lexer.token() + if not tok: break + tokens.append(tok) + return tokens + + # --------------------------------------------------------------------- + # error() + # + # Report a preprocessor error/warning of some kind + # ---------------------------------------------------------------------- + + def error(self,file,line,msg): + print("%s:%d %s" % (file,line,msg)) + + # ---------------------------------------------------------------------- + # lexprobe() + # + # This method probes the preprocessor lexer object to discover + # the token types of symbols that are important to the preprocessor. + # If this works right, the preprocessor will simply "work" + # with any suitable lexer regardless of how tokens have been named. + # ---------------------------------------------------------------------- + + def lexprobe(self): + + # Determine the token type for identifiers + self.lexer.input("identifier") + tok = self.lexer.token() + if not tok or tok.value != "identifier": + print("Couldn't determine identifier type") + else: + self.t_ID = tok.type + + # Determine the token type for integers + self.lexer.input("12345") + tok = self.lexer.token() + if not tok or int(tok.value) != 12345: + print("Couldn't determine integer type") + else: + self.t_INTEGER = tok.type + self.t_INTEGER_TYPE = type(tok.value) + + # Determine the token type for strings enclosed in double quotes + self.lexer.input("\"filename\"") + tok = self.lexer.token() + if not tok or tok.value != "\"filename\"": + print("Couldn't determine string type") + else: + self.t_STRING = tok.type + + # Determine the token type for whitespace--if any + self.lexer.input(" ") + tok = self.lexer.token() + if not tok or tok.value != " ": + self.t_SPACE = None + else: + self.t_SPACE = tok.type + + # Determine the token type for newlines + self.lexer.input("\n") + tok = self.lexer.token() + if not tok or tok.value != "\n": + self.t_NEWLINE = None + print("Couldn't determine token for newlines") + else: + self.t_NEWLINE = tok.type + + self.t_WS = (self.t_SPACE, self.t_NEWLINE) + + # Check for other characters used by the preprocessor + chars = [ '<','>','#','##','\\','(',')',',','.'] + for c in chars: + self.lexer.input(c) + tok = self.lexer.token() + if not tok or tok.value != c: + print("Unable to lex '%s' required for preprocessor" % c) + + # ---------------------------------------------------------------------- + # add_path() + # + # Adds a search path to the preprocessor. + # ---------------------------------------------------------------------- + + def add_path(self,path): + self.path.append(path) + + # ---------------------------------------------------------------------- + # group_lines() + # + # Given an input string, this function splits it into lines. Trailing whitespace + # is removed. Any line ending with \ is grouped with the next line. This + # function forms the lowest level of the preprocessor---grouping into text into + # a line-by-line format. + # ---------------------------------------------------------------------- + + def group_lines(self,input): + lex = self.lexer.clone() + lines = [x.rstrip() for x in input.splitlines()] + for i in xrange(len(lines)): + j = i+1 + while lines[i].endswith('\\') and (j < len(lines)): + lines[i] = lines[i][:-1]+lines[j] + lines[j] = "" + j += 1 + + input = "\n".join(lines) + lex.input(input) + lex.lineno = 1 + + current_line = [] + while True: + tok = lex.token() + if not tok: + break + current_line.append(tok) + if tok.type in self.t_WS and '\n' in tok.value: + yield current_line + current_line = [] + + if current_line: + yield current_line + + # ---------------------------------------------------------------------- + # tokenstrip() + # + # Remove leading/trailing whitespace tokens from a token list + # ---------------------------------------------------------------------- + + def tokenstrip(self,tokens): + i = 0 + while i < len(tokens) and tokens[i].type in self.t_WS: + i += 1 + del tokens[:i] + i = len(tokens)-1 + while i >= 0 and tokens[i].type in self.t_WS: + i -= 1 + del tokens[i+1:] + return tokens + + + # ---------------------------------------------------------------------- + # collect_args() + # + # Collects comma separated arguments from a list of tokens. The arguments + # must be enclosed in parenthesis. Returns a tuple (tokencount,args,positions) + # where tokencount is the number of tokens consumed, args is a list of arguments, + # and positions is a list of integers containing the starting index of each + # argument. Each argument is represented by a list of tokens. + # + # When collecting arguments, leading and trailing whitespace is removed + # from each argument. + # + # This function properly handles nested parenthesis and commas---these do not + # define new arguments. + # ---------------------------------------------------------------------- + + def collect_args(self,tokenlist): + args = [] + positions = [] + current_arg = [] + nesting = 1 + tokenlen = len(tokenlist) + + # Search for the opening '('. + i = 0 + while (i < tokenlen) and (tokenlist[i].type in self.t_WS): + i += 1 + + if (i < tokenlen) and (tokenlist[i].value == '('): + positions.append(i+1) + else: + self.error(self.source,tokenlist[0].lineno,"Missing '(' in macro arguments") + return 0, [], [] + + i += 1 + + while i < tokenlen: + t = tokenlist[i] + if t.value == '(': + current_arg.append(t) + nesting += 1 + elif t.value == ')': + nesting -= 1 + if nesting == 0: + if current_arg: + args.append(self.tokenstrip(current_arg)) + positions.append(i) + return i+1,args,positions + current_arg.append(t) + elif t.value == ',' and nesting == 1: + args.append(self.tokenstrip(current_arg)) + positions.append(i+1) + current_arg = [] + else: + current_arg.append(t) + i += 1 + + # Missing end argument + self.error(self.source,tokenlist[-1].lineno,"Missing ')' in macro arguments") + return 0, [],[] + + # ---------------------------------------------------------------------- + # macro_prescan() + # + # Examine the macro value (token sequence) and identify patch points + # This is used to speed up macro expansion later on---we'll know + # right away where to apply patches to the value to form the expansion + # ---------------------------------------------------------------------- + + def macro_prescan(self,macro): + macro.patch = [] # Standard macro arguments + macro.str_patch = [] # String conversion expansion + macro.var_comma_patch = [] # Variadic macro comma patch + i = 0 + while i < len(macro.value): + if macro.value[i].type == self.t_ID and macro.value[i].value in macro.arglist: + argnum = macro.arglist.index(macro.value[i].value) + # Conversion of argument to a string + if i > 0 and macro.value[i-1].value == '#': + macro.value[i] = copy.copy(macro.value[i]) + macro.value[i].type = self.t_STRING + del macro.value[i-1] + macro.str_patch.append((argnum,i-1)) + continue + # Concatenation + elif (i > 0 and macro.value[i-1].value == '##'): + macro.patch.append(('c',argnum,i-1)) + del macro.value[i-1] + continue + elif ((i+1) < len(macro.value) and macro.value[i+1].value == '##'): + macro.patch.append(('c',argnum,i)) + i += 1 + continue + # Standard expansion + else: + macro.patch.append(('e',argnum,i)) + elif macro.value[i].value == '##': + if macro.variadic and (i > 0) and (macro.value[i-1].value == ',') and \ + ((i+1) < len(macro.value)) and (macro.value[i+1].type == self.t_ID) and \ + (macro.value[i+1].value == macro.vararg): + macro.var_comma_patch.append(i-1) + i += 1 + macro.patch.sort(key=lambda x: x[2],reverse=True) + + # ---------------------------------------------------------------------- + # macro_expand_args() + # + # Given a Macro and list of arguments (each a token list), this method + # returns an expanded version of a macro. The return value is a token sequence + # representing the replacement macro tokens + # ---------------------------------------------------------------------- + + def macro_expand_args(self,macro,args): + # Make a copy of the macro token sequence + rep = [copy.copy(_x) for _x in macro.value] + + # Make string expansion patches. These do not alter the length of the replacement sequence + + str_expansion = {} + for argnum, i in macro.str_patch: + if argnum not in str_expansion: + str_expansion[argnum] = ('"%s"' % "".join([x.value for x in args[argnum]])).replace("\\","\\\\") + rep[i] = copy.copy(rep[i]) + rep[i].value = str_expansion[argnum] + + # Make the variadic macro comma patch. If the variadic macro argument is empty, we get rid + comma_patch = False + if macro.variadic and not args[-1]: + for i in macro.var_comma_patch: + rep[i] = None + comma_patch = True + + # Make all other patches. The order of these matters. It is assumed that the patch list + # has been sorted in reverse order of patch location since replacements will cause the + # size of the replacement sequence to expand from the patch point. + + expanded = { } + for ptype, argnum, i in macro.patch: + # Concatenation. Argument is left unexpanded + if ptype == 'c': + rep[i:i+1] = args[argnum] + # Normal expansion. Argument is macro expanded first + elif ptype == 'e': + if argnum not in expanded: + expanded[argnum] = self.expand_macros(args[argnum]) + rep[i:i+1] = expanded[argnum] + + # Get rid of removed comma if necessary + if comma_patch: + rep = [_i for _i in rep if _i] + + return rep + + + # ---------------------------------------------------------------------- + # expand_macros() + # + # Given a list of tokens, this function performs macro expansion. + # The expanded argument is a dictionary that contains macros already + # expanded. This is used to prevent infinite recursion. + # ---------------------------------------------------------------------- + + def expand_macros(self,tokens,expanded=None): + if expanded is None: + expanded = {} + i = 0 + while i < len(tokens): + t = tokens[i] + if t.type == self.t_ID: + if t.value in self.macros and t.value not in expanded: + # Yes, we found a macro match + expanded[t.value] = True + + m = self.macros[t.value] + if not m.arglist: + # A simple macro + ex = self.expand_macros([copy.copy(_x) for _x in m.value],expanded) + for e in ex: + e.lineno = t.lineno + tokens[i:i+1] = ex + i += len(ex) + else: + # A macro with arguments + j = i + 1 + while j < len(tokens) and tokens[j].type in self.t_WS: + j += 1 + if tokens[j].value == '(': + tokcount,args,positions = self.collect_args(tokens[j:]) + if not m.variadic and len(args) != len(m.arglist): + self.error(self.source,t.lineno,"Macro %s requires %d arguments" % (t.value,len(m.arglist))) + i = j + tokcount + elif m.variadic and len(args) < len(m.arglist)-1: + if len(m.arglist) > 2: + self.error(self.source,t.lineno,"Macro %s must have at least %d arguments" % (t.value, len(m.arglist)-1)) + else: + self.error(self.source,t.lineno,"Macro %s must have at least %d argument" % (t.value, len(m.arglist)-1)) + i = j + tokcount + else: + if m.variadic: + if len(args) == len(m.arglist)-1: + args.append([]) + else: + args[len(m.arglist)-1] = tokens[j+positions[len(m.arglist)-1]:j+tokcount-1] + del args[len(m.arglist):] + + # Get macro replacement text + rep = self.macro_expand_args(m,args) + rep = self.expand_macros(rep,expanded) + for r in rep: + r.lineno = t.lineno + tokens[i:j+tokcount] = rep + i += len(rep) + del expanded[t.value] + continue + elif t.value == '__LINE__': + t.type = self.t_INTEGER + t.value = self.t_INTEGER_TYPE(t.lineno) + + i += 1 + return tokens + + # ---------------------------------------------------------------------- + # evalexpr() + # + # Evaluate an expression token sequence for the purposes of evaluating + # integral expressions. + # ---------------------------------------------------------------------- + + def evalexpr(self,tokens): + # tokens = tokenize(line) + # Search for defined macros + i = 0 + while i < len(tokens): + if tokens[i].type == self.t_ID and tokens[i].value == 'defined': + j = i + 1 + needparen = False + result = "0L" + while j < len(tokens): + if tokens[j].type in self.t_WS: + j += 1 + continue + elif tokens[j].type == self.t_ID: + if tokens[j].value in self.macros: + result = "1L" + else: + result = "0L" + if not needparen: break + elif tokens[j].value == '(': + needparen = True + elif tokens[j].value == ')': + break + else: + self.error(self.source,tokens[i].lineno,"Malformed defined()") + j += 1 + tokens[i].type = self.t_INTEGER + tokens[i].value = self.t_INTEGER_TYPE(result) + del tokens[i+1:j+1] + i += 1 + tokens = self.expand_macros(tokens) + for i,t in enumerate(tokens): + if t.type == self.t_ID: + tokens[i] = copy.copy(t) + tokens[i].type = self.t_INTEGER + tokens[i].value = self.t_INTEGER_TYPE("0L") + elif t.type == self.t_INTEGER: + tokens[i] = copy.copy(t) + # Strip off any trailing suffixes + tokens[i].value = str(tokens[i].value) + while tokens[i].value[-1] not in "0123456789abcdefABCDEF": + tokens[i].value = tokens[i].value[:-1] + + expr = "".join([str(x.value) for x in tokens]) + expr = expr.replace("&&"," and ") + expr = expr.replace("||"," or ") + expr = expr.replace("!"," not ") + try: + result = eval(expr) + except Exception: + self.error(self.source,tokens[0].lineno,"Couldn't evaluate expression") + result = 0 + return result + + # ---------------------------------------------------------------------- + # parsegen() + # + # Parse an input string/ + # ---------------------------------------------------------------------- + def parsegen(self,input,source=None): + + # Replace trigraph sequences + t = trigraph(input) + lines = self.group_lines(t) + + if not source: + source = "" + + self.define("__FILE__ \"%s\"" % source) + + self.source = source + chunk = [] + enable = True + iftrigger = False + ifstack = [] + + for x in lines: + for i,tok in enumerate(x): + if tok.type not in self.t_WS: break + if tok.value == '#': + # Preprocessor directive + + # insert necessary whitespace instead of eaten tokens + for tok in x: + if tok.type in self.t_WS and '\n' in tok.value: + chunk.append(tok) + + dirtokens = self.tokenstrip(x[i+1:]) + if dirtokens: + name = dirtokens[0].value + args = self.tokenstrip(dirtokens[1:]) + else: + name = "" + args = [] + + if name == 'define': + if enable: + for tok in self.expand_macros(chunk): + yield tok + chunk = [] + self.define(args) + elif name == 'include': + if enable: + for tok in self.expand_macros(chunk): + yield tok + chunk = [] + oldfile = self.macros['__FILE__'] + for tok in self.include(args): + yield tok + self.macros['__FILE__'] = oldfile + self.source = source + elif name == 'undef': + if enable: + for tok in self.expand_macros(chunk): + yield tok + chunk = [] + self.undef(args) + elif name == 'ifdef': + ifstack.append((enable,iftrigger)) + if enable: + if not args[0].value in self.macros: + enable = False + iftrigger = False + else: + iftrigger = True + elif name == 'ifndef': + ifstack.append((enable,iftrigger)) + if enable: + if args[0].value in self.macros: + enable = False + iftrigger = False + else: + iftrigger = True + elif name == 'if': + ifstack.append((enable,iftrigger)) + if enable: + result = self.evalexpr(args) + if not result: + enable = False + iftrigger = False + else: + iftrigger = True + elif name == 'elif': + if ifstack: + if ifstack[-1][0]: # We only pay attention if outer "if" allows this + if enable: # If already true, we flip enable False + enable = False + elif not iftrigger: # If False, but not triggered yet, we'll check expression + result = self.evalexpr(args) + if result: + enable = True + iftrigger = True + else: + self.error(self.source,dirtokens[0].lineno,"Misplaced #elif") + + elif name == 'else': + if ifstack: + if ifstack[-1][0]: + if enable: + enable = False + elif not iftrigger: + enable = True + iftrigger = True + else: + self.error(self.source,dirtokens[0].lineno,"Misplaced #else") + + elif name == 'endif': + if ifstack: + enable,iftrigger = ifstack.pop() + else: + self.error(self.source,dirtokens[0].lineno,"Misplaced #endif") + else: + # Unknown preprocessor directive + pass + + else: + # Normal text + if enable: + chunk.extend(x) + + for tok in self.expand_macros(chunk): + yield tok + chunk = [] + + # ---------------------------------------------------------------------- + # include() + # + # Implementation of file-inclusion + # ---------------------------------------------------------------------- + + def include(self,tokens): + # Try to extract the filename and then process an include file + if not tokens: + return + if tokens: + if tokens[0].value != '<' and tokens[0].type != self.t_STRING: + tokens = self.expand_macros(tokens) + + if tokens[0].value == '<': + # Include <...> + i = 1 + while i < len(tokens): + if tokens[i].value == '>': + break + i += 1 + else: + print("Malformed #include <...>") + return + filename = "".join([x.value for x in tokens[1:i]]) + path = self.path + [""] + self.temp_path + elif tokens[0].type == self.t_STRING: + filename = tokens[0].value[1:-1] + path = self.temp_path + [""] + self.path + else: + print("Malformed #include statement") + return + for p in path: + iname = os.path.join(p,filename) + try: + data = open(iname,"r").read() + dname = os.path.dirname(iname) + if dname: + self.temp_path.insert(0,dname) + for tok in self.parsegen(data,filename): + yield tok + if dname: + del self.temp_path[0] + break + except IOError: + pass + else: + print("Couldn't find '%s'" % filename) + + # ---------------------------------------------------------------------- + # define() + # + # Define a new macro + # ---------------------------------------------------------------------- + + def define(self,tokens): + if isinstance(tokens,STRING_TYPES): + tokens = self.tokenize(tokens) + + linetok = tokens + try: + name = linetok[0] + if len(linetok) > 1: + mtype = linetok[1] + else: + mtype = None + if not mtype: + m = Macro(name.value,[]) + self.macros[name.value] = m + elif mtype.type in self.t_WS: + # A normal macro + m = Macro(name.value,self.tokenstrip(linetok[2:])) + self.macros[name.value] = m + elif mtype.value == '(': + # A macro with arguments + tokcount, args, positions = self.collect_args(linetok[1:]) + variadic = False + for a in args: + if variadic: + print("No more arguments may follow a variadic argument") + break + astr = "".join([str(_i.value) for _i in a]) + if astr == "...": + variadic = True + a[0].type = self.t_ID + a[0].value = '__VA_ARGS__' + variadic = True + del a[1:] + continue + elif astr[-3:] == "..." and a[0].type == self.t_ID: + variadic = True + del a[1:] + # If, for some reason, "." is part of the identifier, strip off the name for the purposes + # of macro expansion + if a[0].value[-3:] == '...': + a[0].value = a[0].value[:-3] + continue + if len(a) > 1 or a[0].type != self.t_ID: + print("Invalid macro argument") + break + else: + mvalue = self.tokenstrip(linetok[1+tokcount:]) + i = 0 + while i < len(mvalue): + if i+1 < len(mvalue): + if mvalue[i].type in self.t_WS and mvalue[i+1].value == '##': + del mvalue[i] + continue + elif mvalue[i].value == '##' and mvalue[i+1].type in self.t_WS: + del mvalue[i+1] + i += 1 + m = Macro(name.value,mvalue,[x[0].value for x in args],variadic) + self.macro_prescan(m) + self.macros[name.value] = m + else: + print("Bad macro definition") + except LookupError: + print("Bad macro definition") + + # ---------------------------------------------------------------------- + # undef() + # + # Undefine a macro + # ---------------------------------------------------------------------- + + def undef(self,tokens): + id = tokens[0].value + try: + del self.macros[id] + except LookupError: + pass + + # ---------------------------------------------------------------------- + # parse() + # + # Parse input text. + # ---------------------------------------------------------------------- + def parse(self,input,source=None,ignore={}): + self.ignore = ignore + self.parser = self.parsegen(input,source) + + # ---------------------------------------------------------------------- + # token() + # + # Method to return individual tokens + # ---------------------------------------------------------------------- + def token(self): + try: + while True: + tok = next(self.parser) + if tok.type not in self.ignore: return tok + except StopIteration: + self.parser = None + return None + +if __name__ == '__main__': + import ply.lex as lex + lexer = lex.lex() + + # Run a preprocessor + import sys + f = open(sys.argv[1]) + input = f.read() + + p = Preprocessor(lexer) + p.parse(input,sys.argv[1]) + while True: + tok = p.token() + if not tok: break + print(p.source, tok) diff --git a/.venv/Lib/site-packages/pycparser/ply/ctokens.py b/.venv/Lib/site-packages/pycparser/ply/ctokens.py new file mode 100644 index 00000000..f6f6952d --- /dev/null +++ b/.venv/Lib/site-packages/pycparser/ply/ctokens.py @@ -0,0 +1,133 @@ +# ---------------------------------------------------------------------- +# ctokens.py +# +# Token specifications for symbols in ANSI C and C++. This file is +# meant to be used as a library in other tokenizers. +# ---------------------------------------------------------------------- + +# Reserved words + +tokens = [ + # Literals (identifier, integer constant, float constant, string constant, char const) + 'ID', 'TYPEID', 'INTEGER', 'FLOAT', 'STRING', 'CHARACTER', + + # Operators (+,-,*,/,%,|,&,~,^,<<,>>, ||, &&, !, <, <=, >, >=, ==, !=) + 'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'MODULO', + 'OR', 'AND', 'NOT', 'XOR', 'LSHIFT', 'RSHIFT', + 'LOR', 'LAND', 'LNOT', + 'LT', 'LE', 'GT', 'GE', 'EQ', 'NE', + + # Assignment (=, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=) + 'EQUALS', 'TIMESEQUAL', 'DIVEQUAL', 'MODEQUAL', 'PLUSEQUAL', 'MINUSEQUAL', + 'LSHIFTEQUAL','RSHIFTEQUAL', 'ANDEQUAL', 'XOREQUAL', 'OREQUAL', + + # Increment/decrement (++,--) + 'INCREMENT', 'DECREMENT', + + # Structure dereference (->) + 'ARROW', + + # Ternary operator (?) + 'TERNARY', + + # Delimeters ( ) [ ] { } , . ; : + 'LPAREN', 'RPAREN', + 'LBRACKET', 'RBRACKET', + 'LBRACE', 'RBRACE', + 'COMMA', 'PERIOD', 'SEMI', 'COLON', + + # Ellipsis (...) + 'ELLIPSIS', +] + +# Operators +t_PLUS = r'\+' +t_MINUS = r'-' +t_TIMES = r'\*' +t_DIVIDE = r'/' +t_MODULO = r'%' +t_OR = r'\|' +t_AND = r'&' +t_NOT = r'~' +t_XOR = r'\^' +t_LSHIFT = r'<<' +t_RSHIFT = r'>>' +t_LOR = r'\|\|' +t_LAND = r'&&' +t_LNOT = r'!' +t_LT = r'<' +t_GT = r'>' +t_LE = r'<=' +t_GE = r'>=' +t_EQ = r'==' +t_NE = r'!=' + +# Assignment operators + +t_EQUALS = r'=' +t_TIMESEQUAL = r'\*=' +t_DIVEQUAL = r'/=' +t_MODEQUAL = r'%=' +t_PLUSEQUAL = r'\+=' +t_MINUSEQUAL = r'-=' +t_LSHIFTEQUAL = r'<<=' +t_RSHIFTEQUAL = r'>>=' +t_ANDEQUAL = r'&=' +t_OREQUAL = r'\|=' +t_XOREQUAL = r'\^=' + +# Increment/decrement +t_INCREMENT = r'\+\+' +t_DECREMENT = r'--' + +# -> +t_ARROW = r'->' + +# ? +t_TERNARY = r'\?' + +# Delimeters +t_LPAREN = r'\(' +t_RPAREN = r'\)' +t_LBRACKET = r'\[' +t_RBRACKET = r'\]' +t_LBRACE = r'\{' +t_RBRACE = r'\}' +t_COMMA = r',' +t_PERIOD = r'\.' +t_SEMI = r';' +t_COLON = r':' +t_ELLIPSIS = r'\.\.\.' + +# Identifiers +t_ID = r'[A-Za-z_][A-Za-z0-9_]*' + +# Integer literal +t_INTEGER = r'\d+([uU]|[lL]|[uU][lL]|[lL][uU])?' + +# Floating literal +t_FLOAT = r'((\d+)(\.\d+)(e(\+|-)?(\d+))? | (\d+)e(\+|-)?(\d+))([lL]|[fF])?' + +# String literal +t_STRING = r'\"([^\\\n]|(\\.))*?\"' + +# Character constant 'c' or L'c' +t_CHARACTER = r'(L)?\'([^\\\n]|(\\.))*?\'' + +# Comment (C-Style) +def t_COMMENT(t): + r'/\*(.|\n)*?\*/' + t.lexer.lineno += t.value.count('\n') + return t + +# Comment (C++-Style) +def t_CPPCOMMENT(t): + r'//.*\n' + t.lexer.lineno += 1 + return t + + + + + + diff --git a/.venv/Lib/site-packages/pycparser/ply/lex.py b/.venv/Lib/site-packages/pycparser/ply/lex.py new file mode 100644 index 00000000..4bdd76ca --- /dev/null +++ b/.venv/Lib/site-packages/pycparser/ply/lex.py @@ -0,0 +1,1099 @@ +# ----------------------------------------------------------------------------- +# ply: lex.py +# +# Copyright (C) 2001-2017 +# David M. Beazley (Dabeaz LLC) +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the David Beazley or Dabeaz LLC may be used to +# endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# ----------------------------------------------------------------------------- + +__version__ = '3.10' +__tabversion__ = '3.10' + +import re +import sys +import types +import copy +import os +import inspect + +# This tuple contains known string types +try: + # Python 2.6 + StringTypes = (types.StringType, types.UnicodeType) +except AttributeError: + # Python 3.0 + StringTypes = (str, bytes) + +# This regular expression is used to match valid token names +_is_identifier = re.compile(r'^[a-zA-Z0-9_]+$') + +# Exception thrown when invalid token encountered and no default error +# handler is defined. +class LexError(Exception): + def __init__(self, message, s): + self.args = (message,) + self.text = s + + +# Token class. This class is used to represent the tokens produced. +class LexToken(object): + def __str__(self): + return 'LexToken(%s,%r,%d,%d)' % (self.type, self.value, self.lineno, self.lexpos) + + def __repr__(self): + return str(self) + + +# This object is a stand-in for a logging object created by the +# logging module. + +class PlyLogger(object): + def __init__(self, f): + self.f = f + + def critical(self, msg, *args, **kwargs): + self.f.write((msg % args) + '\n') + + def warning(self, msg, *args, **kwargs): + self.f.write('WARNING: ' + (msg % args) + '\n') + + def error(self, msg, *args, **kwargs): + self.f.write('ERROR: ' + (msg % args) + '\n') + + info = critical + debug = critical + + +# Null logger is used when no output is generated. Does nothing. +class NullLogger(object): + def __getattribute__(self, name): + return self + + def __call__(self, *args, **kwargs): + return self + + +# ----------------------------------------------------------------------------- +# === Lexing Engine === +# +# The following Lexer class implements the lexer runtime. There are only +# a few public methods and attributes: +# +# input() - Store a new string in the lexer +# token() - Get the next token +# clone() - Clone the lexer +# +# lineno - Current line number +# lexpos - Current position in the input string +# ----------------------------------------------------------------------------- + +class Lexer: + def __init__(self): + self.lexre = None # Master regular expression. This is a list of + # tuples (re, findex) where re is a compiled + # regular expression and findex is a list + # mapping regex group numbers to rules + self.lexretext = None # Current regular expression strings + self.lexstatere = {} # Dictionary mapping lexer states to master regexs + self.lexstateretext = {} # Dictionary mapping lexer states to regex strings + self.lexstaterenames = {} # Dictionary mapping lexer states to symbol names + self.lexstate = 'INITIAL' # Current lexer state + self.lexstatestack = [] # Stack of lexer states + self.lexstateinfo = None # State information + self.lexstateignore = {} # Dictionary of ignored characters for each state + self.lexstateerrorf = {} # Dictionary of error functions for each state + self.lexstateeoff = {} # Dictionary of eof functions for each state + self.lexreflags = 0 # Optional re compile flags + self.lexdata = None # Actual input data (as a string) + self.lexpos = 0 # Current position in input text + self.lexlen = 0 # Length of the input text + self.lexerrorf = None # Error rule (if any) + self.lexeoff = None # EOF rule (if any) + self.lextokens = None # List of valid tokens + self.lexignore = '' # Ignored characters + self.lexliterals = '' # Literal characters that can be passed through + self.lexmodule = None # Module + self.lineno = 1 # Current line number + self.lexoptimize = False # Optimized mode + + def clone(self, object=None): + c = copy.copy(self) + + # If the object parameter has been supplied, it means we are attaching the + # lexer to a new object. In this case, we have to rebind all methods in + # the lexstatere and lexstateerrorf tables. + + if object: + newtab = {} + for key, ritem in self.lexstatere.items(): + newre = [] + for cre, findex in ritem: + newfindex = [] + for f in findex: + if not f or not f[0]: + newfindex.append(f) + continue + newfindex.append((getattr(object, f[0].__name__), f[1])) + newre.append((cre, newfindex)) + newtab[key] = newre + c.lexstatere = newtab + c.lexstateerrorf = {} + for key, ef in self.lexstateerrorf.items(): + c.lexstateerrorf[key] = getattr(object, ef.__name__) + c.lexmodule = object + return c + + # ------------------------------------------------------------ + # writetab() - Write lexer information to a table file + # ------------------------------------------------------------ + def writetab(self, lextab, outputdir=''): + if isinstance(lextab, types.ModuleType): + raise IOError("Won't overwrite existing lextab module") + basetabmodule = lextab.split('.')[-1] + filename = os.path.join(outputdir, basetabmodule) + '.py' + with open(filename, 'w') as tf: + tf.write('# %s.py. This file automatically created by PLY (version %s). Don\'t edit!\n' % (basetabmodule, __version__)) + tf.write('_tabversion = %s\n' % repr(__tabversion__)) + tf.write('_lextokens = set(%s)\n' % repr(tuple(self.lextokens))) + tf.write('_lexreflags = %s\n' % repr(self.lexreflags)) + tf.write('_lexliterals = %s\n' % repr(self.lexliterals)) + tf.write('_lexstateinfo = %s\n' % repr(self.lexstateinfo)) + + # Rewrite the lexstatere table, replacing function objects with function names + tabre = {} + for statename, lre in self.lexstatere.items(): + titem = [] + for (pat, func), retext, renames in zip(lre, self.lexstateretext[statename], self.lexstaterenames[statename]): + titem.append((retext, _funcs_to_names(func, renames))) + tabre[statename] = titem + + tf.write('_lexstatere = %s\n' % repr(tabre)) + tf.write('_lexstateignore = %s\n' % repr(self.lexstateignore)) + + taberr = {} + for statename, ef in self.lexstateerrorf.items(): + taberr[statename] = ef.__name__ if ef else None + tf.write('_lexstateerrorf = %s\n' % repr(taberr)) + + tabeof = {} + for statename, ef in self.lexstateeoff.items(): + tabeof[statename] = ef.__name__ if ef else None + tf.write('_lexstateeoff = %s\n' % repr(tabeof)) + + # ------------------------------------------------------------ + # readtab() - Read lexer information from a tab file + # ------------------------------------------------------------ + def readtab(self, tabfile, fdict): + if isinstance(tabfile, types.ModuleType): + lextab = tabfile + else: + exec('import %s' % tabfile) + lextab = sys.modules[tabfile] + + if getattr(lextab, '_tabversion', '0.0') != __tabversion__: + raise ImportError('Inconsistent PLY version') + + self.lextokens = lextab._lextokens + self.lexreflags = lextab._lexreflags + self.lexliterals = lextab._lexliterals + self.lextokens_all = self.lextokens | set(self.lexliterals) + self.lexstateinfo = lextab._lexstateinfo + self.lexstateignore = lextab._lexstateignore + self.lexstatere = {} + self.lexstateretext = {} + for statename, lre in lextab._lexstatere.items(): + titem = [] + txtitem = [] + for pat, func_name in lre: + titem.append((re.compile(pat, lextab._lexreflags), _names_to_funcs(func_name, fdict))) + + self.lexstatere[statename] = titem + self.lexstateretext[statename] = txtitem + + self.lexstateerrorf = {} + for statename, ef in lextab._lexstateerrorf.items(): + self.lexstateerrorf[statename] = fdict[ef] + + self.lexstateeoff = {} + for statename, ef in lextab._lexstateeoff.items(): + self.lexstateeoff[statename] = fdict[ef] + + self.begin('INITIAL') + + # ------------------------------------------------------------ + # input() - Push a new string into the lexer + # ------------------------------------------------------------ + def input(self, s): + # Pull off the first character to see if s looks like a string + c = s[:1] + if not isinstance(c, StringTypes): + raise ValueError('Expected a string') + self.lexdata = s + self.lexpos = 0 + self.lexlen = len(s) + + # ------------------------------------------------------------ + # begin() - Changes the lexing state + # ------------------------------------------------------------ + def begin(self, state): + if state not in self.lexstatere: + raise ValueError('Undefined state') + self.lexre = self.lexstatere[state] + self.lexretext = self.lexstateretext[state] + self.lexignore = self.lexstateignore.get(state, '') + self.lexerrorf = self.lexstateerrorf.get(state, None) + self.lexeoff = self.lexstateeoff.get(state, None) + self.lexstate = state + + # ------------------------------------------------------------ + # push_state() - Changes the lexing state and saves old on stack + # ------------------------------------------------------------ + def push_state(self, state): + self.lexstatestack.append(self.lexstate) + self.begin(state) + + # ------------------------------------------------------------ + # pop_state() - Restores the previous state + # ------------------------------------------------------------ + def pop_state(self): + self.begin(self.lexstatestack.pop()) + + # ------------------------------------------------------------ + # current_state() - Returns the current lexing state + # ------------------------------------------------------------ + def current_state(self): + return self.lexstate + + # ------------------------------------------------------------ + # skip() - Skip ahead n characters + # ------------------------------------------------------------ + def skip(self, n): + self.lexpos += n + + # ------------------------------------------------------------ + # opttoken() - Return the next token from the Lexer + # + # Note: This function has been carefully implemented to be as fast + # as possible. Don't make changes unless you really know what + # you are doing + # ------------------------------------------------------------ + def token(self): + # Make local copies of frequently referenced attributes + lexpos = self.lexpos + lexlen = self.lexlen + lexignore = self.lexignore + lexdata = self.lexdata + + while lexpos < lexlen: + # This code provides some short-circuit code for whitespace, tabs, and other ignored characters + if lexdata[lexpos] in lexignore: + lexpos += 1 + continue + + # Look for a regular expression match + for lexre, lexindexfunc in self.lexre: + m = lexre.match(lexdata, lexpos) + if not m: + continue + + # Create a token for return + tok = LexToken() + tok.value = m.group() + tok.lineno = self.lineno + tok.lexpos = lexpos + + i = m.lastindex + func, tok.type = lexindexfunc[i] + + if not func: + # If no token type was set, it's an ignored token + if tok.type: + self.lexpos = m.end() + return tok + else: + lexpos = m.end() + break + + lexpos = m.end() + + # If token is processed by a function, call it + + tok.lexer = self # Set additional attributes useful in token rules + self.lexmatch = m + self.lexpos = lexpos + + newtok = func(tok) + + # Every function must return a token, if nothing, we just move to next token + if not newtok: + lexpos = self.lexpos # This is here in case user has updated lexpos. + lexignore = self.lexignore # This is here in case there was a state change + break + + # Verify type of the token. If not in the token map, raise an error + if not self.lexoptimize: + if newtok.type not in self.lextokens_all: + raise LexError("%s:%d: Rule '%s' returned an unknown token type '%s'" % ( + func.__code__.co_filename, func.__code__.co_firstlineno, + func.__name__, newtok.type), lexdata[lexpos:]) + + return newtok + else: + # No match, see if in literals + if lexdata[lexpos] in self.lexliterals: + tok = LexToken() + tok.value = lexdata[lexpos] + tok.lineno = self.lineno + tok.type = tok.value + tok.lexpos = lexpos + self.lexpos = lexpos + 1 + return tok + + # No match. Call t_error() if defined. + if self.lexerrorf: + tok = LexToken() + tok.value = self.lexdata[lexpos:] + tok.lineno = self.lineno + tok.type = 'error' + tok.lexer = self + tok.lexpos = lexpos + self.lexpos = lexpos + newtok = self.lexerrorf(tok) + if lexpos == self.lexpos: + # Error method didn't change text position at all. This is an error. + raise LexError("Scanning error. Illegal character '%s'" % (lexdata[lexpos]), lexdata[lexpos:]) + lexpos = self.lexpos + if not newtok: + continue + return newtok + + self.lexpos = lexpos + raise LexError("Illegal character '%s' at index %d" % (lexdata[lexpos], lexpos), lexdata[lexpos:]) + + if self.lexeoff: + tok = LexToken() + tok.type = 'eof' + tok.value = '' + tok.lineno = self.lineno + tok.lexpos = lexpos + tok.lexer = self + self.lexpos = lexpos + newtok = self.lexeoff(tok) + return newtok + + self.lexpos = lexpos + 1 + if self.lexdata is None: + raise RuntimeError('No input string given with input()') + return None + + # Iterator interface + def __iter__(self): + return self + + def next(self): + t = self.token() + if t is None: + raise StopIteration + return t + + __next__ = next + +# ----------------------------------------------------------------------------- +# ==== Lex Builder === +# +# The functions and classes below are used to collect lexing information +# and build a Lexer object from it. +# ----------------------------------------------------------------------------- + +# ----------------------------------------------------------------------------- +# _get_regex(func) +# +# Returns the regular expression assigned to a function either as a doc string +# or as a .regex attribute attached by the @TOKEN decorator. +# ----------------------------------------------------------------------------- +def _get_regex(func): + return getattr(func, 'regex', func.__doc__) + +# ----------------------------------------------------------------------------- +# get_caller_module_dict() +# +# This function returns a dictionary containing all of the symbols defined within +# a caller further down the call stack. This is used to get the environment +# associated with the yacc() call if none was provided. +# ----------------------------------------------------------------------------- +def get_caller_module_dict(levels): + f = sys._getframe(levels) + ldict = f.f_globals.copy() + if f.f_globals != f.f_locals: + ldict.update(f.f_locals) + return ldict + +# ----------------------------------------------------------------------------- +# _funcs_to_names() +# +# Given a list of regular expression functions, this converts it to a list +# suitable for output to a table file +# ----------------------------------------------------------------------------- +def _funcs_to_names(funclist, namelist): + result = [] + for f, name in zip(funclist, namelist): + if f and f[0]: + result.append((name, f[1])) + else: + result.append(f) + return result + +# ----------------------------------------------------------------------------- +# _names_to_funcs() +# +# Given a list of regular expression function names, this converts it back to +# functions. +# ----------------------------------------------------------------------------- +def _names_to_funcs(namelist, fdict): + result = [] + for n in namelist: + if n and n[0]: + result.append((fdict[n[0]], n[1])) + else: + result.append(n) + return result + +# ----------------------------------------------------------------------------- +# _form_master_re() +# +# This function takes a list of all of the regex components and attempts to +# form the master regular expression. Given limitations in the Python re +# module, it may be necessary to break the master regex into separate expressions. +# ----------------------------------------------------------------------------- +def _form_master_re(relist, reflags, ldict, toknames): + if not relist: + return [] + regex = '|'.join(relist) + try: + lexre = re.compile(regex, reflags) + + # Build the index to function map for the matching engine + lexindexfunc = [None] * (max(lexre.groupindex.values()) + 1) + lexindexnames = lexindexfunc[:] + + for f, i in lexre.groupindex.items(): + handle = ldict.get(f, None) + if type(handle) in (types.FunctionType, types.MethodType): + lexindexfunc[i] = (handle, toknames[f]) + lexindexnames[i] = f + elif handle is not None: + lexindexnames[i] = f + if f.find('ignore_') > 0: + lexindexfunc[i] = (None, None) + else: + lexindexfunc[i] = (None, toknames[f]) + + return [(lexre, lexindexfunc)], [regex], [lexindexnames] + except Exception: + m = int(len(relist)/2) + if m == 0: + m = 1 + llist, lre, lnames = _form_master_re(relist[:m], reflags, ldict, toknames) + rlist, rre, rnames = _form_master_re(relist[m:], reflags, ldict, toknames) + return (llist+rlist), (lre+rre), (lnames+rnames) + +# ----------------------------------------------------------------------------- +# def _statetoken(s,names) +# +# Given a declaration name s of the form "t_" and a dictionary whose keys are +# state names, this function returns a tuple (states,tokenname) where states +# is a tuple of state names and tokenname is the name of the token. For example, +# calling this with s = "t_foo_bar_SPAM" might return (('foo','bar'),'SPAM') +# ----------------------------------------------------------------------------- +def _statetoken(s, names): + nonstate = 1 + parts = s.split('_') + for i, part in enumerate(parts[1:], 1): + if part not in names and part != 'ANY': + break + + if i > 1: + states = tuple(parts[1:i]) + else: + states = ('INITIAL',) + + if 'ANY' in states: + states = tuple(names) + + tokenname = '_'.join(parts[i:]) + return (states, tokenname) + + +# ----------------------------------------------------------------------------- +# LexerReflect() +# +# This class represents information needed to build a lexer as extracted from a +# user's input file. +# ----------------------------------------------------------------------------- +class LexerReflect(object): + def __init__(self, ldict, log=None, reflags=0): + self.ldict = ldict + self.error_func = None + self.tokens = [] + self.reflags = reflags + self.stateinfo = {'INITIAL': 'inclusive'} + self.modules = set() + self.error = False + self.log = PlyLogger(sys.stderr) if log is None else log + + # Get all of the basic information + def get_all(self): + self.get_tokens() + self.get_literals() + self.get_states() + self.get_rules() + + # Validate all of the information + def validate_all(self): + self.validate_tokens() + self.validate_literals() + self.validate_rules() + return self.error + + # Get the tokens map + def get_tokens(self): + tokens = self.ldict.get('tokens', None) + if not tokens: + self.log.error('No token list is defined') + self.error = True + return + + if not isinstance(tokens, (list, tuple)): + self.log.error('tokens must be a list or tuple') + self.error = True + return + + if not tokens: + self.log.error('tokens is empty') + self.error = True + return + + self.tokens = tokens + + # Validate the tokens + def validate_tokens(self): + terminals = {} + for n in self.tokens: + if not _is_identifier.match(n): + self.log.error("Bad token name '%s'", n) + self.error = True + if n in terminals: + self.log.warning("Token '%s' multiply defined", n) + terminals[n] = 1 + + # Get the literals specifier + def get_literals(self): + self.literals = self.ldict.get('literals', '') + if not self.literals: + self.literals = '' + + # Validate literals + def validate_literals(self): + try: + for c in self.literals: + if not isinstance(c, StringTypes) or len(c) > 1: + self.log.error('Invalid literal %s. Must be a single character', repr(c)) + self.error = True + + except TypeError: + self.log.error('Invalid literals specification. literals must be a sequence of characters') + self.error = True + + def get_states(self): + self.states = self.ldict.get('states', None) + # Build statemap + if self.states: + if not isinstance(self.states, (tuple, list)): + self.log.error('states must be defined as a tuple or list') + self.error = True + else: + for s in self.states: + if not isinstance(s, tuple) or len(s) != 2: + self.log.error("Invalid state specifier %s. Must be a tuple (statename,'exclusive|inclusive')", repr(s)) + self.error = True + continue + name, statetype = s + if not isinstance(name, StringTypes): + self.log.error('State name %s must be a string', repr(name)) + self.error = True + continue + if not (statetype == 'inclusive' or statetype == 'exclusive'): + self.log.error("State type for state %s must be 'inclusive' or 'exclusive'", name) + self.error = True + continue + if name in self.stateinfo: + self.log.error("State '%s' already defined", name) + self.error = True + continue + self.stateinfo[name] = statetype + + # Get all of the symbols with a t_ prefix and sort them into various + # categories (functions, strings, error functions, and ignore characters) + + def get_rules(self): + tsymbols = [f for f in self.ldict if f[:2] == 't_'] + + # Now build up a list of functions and a list of strings + self.toknames = {} # Mapping of symbols to token names + self.funcsym = {} # Symbols defined as functions + self.strsym = {} # Symbols defined as strings + self.ignore = {} # Ignore strings by state + self.errorf = {} # Error functions by state + self.eoff = {} # EOF functions by state + + for s in self.stateinfo: + self.funcsym[s] = [] + self.strsym[s] = [] + + if len(tsymbols) == 0: + self.log.error('No rules of the form t_rulename are defined') + self.error = True + return + + for f in tsymbols: + t = self.ldict[f] + states, tokname = _statetoken(f, self.stateinfo) + self.toknames[f] = tokname + + if hasattr(t, '__call__'): + if tokname == 'error': + for s in states: + self.errorf[s] = t + elif tokname == 'eof': + for s in states: + self.eoff[s] = t + elif tokname == 'ignore': + line = t.__code__.co_firstlineno + file = t.__code__.co_filename + self.log.error("%s:%d: Rule '%s' must be defined as a string", file, line, t.__name__) + self.error = True + else: + for s in states: + self.funcsym[s].append((f, t)) + elif isinstance(t, StringTypes): + if tokname == 'ignore': + for s in states: + self.ignore[s] = t + if '\\' in t: + self.log.warning("%s contains a literal backslash '\\'", f) + + elif tokname == 'error': + self.log.error("Rule '%s' must be defined as a function", f) + self.error = True + else: + for s in states: + self.strsym[s].append((f, t)) + else: + self.log.error('%s not defined as a function or string', f) + self.error = True + + # Sort the functions by line number + for f in self.funcsym.values(): + f.sort(key=lambda x: x[1].__code__.co_firstlineno) + + # Sort the strings by regular expression length + for s in self.strsym.values(): + s.sort(key=lambda x: len(x[1]), reverse=True) + + # Validate all of the t_rules collected + def validate_rules(self): + for state in self.stateinfo: + # Validate all rules defined by functions + + for fname, f in self.funcsym[state]: + line = f.__code__.co_firstlineno + file = f.__code__.co_filename + module = inspect.getmodule(f) + self.modules.add(module) + + tokname = self.toknames[fname] + if isinstance(f, types.MethodType): + reqargs = 2 + else: + reqargs = 1 + nargs = f.__code__.co_argcount + if nargs > reqargs: + self.log.error("%s:%d: Rule '%s' has too many arguments", file, line, f.__name__) + self.error = True + continue + + if nargs < reqargs: + self.log.error("%s:%d: Rule '%s' requires an argument", file, line, f.__name__) + self.error = True + continue + + if not _get_regex(f): + self.log.error("%s:%d: No regular expression defined for rule '%s'", file, line, f.__name__) + self.error = True + continue + + try: + c = re.compile('(?P<%s>%s)' % (fname, _get_regex(f)), self.reflags) + if c.match(''): + self.log.error("%s:%d: Regular expression for rule '%s' matches empty string", file, line, f.__name__) + self.error = True + except re.error as e: + self.log.error("%s:%d: Invalid regular expression for rule '%s'. %s", file, line, f.__name__, e) + if '#' in _get_regex(f): + self.log.error("%s:%d. Make sure '#' in rule '%s' is escaped with '\\#'", file, line, f.__name__) + self.error = True + + # Validate all rules defined by strings + for name, r in self.strsym[state]: + tokname = self.toknames[name] + if tokname == 'error': + self.log.error("Rule '%s' must be defined as a function", name) + self.error = True + continue + + if tokname not in self.tokens and tokname.find('ignore_') < 0: + self.log.error("Rule '%s' defined for an unspecified token %s", name, tokname) + self.error = True + continue + + try: + c = re.compile('(?P<%s>%s)' % (name, r), self.reflags) + if (c.match('')): + self.log.error("Regular expression for rule '%s' matches empty string", name) + self.error = True + except re.error as e: + self.log.error("Invalid regular expression for rule '%s'. %s", name, e) + if '#' in r: + self.log.error("Make sure '#' in rule '%s' is escaped with '\\#'", name) + self.error = True + + if not self.funcsym[state] and not self.strsym[state]: + self.log.error("No rules defined for state '%s'", state) + self.error = True + + # Validate the error function + efunc = self.errorf.get(state, None) + if efunc: + f = efunc + line = f.__code__.co_firstlineno + file = f.__code__.co_filename + module = inspect.getmodule(f) + self.modules.add(module) + + if isinstance(f, types.MethodType): + reqargs = 2 + else: + reqargs = 1 + nargs = f.__code__.co_argcount + if nargs > reqargs: + self.log.error("%s:%d: Rule '%s' has too many arguments", file, line, f.__name__) + self.error = True + + if nargs < reqargs: + self.log.error("%s:%d: Rule '%s' requires an argument", file, line, f.__name__) + self.error = True + + for module in self.modules: + self.validate_module(module) + + # ----------------------------------------------------------------------------- + # validate_module() + # + # This checks to see if there are duplicated t_rulename() functions or strings + # in the parser input file. This is done using a simple regular expression + # match on each line in the source code of the given module. + # ----------------------------------------------------------------------------- + + def validate_module(self, module): + try: + lines, linen = inspect.getsourcelines(module) + except IOError: + return + + fre = re.compile(r'\s*def\s+(t_[a-zA-Z_0-9]*)\(') + sre = re.compile(r'\s*(t_[a-zA-Z_0-9]*)\s*=') + + counthash = {} + linen += 1 + for line in lines: + m = fre.match(line) + if not m: + m = sre.match(line) + if m: + name = m.group(1) + prev = counthash.get(name) + if not prev: + counthash[name] = linen + else: + filename = inspect.getsourcefile(module) + self.log.error('%s:%d: Rule %s redefined. Previously defined on line %d', filename, linen, name, prev) + self.error = True + linen += 1 + +# ----------------------------------------------------------------------------- +# lex(module) +# +# Build all of the regular expression rules from definitions in the supplied module +# ----------------------------------------------------------------------------- +def lex(module=None, object=None, debug=False, optimize=False, lextab='lextab', + reflags=int(re.VERBOSE), nowarn=False, outputdir=None, debuglog=None, errorlog=None): + + if lextab is None: + lextab = 'lextab' + + global lexer + + ldict = None + stateinfo = {'INITIAL': 'inclusive'} + lexobj = Lexer() + lexobj.lexoptimize = optimize + global token, input + + if errorlog is None: + errorlog = PlyLogger(sys.stderr) + + if debug: + if debuglog is None: + debuglog = PlyLogger(sys.stderr) + + # Get the module dictionary used for the lexer + if object: + module = object + + # Get the module dictionary used for the parser + if module: + _items = [(k, getattr(module, k)) for k in dir(module)] + ldict = dict(_items) + # If no __file__ attribute is available, try to obtain it from the __module__ instead + if '__file__' not in ldict: + ldict['__file__'] = sys.modules[ldict['__module__']].__file__ + else: + ldict = get_caller_module_dict(2) + + # Determine if the module is package of a package or not. + # If so, fix the tabmodule setting so that tables load correctly + pkg = ldict.get('__package__') + if pkg and isinstance(lextab, str): + if '.' not in lextab: + lextab = pkg + '.' + lextab + + # Collect parser information from the dictionary + linfo = LexerReflect(ldict, log=errorlog, reflags=reflags) + linfo.get_all() + if not optimize: + if linfo.validate_all(): + raise SyntaxError("Can't build lexer") + + if optimize and lextab: + try: + lexobj.readtab(lextab, ldict) + token = lexobj.token + input = lexobj.input + lexer = lexobj + return lexobj + + except ImportError: + pass + + # Dump some basic debugging information + if debug: + debuglog.info('lex: tokens = %r', linfo.tokens) + debuglog.info('lex: literals = %r', linfo.literals) + debuglog.info('lex: states = %r', linfo.stateinfo) + + # Build a dictionary of valid token names + lexobj.lextokens = set() + for n in linfo.tokens: + lexobj.lextokens.add(n) + + # Get literals specification + if isinstance(linfo.literals, (list, tuple)): + lexobj.lexliterals = type(linfo.literals[0])().join(linfo.literals) + else: + lexobj.lexliterals = linfo.literals + + lexobj.lextokens_all = lexobj.lextokens | set(lexobj.lexliterals) + + # Get the stateinfo dictionary + stateinfo = linfo.stateinfo + + regexs = {} + # Build the master regular expressions + for state in stateinfo: + regex_list = [] + + # Add rules defined by functions first + for fname, f in linfo.funcsym[state]: + line = f.__code__.co_firstlineno + file = f.__code__.co_filename + regex_list.append('(?P<%s>%s)' % (fname, _get_regex(f))) + if debug: + debuglog.info("lex: Adding rule %s -> '%s' (state '%s')", fname, _get_regex(f), state) + + # Now add all of the simple rules + for name, r in linfo.strsym[state]: + regex_list.append('(?P<%s>%s)' % (name, r)) + if debug: + debuglog.info("lex: Adding rule %s -> '%s' (state '%s')", name, r, state) + + regexs[state] = regex_list + + # Build the master regular expressions + + if debug: + debuglog.info('lex: ==== MASTER REGEXS FOLLOW ====') + + for state in regexs: + lexre, re_text, re_names = _form_master_re(regexs[state], reflags, ldict, linfo.toknames) + lexobj.lexstatere[state] = lexre + lexobj.lexstateretext[state] = re_text + lexobj.lexstaterenames[state] = re_names + if debug: + for i, text in enumerate(re_text): + debuglog.info("lex: state '%s' : regex[%d] = '%s'", state, i, text) + + # For inclusive states, we need to add the regular expressions from the INITIAL state + for state, stype in stateinfo.items(): + if state != 'INITIAL' and stype == 'inclusive': + lexobj.lexstatere[state].extend(lexobj.lexstatere['INITIAL']) + lexobj.lexstateretext[state].extend(lexobj.lexstateretext['INITIAL']) + lexobj.lexstaterenames[state].extend(lexobj.lexstaterenames['INITIAL']) + + lexobj.lexstateinfo = stateinfo + lexobj.lexre = lexobj.lexstatere['INITIAL'] + lexobj.lexretext = lexobj.lexstateretext['INITIAL'] + lexobj.lexreflags = reflags + + # Set up ignore variables + lexobj.lexstateignore = linfo.ignore + lexobj.lexignore = lexobj.lexstateignore.get('INITIAL', '') + + # Set up error functions + lexobj.lexstateerrorf = linfo.errorf + lexobj.lexerrorf = linfo.errorf.get('INITIAL', None) + if not lexobj.lexerrorf: + errorlog.warning('No t_error rule is defined') + + # Set up eof functions + lexobj.lexstateeoff = linfo.eoff + lexobj.lexeoff = linfo.eoff.get('INITIAL', None) + + # Check state information for ignore and error rules + for s, stype in stateinfo.items(): + if stype == 'exclusive': + if s not in linfo.errorf: + errorlog.warning("No error rule is defined for exclusive state '%s'", s) + if s not in linfo.ignore and lexobj.lexignore: + errorlog.warning("No ignore rule is defined for exclusive state '%s'", s) + elif stype == 'inclusive': + if s not in linfo.errorf: + linfo.errorf[s] = linfo.errorf.get('INITIAL', None) + if s not in linfo.ignore: + linfo.ignore[s] = linfo.ignore.get('INITIAL', '') + + # Create global versions of the token() and input() functions + token = lexobj.token + input = lexobj.input + lexer = lexobj + + # If in optimize mode, we write the lextab + if lextab and optimize: + if outputdir is None: + # If no output directory is set, the location of the output files + # is determined according to the following rules: + # - If lextab specifies a package, files go into that package directory + # - Otherwise, files go in the same directory as the specifying module + if isinstance(lextab, types.ModuleType): + srcfile = lextab.__file__ + else: + if '.' not in lextab: + srcfile = ldict['__file__'] + else: + parts = lextab.split('.') + pkgname = '.'.join(parts[:-1]) + exec('import %s' % pkgname) + srcfile = getattr(sys.modules[pkgname], '__file__', '') + outputdir = os.path.dirname(srcfile) + try: + lexobj.writetab(lextab, outputdir) + except IOError as e: + errorlog.warning("Couldn't write lextab module %r. %s" % (lextab, e)) + + return lexobj + +# ----------------------------------------------------------------------------- +# runmain() +# +# This runs the lexer as a main program +# ----------------------------------------------------------------------------- + +def runmain(lexer=None, data=None): + if not data: + try: + filename = sys.argv[1] + f = open(filename) + data = f.read() + f.close() + except IndexError: + sys.stdout.write('Reading from standard input (type EOF to end):\n') + data = sys.stdin.read() + + if lexer: + _input = lexer.input + else: + _input = input + _input(data) + if lexer: + _token = lexer.token + else: + _token = token + + while True: + tok = _token() + if not tok: + break + sys.stdout.write('(%s,%r,%d,%d)\n' % (tok.type, tok.value, tok.lineno, tok.lexpos)) + +# ----------------------------------------------------------------------------- +# @TOKEN(regex) +# +# This decorator function can be used to set the regex expression on a function +# when its docstring might need to be set in an alternative way +# ----------------------------------------------------------------------------- + +def TOKEN(r): + def set_regex(f): + if hasattr(r, '__call__'): + f.regex = _get_regex(r) + else: + f.regex = r + return f + return set_regex + +# Alternative spelling of the TOKEN decorator +Token = TOKEN diff --git a/.venv/Lib/site-packages/pycparser/ply/yacc.py b/.venv/Lib/site-packages/pycparser/ply/yacc.py new file mode 100644 index 00000000..20b4f286 --- /dev/null +++ b/.venv/Lib/site-packages/pycparser/ply/yacc.py @@ -0,0 +1,3494 @@ +# ----------------------------------------------------------------------------- +# ply: yacc.py +# +# Copyright (C) 2001-2017 +# David M. Beazley (Dabeaz LLC) +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the David Beazley or Dabeaz LLC may be used to +# endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# ----------------------------------------------------------------------------- +# +# This implements an LR parser that is constructed from grammar rules defined +# as Python functions. The grammer is specified by supplying the BNF inside +# Python documentation strings. The inspiration for this technique was borrowed +# from John Aycock's Spark parsing system. PLY might be viewed as cross between +# Spark and the GNU bison utility. +# +# The current implementation is only somewhat object-oriented. The +# LR parser itself is defined in terms of an object (which allows multiple +# parsers to co-exist). However, most of the variables used during table +# construction are defined in terms of global variables. Users shouldn't +# notice unless they are trying to define multiple parsers at the same +# time using threads (in which case they should have their head examined). +# +# This implementation supports both SLR and LALR(1) parsing. LALR(1) +# support was originally implemented by Elias Ioup (ezioup@alumni.uchicago.edu), +# using the algorithm found in Aho, Sethi, and Ullman "Compilers: Principles, +# Techniques, and Tools" (The Dragon Book). LALR(1) has since been replaced +# by the more efficient DeRemer and Pennello algorithm. +# +# :::::::: WARNING ::::::: +# +# Construction of LR parsing tables is fairly complicated and expensive. +# To make this module run fast, a *LOT* of work has been put into +# optimization---often at the expensive of readability and what might +# consider to be good Python "coding style." Modify the code at your +# own risk! +# ---------------------------------------------------------------------------- + +import re +import types +import sys +import os.path +import inspect +import base64 +import warnings + +__version__ = '3.10' +__tabversion__ = '3.10' + +#----------------------------------------------------------------------------- +# === User configurable parameters === +# +# Change these to modify the default behavior of yacc (if you wish) +#----------------------------------------------------------------------------- + +yaccdebug = True # Debugging mode. If set, yacc generates a + # a 'parser.out' file in the current directory + +debug_file = 'parser.out' # Default name of the debugging file +tab_module = 'parsetab' # Default name of the table module +default_lr = 'LALR' # Default LR table generation method + +error_count = 3 # Number of symbols that must be shifted to leave recovery mode + +yaccdevel = False # Set to True if developing yacc. This turns off optimized + # implementations of certain functions. + +resultlimit = 40 # Size limit of results when running in debug mode. + +pickle_protocol = 0 # Protocol to use when writing pickle files + +# String type-checking compatibility +if sys.version_info[0] < 3: + string_types = basestring +else: + string_types = str + +MAXINT = sys.maxsize + +# This object is a stand-in for a logging object created by the +# logging module. PLY will use this by default to create things +# such as the parser.out file. If a user wants more detailed +# information, they can create their own logging object and pass +# it into PLY. + +class PlyLogger(object): + def __init__(self, f): + self.f = f + + def debug(self, msg, *args, **kwargs): + self.f.write((msg % args) + '\n') + + info = debug + + def warning(self, msg, *args, **kwargs): + self.f.write('WARNING: ' + (msg % args) + '\n') + + def error(self, msg, *args, **kwargs): + self.f.write('ERROR: ' + (msg % args) + '\n') + + critical = debug + +# Null logger is used when no output is generated. Does nothing. +class NullLogger(object): + def __getattribute__(self, name): + return self + + def __call__(self, *args, **kwargs): + return self + +# Exception raised for yacc-related errors +class YaccError(Exception): + pass + +# Format the result message that the parser produces when running in debug mode. +def format_result(r): + repr_str = repr(r) + if '\n' in repr_str: + repr_str = repr(repr_str) + if len(repr_str) > resultlimit: + repr_str = repr_str[:resultlimit] + ' ...' + result = '<%s @ 0x%x> (%s)' % (type(r).__name__, id(r), repr_str) + return result + +# Format stack entries when the parser is running in debug mode +def format_stack_entry(r): + repr_str = repr(r) + if '\n' in repr_str: + repr_str = repr(repr_str) + if len(repr_str) < 16: + return repr_str + else: + return '<%s @ 0x%x>' % (type(r).__name__, id(r)) + +# Panic mode error recovery support. This feature is being reworked--much of the +# code here is to offer a deprecation/backwards compatible transition + +_errok = None +_token = None +_restart = None +_warnmsg = '''PLY: Don't use global functions errok(), token(), and restart() in p_error(). +Instead, invoke the methods on the associated parser instance: + + def p_error(p): + ... + # Use parser.errok(), parser.token(), parser.restart() + ... + + parser = yacc.yacc() +''' + +def errok(): + warnings.warn(_warnmsg) + return _errok() + +def restart(): + warnings.warn(_warnmsg) + return _restart() + +def token(): + warnings.warn(_warnmsg) + return _token() + +# Utility function to call the p_error() function with some deprecation hacks +def call_errorfunc(errorfunc, token, parser): + global _errok, _token, _restart + _errok = parser.errok + _token = parser.token + _restart = parser.restart + r = errorfunc(token) + try: + del _errok, _token, _restart + except NameError: + pass + return r + +#----------------------------------------------------------------------------- +# === LR Parsing Engine === +# +# The following classes are used for the LR parser itself. These are not +# used during table construction and are independent of the actual LR +# table generation algorithm +#----------------------------------------------------------------------------- + +# This class is used to hold non-terminal grammar symbols during parsing. +# It normally has the following attributes set: +# .type = Grammar symbol type +# .value = Symbol value +# .lineno = Starting line number +# .endlineno = Ending line number (optional, set automatically) +# .lexpos = Starting lex position +# .endlexpos = Ending lex position (optional, set automatically) + +class YaccSymbol: + def __str__(self): + return self.type + + def __repr__(self): + return str(self) + +# This class is a wrapper around the objects actually passed to each +# grammar rule. Index lookup and assignment actually assign the +# .value attribute of the underlying YaccSymbol object. +# The lineno() method returns the line number of a given +# item (or 0 if not defined). The linespan() method returns +# a tuple of (startline,endline) representing the range of lines +# for a symbol. The lexspan() method returns a tuple (lexpos,endlexpos) +# representing the range of positional information for a symbol. + +class YaccProduction: + def __init__(self, s, stack=None): + self.slice = s + self.stack = stack + self.lexer = None + self.parser = None + + def __getitem__(self, n): + if isinstance(n, slice): + return [s.value for s in self.slice[n]] + elif n >= 0: + return self.slice[n].value + else: + return self.stack[n].value + + def __setitem__(self, n, v): + self.slice[n].value = v + + def __getslice__(self, i, j): + return [s.value for s in self.slice[i:j]] + + def __len__(self): + return len(self.slice) + + def lineno(self, n): + return getattr(self.slice[n], 'lineno', 0) + + def set_lineno(self, n, lineno): + self.slice[n].lineno = lineno + + def linespan(self, n): + startline = getattr(self.slice[n], 'lineno', 0) + endline = getattr(self.slice[n], 'endlineno', startline) + return startline, endline + + def lexpos(self, n): + return getattr(self.slice[n], 'lexpos', 0) + + def lexspan(self, n): + startpos = getattr(self.slice[n], 'lexpos', 0) + endpos = getattr(self.slice[n], 'endlexpos', startpos) + return startpos, endpos + + def error(self): + raise SyntaxError + +# ----------------------------------------------------------------------------- +# == LRParser == +# +# The LR Parsing engine. +# ----------------------------------------------------------------------------- + +class LRParser: + def __init__(self, lrtab, errorf): + self.productions = lrtab.lr_productions + self.action = lrtab.lr_action + self.goto = lrtab.lr_goto + self.errorfunc = errorf + self.set_defaulted_states() + self.errorok = True + + def errok(self): + self.errorok = True + + def restart(self): + del self.statestack[:] + del self.symstack[:] + sym = YaccSymbol() + sym.type = '$end' + self.symstack.append(sym) + self.statestack.append(0) + + # Defaulted state support. + # This method identifies parser states where there is only one possible reduction action. + # For such states, the parser can make a choose to make a rule reduction without consuming + # the next look-ahead token. This delayed invocation of the tokenizer can be useful in + # certain kinds of advanced parsing situations where the lexer and parser interact with + # each other or change states (i.e., manipulation of scope, lexer states, etc.). + # + # See: https://www.gnu.org/software/bison/manual/html_node/Default-Reductions.html#Default-Reductions + def set_defaulted_states(self): + self.defaulted_states = {} + for state, actions in self.action.items(): + rules = list(actions.values()) + if len(rules) == 1 and rules[0] < 0: + self.defaulted_states[state] = rules[0] + + def disable_defaulted_states(self): + self.defaulted_states = {} + + def parse(self, input=None, lexer=None, debug=False, tracking=False, tokenfunc=None): + if debug or yaccdevel: + if isinstance(debug, int): + debug = PlyLogger(sys.stderr) + return self.parsedebug(input, lexer, debug, tracking, tokenfunc) + elif tracking: + return self.parseopt(input, lexer, debug, tracking, tokenfunc) + else: + return self.parseopt_notrack(input, lexer, debug, tracking, tokenfunc) + + + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # parsedebug(). + # + # This is the debugging enabled version of parse(). All changes made to the + # parsing engine should be made here. Optimized versions of this function + # are automatically created by the ply/ygen.py script. This script cuts out + # sections enclosed in markers such as this: + # + # #--! DEBUG + # statements + # #--! DEBUG + # + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + def parsedebug(self, input=None, lexer=None, debug=False, tracking=False, tokenfunc=None): + #--! parsedebug-start + lookahead = None # Current lookahead symbol + lookaheadstack = [] # Stack of lookahead symbols + actions = self.action # Local reference to action table (to avoid lookup on self.) + goto = self.goto # Local reference to goto table (to avoid lookup on self.) + prod = self.productions # Local reference to production list (to avoid lookup on self.) + defaulted_states = self.defaulted_states # Local reference to defaulted states + pslice = YaccProduction(None) # Production object passed to grammar rules + errorcount = 0 # Used during error recovery + + #--! DEBUG + debug.info('PLY: PARSE DEBUG START') + #--! DEBUG + + # If no lexer was given, we will try to use the lex module + if not lexer: + from . import lex + lexer = lex.lexer + + # Set up the lexer and parser objects on pslice + pslice.lexer = lexer + pslice.parser = self + + # If input was supplied, pass to lexer + if input is not None: + lexer.input(input) + + if tokenfunc is None: + # Tokenize function + get_token = lexer.token + else: + get_token = tokenfunc + + # Set the parser() token method (sometimes used in error recovery) + self.token = get_token + + # Set up the state and symbol stacks + + statestack = [] # Stack of parsing states + self.statestack = statestack + symstack = [] # Stack of grammar symbols + self.symstack = symstack + + pslice.stack = symstack # Put in the production + errtoken = None # Err token + + # The start state is assumed to be (0,$end) + + statestack.append(0) + sym = YaccSymbol() + sym.type = '$end' + symstack.append(sym) + state = 0 + while True: + # Get the next symbol on the input. If a lookahead symbol + # is already set, we just use that. Otherwise, we'll pull + # the next token off of the lookaheadstack or from the lexer + + #--! DEBUG + debug.debug('') + debug.debug('State : %s', state) + #--! DEBUG + + if state not in defaulted_states: + if not lookahead: + if not lookaheadstack: + lookahead = get_token() # Get the next token + else: + lookahead = lookaheadstack.pop() + if not lookahead: + lookahead = YaccSymbol() + lookahead.type = '$end' + + # Check the action table + ltype = lookahead.type + t = actions[state].get(ltype) + else: + t = defaulted_states[state] + #--! DEBUG + debug.debug('Defaulted state %s: Reduce using %d', state, -t) + #--! DEBUG + + #--! DEBUG + debug.debug('Stack : %s', + ('%s . %s' % (' '.join([xx.type for xx in symstack][1:]), str(lookahead))).lstrip()) + #--! DEBUG + + if t is not None: + if t > 0: + # shift a symbol on the stack + statestack.append(t) + state = t + + #--! DEBUG + debug.debug('Action : Shift and goto state %s', t) + #--! DEBUG + + symstack.append(lookahead) + lookahead = None + + # Decrease error count on successful shift + if errorcount: + errorcount -= 1 + continue + + if t < 0: + # reduce a symbol on the stack, emit a production + p = prod[-t] + pname = p.name + plen = p.len + + # Get production function + sym = YaccSymbol() + sym.type = pname # Production name + sym.value = None + + #--! DEBUG + if plen: + debug.info('Action : Reduce rule [%s] with %s and goto state %d', p.str, + '['+','.join([format_stack_entry(_v.value) for _v in symstack[-plen:]])+']', + goto[statestack[-1-plen]][pname]) + else: + debug.info('Action : Reduce rule [%s] with %s and goto state %d', p.str, [], + goto[statestack[-1]][pname]) + + #--! DEBUG + + if plen: + targ = symstack[-plen-1:] + targ[0] = sym + + #--! TRACKING + if tracking: + t1 = targ[1] + sym.lineno = t1.lineno + sym.lexpos = t1.lexpos + t1 = targ[-1] + sym.endlineno = getattr(t1, 'endlineno', t1.lineno) + sym.endlexpos = getattr(t1, 'endlexpos', t1.lexpos) + #--! TRACKING + + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # The code enclosed in this section is duplicated + # below as a performance optimization. Make sure + # changes get made in both locations. + + pslice.slice = targ + + try: + # Call the grammar rule with our special slice object + del symstack[-plen:] + self.state = state + p.callable(pslice) + del statestack[-plen:] + #--! DEBUG + debug.info('Result : %s', format_result(pslice[0])) + #--! DEBUG + symstack.append(sym) + state = goto[statestack[-1]][pname] + statestack.append(state) + except SyntaxError: + # If an error was set. Enter error recovery state + lookaheadstack.append(lookahead) # Save the current lookahead token + symstack.extend(targ[1:-1]) # Put the production slice back on the stack + statestack.pop() # Pop back one state (before the reduce) + state = statestack[-1] + sym.type = 'error' + sym.value = 'error' + lookahead = sym + errorcount = error_count + self.errorok = False + + continue + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + else: + + #--! TRACKING + if tracking: + sym.lineno = lexer.lineno + sym.lexpos = lexer.lexpos + #--! TRACKING + + targ = [sym] + + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # The code enclosed in this section is duplicated + # above as a performance optimization. Make sure + # changes get made in both locations. + + pslice.slice = targ + + try: + # Call the grammar rule with our special slice object + self.state = state + p.callable(pslice) + #--! DEBUG + debug.info('Result : %s', format_result(pslice[0])) + #--! DEBUG + symstack.append(sym) + state = goto[statestack[-1]][pname] + statestack.append(state) + except SyntaxError: + # If an error was set. Enter error recovery state + lookaheadstack.append(lookahead) # Save the current lookahead token + statestack.pop() # Pop back one state (before the reduce) + state = statestack[-1] + sym.type = 'error' + sym.value = 'error' + lookahead = sym + errorcount = error_count + self.errorok = False + + continue + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + if t == 0: + n = symstack[-1] + result = getattr(n, 'value', None) + #--! DEBUG + debug.info('Done : Returning %s', format_result(result)) + debug.info('PLY: PARSE DEBUG END') + #--! DEBUG + return result + + if t is None: + + #--! DEBUG + debug.error('Error : %s', + ('%s . %s' % (' '.join([xx.type for xx in symstack][1:]), str(lookahead))).lstrip()) + #--! DEBUG + + # We have some kind of parsing error here. To handle + # this, we are going to push the current token onto + # the tokenstack and replace it with an 'error' token. + # If there are any synchronization rules, they may + # catch it. + # + # In addition to pushing the error token, we call call + # the user defined p_error() function if this is the + # first syntax error. This function is only called if + # errorcount == 0. + if errorcount == 0 or self.errorok: + errorcount = error_count + self.errorok = False + errtoken = lookahead + if errtoken.type == '$end': + errtoken = None # End of file! + if self.errorfunc: + if errtoken and not hasattr(errtoken, 'lexer'): + errtoken.lexer = lexer + self.state = state + tok = call_errorfunc(self.errorfunc, errtoken, self) + if self.errorok: + # User must have done some kind of panic + # mode recovery on their own. The + # returned token is the next lookahead + lookahead = tok + errtoken = None + continue + else: + if errtoken: + if hasattr(errtoken, 'lineno'): + lineno = lookahead.lineno + else: + lineno = 0 + if lineno: + sys.stderr.write('yacc: Syntax error at line %d, token=%s\n' % (lineno, errtoken.type)) + else: + sys.stderr.write('yacc: Syntax error, token=%s' % errtoken.type) + else: + sys.stderr.write('yacc: Parse error in input. EOF\n') + return + + else: + errorcount = error_count + + # case 1: the statestack only has 1 entry on it. If we're in this state, the + # entire parse has been rolled back and we're completely hosed. The token is + # discarded and we just keep going. + + if len(statestack) <= 1 and lookahead.type != '$end': + lookahead = None + errtoken = None + state = 0 + # Nuke the pushback stack + del lookaheadstack[:] + continue + + # case 2: the statestack has a couple of entries on it, but we're + # at the end of the file. nuke the top entry and generate an error token + + # Start nuking entries on the stack + if lookahead.type == '$end': + # Whoa. We're really hosed here. Bail out + return + + if lookahead.type != 'error': + sym = symstack[-1] + if sym.type == 'error': + # Hmmm. Error is on top of stack, we'll just nuke input + # symbol and continue + #--! TRACKING + if tracking: + sym.endlineno = getattr(lookahead, 'lineno', sym.lineno) + sym.endlexpos = getattr(lookahead, 'lexpos', sym.lexpos) + #--! TRACKING + lookahead = None + continue + + # Create the error symbol for the first time and make it the new lookahead symbol + t = YaccSymbol() + t.type = 'error' + + if hasattr(lookahead, 'lineno'): + t.lineno = t.endlineno = lookahead.lineno + if hasattr(lookahead, 'lexpos'): + t.lexpos = t.endlexpos = lookahead.lexpos + t.value = lookahead + lookaheadstack.append(lookahead) + lookahead = t + else: + sym = symstack.pop() + #--! TRACKING + if tracking: + lookahead.lineno = sym.lineno + lookahead.lexpos = sym.lexpos + #--! TRACKING + statestack.pop() + state = statestack[-1] + + continue + + # Call an error function here + raise RuntimeError('yacc: internal parser error!!!\n') + + #--! parsedebug-end + + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # parseopt(). + # + # Optimized version of parse() method. DO NOT EDIT THIS CODE DIRECTLY! + # This code is automatically generated by the ply/ygen.py script. Make + # changes to the parsedebug() method instead. + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + def parseopt(self, input=None, lexer=None, debug=False, tracking=False, tokenfunc=None): + #--! parseopt-start + lookahead = None # Current lookahead symbol + lookaheadstack = [] # Stack of lookahead symbols + actions = self.action # Local reference to action table (to avoid lookup on self.) + goto = self.goto # Local reference to goto table (to avoid lookup on self.) + prod = self.productions # Local reference to production list (to avoid lookup on self.) + defaulted_states = self.defaulted_states # Local reference to defaulted states + pslice = YaccProduction(None) # Production object passed to grammar rules + errorcount = 0 # Used during error recovery + + + # If no lexer was given, we will try to use the lex module + if not lexer: + from . import lex + lexer = lex.lexer + + # Set up the lexer and parser objects on pslice + pslice.lexer = lexer + pslice.parser = self + + # If input was supplied, pass to lexer + if input is not None: + lexer.input(input) + + if tokenfunc is None: + # Tokenize function + get_token = lexer.token + else: + get_token = tokenfunc + + # Set the parser() token method (sometimes used in error recovery) + self.token = get_token + + # Set up the state and symbol stacks + + statestack = [] # Stack of parsing states + self.statestack = statestack + symstack = [] # Stack of grammar symbols + self.symstack = symstack + + pslice.stack = symstack # Put in the production + errtoken = None # Err token + + # The start state is assumed to be (0,$end) + + statestack.append(0) + sym = YaccSymbol() + sym.type = '$end' + symstack.append(sym) + state = 0 + while True: + # Get the next symbol on the input. If a lookahead symbol + # is already set, we just use that. Otherwise, we'll pull + # the next token off of the lookaheadstack or from the lexer + + + if state not in defaulted_states: + if not lookahead: + if not lookaheadstack: + lookahead = get_token() # Get the next token + else: + lookahead = lookaheadstack.pop() + if not lookahead: + lookahead = YaccSymbol() + lookahead.type = '$end' + + # Check the action table + ltype = lookahead.type + t = actions[state].get(ltype) + else: + t = defaulted_states[state] + + + if t is not None: + if t > 0: + # shift a symbol on the stack + statestack.append(t) + state = t + + + symstack.append(lookahead) + lookahead = None + + # Decrease error count on successful shift + if errorcount: + errorcount -= 1 + continue + + if t < 0: + # reduce a symbol on the stack, emit a production + p = prod[-t] + pname = p.name + plen = p.len + + # Get production function + sym = YaccSymbol() + sym.type = pname # Production name + sym.value = None + + + if plen: + targ = symstack[-plen-1:] + targ[0] = sym + + #--! TRACKING + if tracking: + t1 = targ[1] + sym.lineno = t1.lineno + sym.lexpos = t1.lexpos + t1 = targ[-1] + sym.endlineno = getattr(t1, 'endlineno', t1.lineno) + sym.endlexpos = getattr(t1, 'endlexpos', t1.lexpos) + #--! TRACKING + + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # The code enclosed in this section is duplicated + # below as a performance optimization. Make sure + # changes get made in both locations. + + pslice.slice = targ + + try: + # Call the grammar rule with our special slice object + del symstack[-plen:] + self.state = state + p.callable(pslice) + del statestack[-plen:] + symstack.append(sym) + state = goto[statestack[-1]][pname] + statestack.append(state) + except SyntaxError: + # If an error was set. Enter error recovery state + lookaheadstack.append(lookahead) # Save the current lookahead token + symstack.extend(targ[1:-1]) # Put the production slice back on the stack + statestack.pop() # Pop back one state (before the reduce) + state = statestack[-1] + sym.type = 'error' + sym.value = 'error' + lookahead = sym + errorcount = error_count + self.errorok = False + + continue + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + else: + + #--! TRACKING + if tracking: + sym.lineno = lexer.lineno + sym.lexpos = lexer.lexpos + #--! TRACKING + + targ = [sym] + + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # The code enclosed in this section is duplicated + # above as a performance optimization. Make sure + # changes get made in both locations. + + pslice.slice = targ + + try: + # Call the grammar rule with our special slice object + self.state = state + p.callable(pslice) + symstack.append(sym) + state = goto[statestack[-1]][pname] + statestack.append(state) + except SyntaxError: + # If an error was set. Enter error recovery state + lookaheadstack.append(lookahead) # Save the current lookahead token + statestack.pop() # Pop back one state (before the reduce) + state = statestack[-1] + sym.type = 'error' + sym.value = 'error' + lookahead = sym + errorcount = error_count + self.errorok = False + + continue + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + if t == 0: + n = symstack[-1] + result = getattr(n, 'value', None) + return result + + if t is None: + + + # We have some kind of parsing error here. To handle + # this, we are going to push the current token onto + # the tokenstack and replace it with an 'error' token. + # If there are any synchronization rules, they may + # catch it. + # + # In addition to pushing the error token, we call call + # the user defined p_error() function if this is the + # first syntax error. This function is only called if + # errorcount == 0. + if errorcount == 0 or self.errorok: + errorcount = error_count + self.errorok = False + errtoken = lookahead + if errtoken.type == '$end': + errtoken = None # End of file! + if self.errorfunc: + if errtoken and not hasattr(errtoken, 'lexer'): + errtoken.lexer = lexer + self.state = state + tok = call_errorfunc(self.errorfunc, errtoken, self) + if self.errorok: + # User must have done some kind of panic + # mode recovery on their own. The + # returned token is the next lookahead + lookahead = tok + errtoken = None + continue + else: + if errtoken: + if hasattr(errtoken, 'lineno'): + lineno = lookahead.lineno + else: + lineno = 0 + if lineno: + sys.stderr.write('yacc: Syntax error at line %d, token=%s\n' % (lineno, errtoken.type)) + else: + sys.stderr.write('yacc: Syntax error, token=%s' % errtoken.type) + else: + sys.stderr.write('yacc: Parse error in input. EOF\n') + return + + else: + errorcount = error_count + + # case 1: the statestack only has 1 entry on it. If we're in this state, the + # entire parse has been rolled back and we're completely hosed. The token is + # discarded and we just keep going. + + if len(statestack) <= 1 and lookahead.type != '$end': + lookahead = None + errtoken = None + state = 0 + # Nuke the pushback stack + del lookaheadstack[:] + continue + + # case 2: the statestack has a couple of entries on it, but we're + # at the end of the file. nuke the top entry and generate an error token + + # Start nuking entries on the stack + if lookahead.type == '$end': + # Whoa. We're really hosed here. Bail out + return + + if lookahead.type != 'error': + sym = symstack[-1] + if sym.type == 'error': + # Hmmm. Error is on top of stack, we'll just nuke input + # symbol and continue + #--! TRACKING + if tracking: + sym.endlineno = getattr(lookahead, 'lineno', sym.lineno) + sym.endlexpos = getattr(lookahead, 'lexpos', sym.lexpos) + #--! TRACKING + lookahead = None + continue + + # Create the error symbol for the first time and make it the new lookahead symbol + t = YaccSymbol() + t.type = 'error' + + if hasattr(lookahead, 'lineno'): + t.lineno = t.endlineno = lookahead.lineno + if hasattr(lookahead, 'lexpos'): + t.lexpos = t.endlexpos = lookahead.lexpos + t.value = lookahead + lookaheadstack.append(lookahead) + lookahead = t + else: + sym = symstack.pop() + #--! TRACKING + if tracking: + lookahead.lineno = sym.lineno + lookahead.lexpos = sym.lexpos + #--! TRACKING + statestack.pop() + state = statestack[-1] + + continue + + # Call an error function here + raise RuntimeError('yacc: internal parser error!!!\n') + + #--! parseopt-end + + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # parseopt_notrack(). + # + # Optimized version of parseopt() with line number tracking removed. + # DO NOT EDIT THIS CODE DIRECTLY. This code is automatically generated + # by the ply/ygen.py script. Make changes to the parsedebug() method instead. + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + def parseopt_notrack(self, input=None, lexer=None, debug=False, tracking=False, tokenfunc=None): + #--! parseopt-notrack-start + lookahead = None # Current lookahead symbol + lookaheadstack = [] # Stack of lookahead symbols + actions = self.action # Local reference to action table (to avoid lookup on self.) + goto = self.goto # Local reference to goto table (to avoid lookup on self.) + prod = self.productions # Local reference to production list (to avoid lookup on self.) + defaulted_states = self.defaulted_states # Local reference to defaulted states + pslice = YaccProduction(None) # Production object passed to grammar rules + errorcount = 0 # Used during error recovery + + + # If no lexer was given, we will try to use the lex module + if not lexer: + from . import lex + lexer = lex.lexer + + # Set up the lexer and parser objects on pslice + pslice.lexer = lexer + pslice.parser = self + + # If input was supplied, pass to lexer + if input is not None: + lexer.input(input) + + if tokenfunc is None: + # Tokenize function + get_token = lexer.token + else: + get_token = tokenfunc + + # Set the parser() token method (sometimes used in error recovery) + self.token = get_token + + # Set up the state and symbol stacks + + statestack = [] # Stack of parsing states + self.statestack = statestack + symstack = [] # Stack of grammar symbols + self.symstack = symstack + + pslice.stack = symstack # Put in the production + errtoken = None # Err token + + # The start state is assumed to be (0,$end) + + statestack.append(0) + sym = YaccSymbol() + sym.type = '$end' + symstack.append(sym) + state = 0 + while True: + # Get the next symbol on the input. If a lookahead symbol + # is already set, we just use that. Otherwise, we'll pull + # the next token off of the lookaheadstack or from the lexer + + + if state not in defaulted_states: + if not lookahead: + if not lookaheadstack: + lookahead = get_token() # Get the next token + else: + lookahead = lookaheadstack.pop() + if not lookahead: + lookahead = YaccSymbol() + lookahead.type = '$end' + + # Check the action table + ltype = lookahead.type + t = actions[state].get(ltype) + else: + t = defaulted_states[state] + + + if t is not None: + if t > 0: + # shift a symbol on the stack + statestack.append(t) + state = t + + + symstack.append(lookahead) + lookahead = None + + # Decrease error count on successful shift + if errorcount: + errorcount -= 1 + continue + + if t < 0: + # reduce a symbol on the stack, emit a production + p = prod[-t] + pname = p.name + plen = p.len + + # Get production function + sym = YaccSymbol() + sym.type = pname # Production name + sym.value = None + + + if plen: + targ = symstack[-plen-1:] + targ[0] = sym + + + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # The code enclosed in this section is duplicated + # below as a performance optimization. Make sure + # changes get made in both locations. + + pslice.slice = targ + + try: + # Call the grammar rule with our special slice object + del symstack[-plen:] + self.state = state + p.callable(pslice) + del statestack[-plen:] + symstack.append(sym) + state = goto[statestack[-1]][pname] + statestack.append(state) + except SyntaxError: + # If an error was set. Enter error recovery state + lookaheadstack.append(lookahead) # Save the current lookahead token + symstack.extend(targ[1:-1]) # Put the production slice back on the stack + statestack.pop() # Pop back one state (before the reduce) + state = statestack[-1] + sym.type = 'error' + sym.value = 'error' + lookahead = sym + errorcount = error_count + self.errorok = False + + continue + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + else: + + + targ = [sym] + + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # The code enclosed in this section is duplicated + # above as a performance optimization. Make sure + # changes get made in both locations. + + pslice.slice = targ + + try: + # Call the grammar rule with our special slice object + self.state = state + p.callable(pslice) + symstack.append(sym) + state = goto[statestack[-1]][pname] + statestack.append(state) + except SyntaxError: + # If an error was set. Enter error recovery state + lookaheadstack.append(lookahead) # Save the current lookahead token + statestack.pop() # Pop back one state (before the reduce) + state = statestack[-1] + sym.type = 'error' + sym.value = 'error' + lookahead = sym + errorcount = error_count + self.errorok = False + + continue + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + if t == 0: + n = symstack[-1] + result = getattr(n, 'value', None) + return result + + if t is None: + + + # We have some kind of parsing error here. To handle + # this, we are going to push the current token onto + # the tokenstack and replace it with an 'error' token. + # If there are any synchronization rules, they may + # catch it. + # + # In addition to pushing the error token, we call call + # the user defined p_error() function if this is the + # first syntax error. This function is only called if + # errorcount == 0. + if errorcount == 0 or self.errorok: + errorcount = error_count + self.errorok = False + errtoken = lookahead + if errtoken.type == '$end': + errtoken = None # End of file! + if self.errorfunc: + if errtoken and not hasattr(errtoken, 'lexer'): + errtoken.lexer = lexer + self.state = state + tok = call_errorfunc(self.errorfunc, errtoken, self) + if self.errorok: + # User must have done some kind of panic + # mode recovery on their own. The + # returned token is the next lookahead + lookahead = tok + errtoken = None + continue + else: + if errtoken: + if hasattr(errtoken, 'lineno'): + lineno = lookahead.lineno + else: + lineno = 0 + if lineno: + sys.stderr.write('yacc: Syntax error at line %d, token=%s\n' % (lineno, errtoken.type)) + else: + sys.stderr.write('yacc: Syntax error, token=%s' % errtoken.type) + else: + sys.stderr.write('yacc: Parse error in input. EOF\n') + return + + else: + errorcount = error_count + + # case 1: the statestack only has 1 entry on it. If we're in this state, the + # entire parse has been rolled back and we're completely hosed. The token is + # discarded and we just keep going. + + if len(statestack) <= 1 and lookahead.type != '$end': + lookahead = None + errtoken = None + state = 0 + # Nuke the pushback stack + del lookaheadstack[:] + continue + + # case 2: the statestack has a couple of entries on it, but we're + # at the end of the file. nuke the top entry and generate an error token + + # Start nuking entries on the stack + if lookahead.type == '$end': + # Whoa. We're really hosed here. Bail out + return + + if lookahead.type != 'error': + sym = symstack[-1] + if sym.type == 'error': + # Hmmm. Error is on top of stack, we'll just nuke input + # symbol and continue + lookahead = None + continue + + # Create the error symbol for the first time and make it the new lookahead symbol + t = YaccSymbol() + t.type = 'error' + + if hasattr(lookahead, 'lineno'): + t.lineno = t.endlineno = lookahead.lineno + if hasattr(lookahead, 'lexpos'): + t.lexpos = t.endlexpos = lookahead.lexpos + t.value = lookahead + lookaheadstack.append(lookahead) + lookahead = t + else: + sym = symstack.pop() + statestack.pop() + state = statestack[-1] + + continue + + # Call an error function here + raise RuntimeError('yacc: internal parser error!!!\n') + + #--! parseopt-notrack-end + +# ----------------------------------------------------------------------------- +# === Grammar Representation === +# +# The following functions, classes, and variables are used to represent and +# manipulate the rules that make up a grammar. +# ----------------------------------------------------------------------------- + +# regex matching identifiers +_is_identifier = re.compile(r'^[a-zA-Z0-9_-]+$') + +# ----------------------------------------------------------------------------- +# class Production: +# +# This class stores the raw information about a single production or grammar rule. +# A grammar rule refers to a specification such as this: +# +# expr : expr PLUS term +# +# Here are the basic attributes defined on all productions +# +# name - Name of the production. For example 'expr' +# prod - A list of symbols on the right side ['expr','PLUS','term'] +# prec - Production precedence level +# number - Production number. +# func - Function that executes on reduce +# file - File where production function is defined +# lineno - Line number where production function is defined +# +# The following attributes are defined or optional. +# +# len - Length of the production (number of symbols on right hand side) +# usyms - Set of unique symbols found in the production +# ----------------------------------------------------------------------------- + +class Production(object): + reduced = 0 + def __init__(self, number, name, prod, precedence=('right', 0), func=None, file='', line=0): + self.name = name + self.prod = tuple(prod) + self.number = number + self.func = func + self.callable = None + self.file = file + self.line = line + self.prec = precedence + + # Internal settings used during table construction + + self.len = len(self.prod) # Length of the production + + # Create a list of unique production symbols used in the production + self.usyms = [] + for s in self.prod: + if s not in self.usyms: + self.usyms.append(s) + + # List of all LR items for the production + self.lr_items = [] + self.lr_next = None + + # Create a string representation + if self.prod: + self.str = '%s -> %s' % (self.name, ' '.join(self.prod)) + else: + self.str = '%s -> ' % self.name + + def __str__(self): + return self.str + + def __repr__(self): + return 'Production(' + str(self) + ')' + + def __len__(self): + return len(self.prod) + + def __nonzero__(self): + return 1 + + def __getitem__(self, index): + return self.prod[index] + + # Return the nth lr_item from the production (or None if at the end) + def lr_item(self, n): + if n > len(self.prod): + return None + p = LRItem(self, n) + # Precompute the list of productions immediately following. + try: + p.lr_after = Prodnames[p.prod[n+1]] + except (IndexError, KeyError): + p.lr_after = [] + try: + p.lr_before = p.prod[n-1] + except IndexError: + p.lr_before = None + return p + + # Bind the production function name to a callable + def bind(self, pdict): + if self.func: + self.callable = pdict[self.func] + +# This class serves as a minimal standin for Production objects when +# reading table data from files. It only contains information +# actually used by the LR parsing engine, plus some additional +# debugging information. +class MiniProduction(object): + def __init__(self, str, name, len, func, file, line): + self.name = name + self.len = len + self.func = func + self.callable = None + self.file = file + self.line = line + self.str = str + + def __str__(self): + return self.str + + def __repr__(self): + return 'MiniProduction(%s)' % self.str + + # Bind the production function name to a callable + def bind(self, pdict): + if self.func: + self.callable = pdict[self.func] + + +# ----------------------------------------------------------------------------- +# class LRItem +# +# This class represents a specific stage of parsing a production rule. For +# example: +# +# expr : expr . PLUS term +# +# In the above, the "." represents the current location of the parse. Here +# basic attributes: +# +# name - Name of the production. For example 'expr' +# prod - A list of symbols on the right side ['expr','.', 'PLUS','term'] +# number - Production number. +# +# lr_next Next LR item. Example, if we are ' expr -> expr . PLUS term' +# then lr_next refers to 'expr -> expr PLUS . term' +# lr_index - LR item index (location of the ".") in the prod list. +# lookaheads - LALR lookahead symbols for this item +# len - Length of the production (number of symbols on right hand side) +# lr_after - List of all productions that immediately follow +# lr_before - Grammar symbol immediately before +# ----------------------------------------------------------------------------- + +class LRItem(object): + def __init__(self, p, n): + self.name = p.name + self.prod = list(p.prod) + self.number = p.number + self.lr_index = n + self.lookaheads = {} + self.prod.insert(n, '.') + self.prod = tuple(self.prod) + self.len = len(self.prod) + self.usyms = p.usyms + + def __str__(self): + if self.prod: + s = '%s -> %s' % (self.name, ' '.join(self.prod)) + else: + s = '%s -> ' % self.name + return s + + def __repr__(self): + return 'LRItem(' + str(self) + ')' + +# ----------------------------------------------------------------------------- +# rightmost_terminal() +# +# Return the rightmost terminal from a list of symbols. Used in add_production() +# ----------------------------------------------------------------------------- +def rightmost_terminal(symbols, terminals): + i = len(symbols) - 1 + while i >= 0: + if symbols[i] in terminals: + return symbols[i] + i -= 1 + return None + +# ----------------------------------------------------------------------------- +# === GRAMMAR CLASS === +# +# The following class represents the contents of the specified grammar along +# with various computed properties such as first sets, follow sets, LR items, etc. +# This data is used for critical parts of the table generation process later. +# ----------------------------------------------------------------------------- + +class GrammarError(YaccError): + pass + +class Grammar(object): + def __init__(self, terminals): + self.Productions = [None] # A list of all of the productions. The first + # entry is always reserved for the purpose of + # building an augmented grammar + + self.Prodnames = {} # A dictionary mapping the names of nonterminals to a list of all + # productions of that nonterminal. + + self.Prodmap = {} # A dictionary that is only used to detect duplicate + # productions. + + self.Terminals = {} # A dictionary mapping the names of terminal symbols to a + # list of the rules where they are used. + + for term in terminals: + self.Terminals[term] = [] + + self.Terminals['error'] = [] + + self.Nonterminals = {} # A dictionary mapping names of nonterminals to a list + # of rule numbers where they are used. + + self.First = {} # A dictionary of precomputed FIRST(x) symbols + + self.Follow = {} # A dictionary of precomputed FOLLOW(x) symbols + + self.Precedence = {} # Precedence rules for each terminal. Contains tuples of the + # form ('right',level) or ('nonassoc', level) or ('left',level) + + self.UsedPrecedence = set() # Precedence rules that were actually used by the grammer. + # This is only used to provide error checking and to generate + # a warning about unused precedence rules. + + self.Start = None # Starting symbol for the grammar + + + def __len__(self): + return len(self.Productions) + + def __getitem__(self, index): + return self.Productions[index] + + # ----------------------------------------------------------------------------- + # set_precedence() + # + # Sets the precedence for a given terminal. assoc is the associativity such as + # 'left','right', or 'nonassoc'. level is a numeric level. + # + # ----------------------------------------------------------------------------- + + def set_precedence(self, term, assoc, level): + assert self.Productions == [None], 'Must call set_precedence() before add_production()' + if term in self.Precedence: + raise GrammarError('Precedence already specified for terminal %r' % term) + if assoc not in ['left', 'right', 'nonassoc']: + raise GrammarError("Associativity must be one of 'left','right', or 'nonassoc'") + self.Precedence[term] = (assoc, level) + + # ----------------------------------------------------------------------------- + # add_production() + # + # Given an action function, this function assembles a production rule and + # computes its precedence level. + # + # The production rule is supplied as a list of symbols. For example, + # a rule such as 'expr : expr PLUS term' has a production name of 'expr' and + # symbols ['expr','PLUS','term']. + # + # Precedence is determined by the precedence of the right-most non-terminal + # or the precedence of a terminal specified by %prec. + # + # A variety of error checks are performed to make sure production symbols + # are valid and that %prec is used correctly. + # ----------------------------------------------------------------------------- + + def add_production(self, prodname, syms, func=None, file='', line=0): + + if prodname in self.Terminals: + raise GrammarError('%s:%d: Illegal rule name %r. Already defined as a token' % (file, line, prodname)) + if prodname == 'error': + raise GrammarError('%s:%d: Illegal rule name %r. error is a reserved word' % (file, line, prodname)) + if not _is_identifier.match(prodname): + raise GrammarError('%s:%d: Illegal rule name %r' % (file, line, prodname)) + + # Look for literal tokens + for n, s in enumerate(syms): + if s[0] in "'\"": + try: + c = eval(s) + if (len(c) > 1): + raise GrammarError('%s:%d: Literal token %s in rule %r may only be a single character' % + (file, line, s, prodname)) + if c not in self.Terminals: + self.Terminals[c] = [] + syms[n] = c + continue + except SyntaxError: + pass + if not _is_identifier.match(s) and s != '%prec': + raise GrammarError('%s:%d: Illegal name %r in rule %r' % (file, line, s, prodname)) + + # Determine the precedence level + if '%prec' in syms: + if syms[-1] == '%prec': + raise GrammarError('%s:%d: Syntax error. Nothing follows %%prec' % (file, line)) + if syms[-2] != '%prec': + raise GrammarError('%s:%d: Syntax error. %%prec can only appear at the end of a grammar rule' % + (file, line)) + precname = syms[-1] + prodprec = self.Precedence.get(precname) + if not prodprec: + raise GrammarError('%s:%d: Nothing known about the precedence of %r' % (file, line, precname)) + else: + self.UsedPrecedence.add(precname) + del syms[-2:] # Drop %prec from the rule + else: + # If no %prec, precedence is determined by the rightmost terminal symbol + precname = rightmost_terminal(syms, self.Terminals) + prodprec = self.Precedence.get(precname, ('right', 0)) + + # See if the rule is already in the rulemap + map = '%s -> %s' % (prodname, syms) + if map in self.Prodmap: + m = self.Prodmap[map] + raise GrammarError('%s:%d: Duplicate rule %s. ' % (file, line, m) + + 'Previous definition at %s:%d' % (m.file, m.line)) + + # From this point on, everything is valid. Create a new Production instance + pnumber = len(self.Productions) + if prodname not in self.Nonterminals: + self.Nonterminals[prodname] = [] + + # Add the production number to Terminals and Nonterminals + for t in syms: + if t in self.Terminals: + self.Terminals[t].append(pnumber) + else: + if t not in self.Nonterminals: + self.Nonterminals[t] = [] + self.Nonterminals[t].append(pnumber) + + # Create a production and add it to the list of productions + p = Production(pnumber, prodname, syms, prodprec, func, file, line) + self.Productions.append(p) + self.Prodmap[map] = p + + # Add to the global productions list + try: + self.Prodnames[prodname].append(p) + except KeyError: + self.Prodnames[prodname] = [p] + + # ----------------------------------------------------------------------------- + # set_start() + # + # Sets the starting symbol and creates the augmented grammar. Production + # rule 0 is S' -> start where start is the start symbol. + # ----------------------------------------------------------------------------- + + def set_start(self, start=None): + if not start: + start = self.Productions[1].name + if start not in self.Nonterminals: + raise GrammarError('start symbol %s undefined' % start) + self.Productions[0] = Production(0, "S'", [start]) + self.Nonterminals[start].append(0) + self.Start = start + + # ----------------------------------------------------------------------------- + # find_unreachable() + # + # Find all of the nonterminal symbols that can't be reached from the starting + # symbol. Returns a list of nonterminals that can't be reached. + # ----------------------------------------------------------------------------- + + def find_unreachable(self): + + # Mark all symbols that are reachable from a symbol s + def mark_reachable_from(s): + if s in reachable: + return + reachable.add(s) + for p in self.Prodnames.get(s, []): + for r in p.prod: + mark_reachable_from(r) + + reachable = set() + mark_reachable_from(self.Productions[0].prod[0]) + return [s for s in self.Nonterminals if s not in reachable] + + # ----------------------------------------------------------------------------- + # infinite_cycles() + # + # This function looks at the various parsing rules and tries to detect + # infinite recursion cycles (grammar rules where there is no possible way + # to derive a string of only terminals). + # ----------------------------------------------------------------------------- + + def infinite_cycles(self): + terminates = {} + + # Terminals: + for t in self.Terminals: + terminates[t] = True + + terminates['$end'] = True + + # Nonterminals: + + # Initialize to false: + for n in self.Nonterminals: + terminates[n] = False + + # Then propagate termination until no change: + while True: + some_change = False + for (n, pl) in self.Prodnames.items(): + # Nonterminal n terminates iff any of its productions terminates. + for p in pl: + # Production p terminates iff all of its rhs symbols terminate. + for s in p.prod: + if not terminates[s]: + # The symbol s does not terminate, + # so production p does not terminate. + p_terminates = False + break + else: + # didn't break from the loop, + # so every symbol s terminates + # so production p terminates. + p_terminates = True + + if p_terminates: + # symbol n terminates! + if not terminates[n]: + terminates[n] = True + some_change = True + # Don't need to consider any more productions for this n. + break + + if not some_change: + break + + infinite = [] + for (s, term) in terminates.items(): + if not term: + if s not in self.Prodnames and s not in self.Terminals and s != 'error': + # s is used-but-not-defined, and we've already warned of that, + # so it would be overkill to say that it's also non-terminating. + pass + else: + infinite.append(s) + + return infinite + + # ----------------------------------------------------------------------------- + # undefined_symbols() + # + # Find all symbols that were used the grammar, but not defined as tokens or + # grammar rules. Returns a list of tuples (sym, prod) where sym in the symbol + # and prod is the production where the symbol was used. + # ----------------------------------------------------------------------------- + def undefined_symbols(self): + result = [] + for p in self.Productions: + if not p: + continue + + for s in p.prod: + if s not in self.Prodnames and s not in self.Terminals and s != 'error': + result.append((s, p)) + return result + + # ----------------------------------------------------------------------------- + # unused_terminals() + # + # Find all terminals that were defined, but not used by the grammar. Returns + # a list of all symbols. + # ----------------------------------------------------------------------------- + def unused_terminals(self): + unused_tok = [] + for s, v in self.Terminals.items(): + if s != 'error' and not v: + unused_tok.append(s) + + return unused_tok + + # ------------------------------------------------------------------------------ + # unused_rules() + # + # Find all grammar rules that were defined, but not used (maybe not reachable) + # Returns a list of productions. + # ------------------------------------------------------------------------------ + + def unused_rules(self): + unused_prod = [] + for s, v in self.Nonterminals.items(): + if not v: + p = self.Prodnames[s][0] + unused_prod.append(p) + return unused_prod + + # ----------------------------------------------------------------------------- + # unused_precedence() + # + # Returns a list of tuples (term,precedence) corresponding to precedence + # rules that were never used by the grammar. term is the name of the terminal + # on which precedence was applied and precedence is a string such as 'left' or + # 'right' corresponding to the type of precedence. + # ----------------------------------------------------------------------------- + + def unused_precedence(self): + unused = [] + for termname in self.Precedence: + if not (termname in self.Terminals or termname in self.UsedPrecedence): + unused.append((termname, self.Precedence[termname][0])) + + return unused + + # ------------------------------------------------------------------------- + # _first() + # + # Compute the value of FIRST1(beta) where beta is a tuple of symbols. + # + # During execution of compute_first1, the result may be incomplete. + # Afterward (e.g., when called from compute_follow()), it will be complete. + # ------------------------------------------------------------------------- + def _first(self, beta): + + # We are computing First(x1,x2,x3,...,xn) + result = [] + for x in beta: + x_produces_empty = False + + # Add all the non- symbols of First[x] to the result. + for f in self.First[x]: + if f == '': + x_produces_empty = True + else: + if f not in result: + result.append(f) + + if x_produces_empty: + # We have to consider the next x in beta, + # i.e. stay in the loop. + pass + else: + # We don't have to consider any further symbols in beta. + break + else: + # There was no 'break' from the loop, + # so x_produces_empty was true for all x in beta, + # so beta produces empty as well. + result.append('') + + return result + + # ------------------------------------------------------------------------- + # compute_first() + # + # Compute the value of FIRST1(X) for all symbols + # ------------------------------------------------------------------------- + def compute_first(self): + if self.First: + return self.First + + # Terminals: + for t in self.Terminals: + self.First[t] = [t] + + self.First['$end'] = ['$end'] + + # Nonterminals: + + # Initialize to the empty set: + for n in self.Nonterminals: + self.First[n] = [] + + # Then propagate symbols until no change: + while True: + some_change = False + for n in self.Nonterminals: + for p in self.Prodnames[n]: + for f in self._first(p.prod): + if f not in self.First[n]: + self.First[n].append(f) + some_change = True + if not some_change: + break + + return self.First + + # --------------------------------------------------------------------- + # compute_follow() + # + # Computes all of the follow sets for every non-terminal symbol. The + # follow set is the set of all symbols that might follow a given + # non-terminal. See the Dragon book, 2nd Ed. p. 189. + # --------------------------------------------------------------------- + def compute_follow(self, start=None): + # If already computed, return the result + if self.Follow: + return self.Follow + + # If first sets not computed yet, do that first. + if not self.First: + self.compute_first() + + # Add '$end' to the follow list of the start symbol + for k in self.Nonterminals: + self.Follow[k] = [] + + if not start: + start = self.Productions[1].name + + self.Follow[start] = ['$end'] + + while True: + didadd = False + for p in self.Productions[1:]: + # Here is the production set + for i, B in enumerate(p.prod): + if B in self.Nonterminals: + # Okay. We got a non-terminal in a production + fst = self._first(p.prod[i+1:]) + hasempty = False + for f in fst: + if f != '' and f not in self.Follow[B]: + self.Follow[B].append(f) + didadd = True + if f == '': + hasempty = True + if hasempty or i == (len(p.prod)-1): + # Add elements of follow(a) to follow(b) + for f in self.Follow[p.name]: + if f not in self.Follow[B]: + self.Follow[B].append(f) + didadd = True + if not didadd: + break + return self.Follow + + + # ----------------------------------------------------------------------------- + # build_lritems() + # + # This function walks the list of productions and builds a complete set of the + # LR items. The LR items are stored in two ways: First, they are uniquely + # numbered and placed in the list _lritems. Second, a linked list of LR items + # is built for each production. For example: + # + # E -> E PLUS E + # + # Creates the list + # + # [E -> . E PLUS E, E -> E . PLUS E, E -> E PLUS . E, E -> E PLUS E . ] + # ----------------------------------------------------------------------------- + + def build_lritems(self): + for p in self.Productions: + lastlri = p + i = 0 + lr_items = [] + while True: + if i > len(p): + lri = None + else: + lri = LRItem(p, i) + # Precompute the list of productions immediately following + try: + lri.lr_after = self.Prodnames[lri.prod[i+1]] + except (IndexError, KeyError): + lri.lr_after = [] + try: + lri.lr_before = lri.prod[i-1] + except IndexError: + lri.lr_before = None + + lastlri.lr_next = lri + if not lri: + break + lr_items.append(lri) + lastlri = lri + i += 1 + p.lr_items = lr_items + +# ----------------------------------------------------------------------------- +# == Class LRTable == +# +# This basic class represents a basic table of LR parsing information. +# Methods for generating the tables are not defined here. They are defined +# in the derived class LRGeneratedTable. +# ----------------------------------------------------------------------------- + +class VersionError(YaccError): + pass + +class LRTable(object): + def __init__(self): + self.lr_action = None + self.lr_goto = None + self.lr_productions = None + self.lr_method = None + + def read_table(self, module): + if isinstance(module, types.ModuleType): + parsetab = module + else: + exec('import %s' % module) + parsetab = sys.modules[module] + + if parsetab._tabversion != __tabversion__: + raise VersionError('yacc table file version is out of date') + + self.lr_action = parsetab._lr_action + self.lr_goto = parsetab._lr_goto + + self.lr_productions = [] + for p in parsetab._lr_productions: + self.lr_productions.append(MiniProduction(*p)) + + self.lr_method = parsetab._lr_method + return parsetab._lr_signature + + def read_pickle(self, filename): + try: + import cPickle as pickle + except ImportError: + import pickle + + if not os.path.exists(filename): + raise ImportError + + in_f = open(filename, 'rb') + + tabversion = pickle.load(in_f) + if tabversion != __tabversion__: + raise VersionError('yacc table file version is out of date') + self.lr_method = pickle.load(in_f) + signature = pickle.load(in_f) + self.lr_action = pickle.load(in_f) + self.lr_goto = pickle.load(in_f) + productions = pickle.load(in_f) + + self.lr_productions = [] + for p in productions: + self.lr_productions.append(MiniProduction(*p)) + + in_f.close() + return signature + + # Bind all production function names to callable objects in pdict + def bind_callables(self, pdict): + for p in self.lr_productions: + p.bind(pdict) + + +# ----------------------------------------------------------------------------- +# === LR Generator === +# +# The following classes and functions are used to generate LR parsing tables on +# a grammar. +# ----------------------------------------------------------------------------- + +# ----------------------------------------------------------------------------- +# digraph() +# traverse() +# +# The following two functions are used to compute set valued functions +# of the form: +# +# F(x) = F'(x) U U{F(y) | x R y} +# +# This is used to compute the values of Read() sets as well as FOLLOW sets +# in LALR(1) generation. +# +# Inputs: X - An input set +# R - A relation +# FP - Set-valued function +# ------------------------------------------------------------------------------ + +def digraph(X, R, FP): + N = {} + for x in X: + N[x] = 0 + stack = [] + F = {} + for x in X: + if N[x] == 0: + traverse(x, N, stack, F, X, R, FP) + return F + +def traverse(x, N, stack, F, X, R, FP): + stack.append(x) + d = len(stack) + N[x] = d + F[x] = FP(x) # F(X) <- F'(x) + + rel = R(x) # Get y's related to x + for y in rel: + if N[y] == 0: + traverse(y, N, stack, F, X, R, FP) + N[x] = min(N[x], N[y]) + for a in F.get(y, []): + if a not in F[x]: + F[x].append(a) + if N[x] == d: + N[stack[-1]] = MAXINT + F[stack[-1]] = F[x] + element = stack.pop() + while element != x: + N[stack[-1]] = MAXINT + F[stack[-1]] = F[x] + element = stack.pop() + +class LALRError(YaccError): + pass + +# ----------------------------------------------------------------------------- +# == LRGeneratedTable == +# +# This class implements the LR table generation algorithm. There are no +# public methods except for write() +# ----------------------------------------------------------------------------- + +class LRGeneratedTable(LRTable): + def __init__(self, grammar, method='LALR', log=None): + if method not in ['SLR', 'LALR']: + raise LALRError('Unsupported method %s' % method) + + self.grammar = grammar + self.lr_method = method + + # Set up the logger + if not log: + log = NullLogger() + self.log = log + + # Internal attributes + self.lr_action = {} # Action table + self.lr_goto = {} # Goto table + self.lr_productions = grammar.Productions # Copy of grammar Production array + self.lr_goto_cache = {} # Cache of computed gotos + self.lr0_cidhash = {} # Cache of closures + + self._add_count = 0 # Internal counter used to detect cycles + + # Diagonistic information filled in by the table generator + self.sr_conflict = 0 + self.rr_conflict = 0 + self.conflicts = [] # List of conflicts + + self.sr_conflicts = [] + self.rr_conflicts = [] + + # Build the tables + self.grammar.build_lritems() + self.grammar.compute_first() + self.grammar.compute_follow() + self.lr_parse_table() + + # Compute the LR(0) closure operation on I, where I is a set of LR(0) items. + + def lr0_closure(self, I): + self._add_count += 1 + + # Add everything in I to J + J = I[:] + didadd = True + while didadd: + didadd = False + for j in J: + for x in j.lr_after: + if getattr(x, 'lr0_added', 0) == self._add_count: + continue + # Add B --> .G to J + J.append(x.lr_next) + x.lr0_added = self._add_count + didadd = True + + return J + + # Compute the LR(0) goto function goto(I,X) where I is a set + # of LR(0) items and X is a grammar symbol. This function is written + # in a way that guarantees uniqueness of the generated goto sets + # (i.e. the same goto set will never be returned as two different Python + # objects). With uniqueness, we can later do fast set comparisons using + # id(obj) instead of element-wise comparison. + + def lr0_goto(self, I, x): + # First we look for a previously cached entry + g = self.lr_goto_cache.get((id(I), x)) + if g: + return g + + # Now we generate the goto set in a way that guarantees uniqueness + # of the result + + s = self.lr_goto_cache.get(x) + if not s: + s = {} + self.lr_goto_cache[x] = s + + gs = [] + for p in I: + n = p.lr_next + if n and n.lr_before == x: + s1 = s.get(id(n)) + if not s1: + s1 = {} + s[id(n)] = s1 + gs.append(n) + s = s1 + g = s.get('$end') + if not g: + if gs: + g = self.lr0_closure(gs) + s['$end'] = g + else: + s['$end'] = gs + self.lr_goto_cache[(id(I), x)] = g + return g + + # Compute the LR(0) sets of item function + def lr0_items(self): + C = [self.lr0_closure([self.grammar.Productions[0].lr_next])] + i = 0 + for I in C: + self.lr0_cidhash[id(I)] = i + i += 1 + + # Loop over the items in C and each grammar symbols + i = 0 + while i < len(C): + I = C[i] + i += 1 + + # Collect all of the symbols that could possibly be in the goto(I,X) sets + asyms = {} + for ii in I: + for s in ii.usyms: + asyms[s] = None + + for x in asyms: + g = self.lr0_goto(I, x) + if not g or id(g) in self.lr0_cidhash: + continue + self.lr0_cidhash[id(g)] = len(C) + C.append(g) + + return C + + # ----------------------------------------------------------------------------- + # ==== LALR(1) Parsing ==== + # + # LALR(1) parsing is almost exactly the same as SLR except that instead of + # relying upon Follow() sets when performing reductions, a more selective + # lookahead set that incorporates the state of the LR(0) machine is utilized. + # Thus, we mainly just have to focus on calculating the lookahead sets. + # + # The method used here is due to DeRemer and Pennelo (1982). + # + # DeRemer, F. L., and T. J. Pennelo: "Efficient Computation of LALR(1) + # Lookahead Sets", ACM Transactions on Programming Languages and Systems, + # Vol. 4, No. 4, Oct. 1982, pp. 615-649 + # + # Further details can also be found in: + # + # J. Tremblay and P. Sorenson, "The Theory and Practice of Compiler Writing", + # McGraw-Hill Book Company, (1985). + # + # ----------------------------------------------------------------------------- + + # ----------------------------------------------------------------------------- + # compute_nullable_nonterminals() + # + # Creates a dictionary containing all of the non-terminals that might produce + # an empty production. + # ----------------------------------------------------------------------------- + + def compute_nullable_nonterminals(self): + nullable = set() + num_nullable = 0 + while True: + for p in self.grammar.Productions[1:]: + if p.len == 0: + nullable.add(p.name) + continue + for t in p.prod: + if t not in nullable: + break + else: + nullable.add(p.name) + if len(nullable) == num_nullable: + break + num_nullable = len(nullable) + return nullable + + # ----------------------------------------------------------------------------- + # find_nonterminal_trans(C) + # + # Given a set of LR(0) items, this functions finds all of the non-terminal + # transitions. These are transitions in which a dot appears immediately before + # a non-terminal. Returns a list of tuples of the form (state,N) where state + # is the state number and N is the nonterminal symbol. + # + # The input C is the set of LR(0) items. + # ----------------------------------------------------------------------------- + + def find_nonterminal_transitions(self, C): + trans = [] + for stateno, state in enumerate(C): + for p in state: + if p.lr_index < p.len - 1: + t = (stateno, p.prod[p.lr_index+1]) + if t[1] in self.grammar.Nonterminals: + if t not in trans: + trans.append(t) + return trans + + # ----------------------------------------------------------------------------- + # dr_relation() + # + # Computes the DR(p,A) relationships for non-terminal transitions. The input + # is a tuple (state,N) where state is a number and N is a nonterminal symbol. + # + # Returns a list of terminals. + # ----------------------------------------------------------------------------- + + def dr_relation(self, C, trans, nullable): + dr_set = {} + state, N = trans + terms = [] + + g = self.lr0_goto(C[state], N) + for p in g: + if p.lr_index < p.len - 1: + a = p.prod[p.lr_index+1] + if a in self.grammar.Terminals: + if a not in terms: + terms.append(a) + + # This extra bit is to handle the start state + if state == 0 and N == self.grammar.Productions[0].prod[0]: + terms.append('$end') + + return terms + + # ----------------------------------------------------------------------------- + # reads_relation() + # + # Computes the READS() relation (p,A) READS (t,C). + # ----------------------------------------------------------------------------- + + def reads_relation(self, C, trans, empty): + # Look for empty transitions + rel = [] + state, N = trans + + g = self.lr0_goto(C[state], N) + j = self.lr0_cidhash.get(id(g), -1) + for p in g: + if p.lr_index < p.len - 1: + a = p.prod[p.lr_index + 1] + if a in empty: + rel.append((j, a)) + + return rel + + # ----------------------------------------------------------------------------- + # compute_lookback_includes() + # + # Determines the lookback and includes relations + # + # LOOKBACK: + # + # This relation is determined by running the LR(0) state machine forward. + # For example, starting with a production "N : . A B C", we run it forward + # to obtain "N : A B C ." We then build a relationship between this final + # state and the starting state. These relationships are stored in a dictionary + # lookdict. + # + # INCLUDES: + # + # Computes the INCLUDE() relation (p,A) INCLUDES (p',B). + # + # This relation is used to determine non-terminal transitions that occur + # inside of other non-terminal transition states. (p,A) INCLUDES (p', B) + # if the following holds: + # + # B -> LAT, where T -> epsilon and p' -L-> p + # + # L is essentially a prefix (which may be empty), T is a suffix that must be + # able to derive an empty string. State p' must lead to state p with the string L. + # + # ----------------------------------------------------------------------------- + + def compute_lookback_includes(self, C, trans, nullable): + lookdict = {} # Dictionary of lookback relations + includedict = {} # Dictionary of include relations + + # Make a dictionary of non-terminal transitions + dtrans = {} + for t in trans: + dtrans[t] = 1 + + # Loop over all transitions and compute lookbacks and includes + for state, N in trans: + lookb = [] + includes = [] + for p in C[state]: + if p.name != N: + continue + + # Okay, we have a name match. We now follow the production all the way + # through the state machine until we get the . on the right hand side + + lr_index = p.lr_index + j = state + while lr_index < p.len - 1: + lr_index = lr_index + 1 + t = p.prod[lr_index] + + # Check to see if this symbol and state are a non-terminal transition + if (j, t) in dtrans: + # Yes. Okay, there is some chance that this is an includes relation + # the only way to know for certain is whether the rest of the + # production derives empty + + li = lr_index + 1 + while li < p.len: + if p.prod[li] in self.grammar.Terminals: + break # No forget it + if p.prod[li] not in nullable: + break + li = li + 1 + else: + # Appears to be a relation between (j,t) and (state,N) + includes.append((j, t)) + + g = self.lr0_goto(C[j], t) # Go to next set + j = self.lr0_cidhash.get(id(g), -1) # Go to next state + + # When we get here, j is the final state, now we have to locate the production + for r in C[j]: + if r.name != p.name: + continue + if r.len != p.len: + continue + i = 0 + # This look is comparing a production ". A B C" with "A B C ." + while i < r.lr_index: + if r.prod[i] != p.prod[i+1]: + break + i = i + 1 + else: + lookb.append((j, r)) + for i in includes: + if i not in includedict: + includedict[i] = [] + includedict[i].append((state, N)) + lookdict[(state, N)] = lookb + + return lookdict, includedict + + # ----------------------------------------------------------------------------- + # compute_read_sets() + # + # Given a set of LR(0) items, this function computes the read sets. + # + # Inputs: C = Set of LR(0) items + # ntrans = Set of nonterminal transitions + # nullable = Set of empty transitions + # + # Returns a set containing the read sets + # ----------------------------------------------------------------------------- + + def compute_read_sets(self, C, ntrans, nullable): + FP = lambda x: self.dr_relation(C, x, nullable) + R = lambda x: self.reads_relation(C, x, nullable) + F = digraph(ntrans, R, FP) + return F + + # ----------------------------------------------------------------------------- + # compute_follow_sets() + # + # Given a set of LR(0) items, a set of non-terminal transitions, a readset, + # and an include set, this function computes the follow sets + # + # Follow(p,A) = Read(p,A) U U {Follow(p',B) | (p,A) INCLUDES (p',B)} + # + # Inputs: + # ntrans = Set of nonterminal transitions + # readsets = Readset (previously computed) + # inclsets = Include sets (previously computed) + # + # Returns a set containing the follow sets + # ----------------------------------------------------------------------------- + + def compute_follow_sets(self, ntrans, readsets, inclsets): + FP = lambda x: readsets[x] + R = lambda x: inclsets.get(x, []) + F = digraph(ntrans, R, FP) + return F + + # ----------------------------------------------------------------------------- + # add_lookaheads() + # + # Attaches the lookahead symbols to grammar rules. + # + # Inputs: lookbacks - Set of lookback relations + # followset - Computed follow set + # + # This function directly attaches the lookaheads to productions contained + # in the lookbacks set + # ----------------------------------------------------------------------------- + + def add_lookaheads(self, lookbacks, followset): + for trans, lb in lookbacks.items(): + # Loop over productions in lookback + for state, p in lb: + if state not in p.lookaheads: + p.lookaheads[state] = [] + f = followset.get(trans, []) + for a in f: + if a not in p.lookaheads[state]: + p.lookaheads[state].append(a) + + # ----------------------------------------------------------------------------- + # add_lalr_lookaheads() + # + # This function does all of the work of adding lookahead information for use + # with LALR parsing + # ----------------------------------------------------------------------------- + + def add_lalr_lookaheads(self, C): + # Determine all of the nullable nonterminals + nullable = self.compute_nullable_nonterminals() + + # Find all non-terminal transitions + trans = self.find_nonterminal_transitions(C) + + # Compute read sets + readsets = self.compute_read_sets(C, trans, nullable) + + # Compute lookback/includes relations + lookd, included = self.compute_lookback_includes(C, trans, nullable) + + # Compute LALR FOLLOW sets + followsets = self.compute_follow_sets(trans, readsets, included) + + # Add all of the lookaheads + self.add_lookaheads(lookd, followsets) + + # ----------------------------------------------------------------------------- + # lr_parse_table() + # + # This function constructs the parse tables for SLR or LALR + # ----------------------------------------------------------------------------- + def lr_parse_table(self): + Productions = self.grammar.Productions + Precedence = self.grammar.Precedence + goto = self.lr_goto # Goto array + action = self.lr_action # Action array + log = self.log # Logger for output + + actionp = {} # Action production array (temporary) + + log.info('Parsing method: %s', self.lr_method) + + # Step 1: Construct C = { I0, I1, ... IN}, collection of LR(0) items + # This determines the number of states + + C = self.lr0_items() + + if self.lr_method == 'LALR': + self.add_lalr_lookaheads(C) + + # Build the parser table, state by state + st = 0 + for I in C: + # Loop over each production in I + actlist = [] # List of actions + st_action = {} + st_actionp = {} + st_goto = {} + log.info('') + log.info('state %d', st) + log.info('') + for p in I: + log.info(' (%d) %s', p.number, p) + log.info('') + + for p in I: + if p.len == p.lr_index + 1: + if p.name == "S'": + # Start symbol. Accept! + st_action['$end'] = 0 + st_actionp['$end'] = p + else: + # We are at the end of a production. Reduce! + if self.lr_method == 'LALR': + laheads = p.lookaheads[st] + else: + laheads = self.grammar.Follow[p.name] + for a in laheads: + actlist.append((a, p, 'reduce using rule %d (%s)' % (p.number, p))) + r = st_action.get(a) + if r is not None: + # Whoa. Have a shift/reduce or reduce/reduce conflict + if r > 0: + # Need to decide on shift or reduce here + # By default we favor shifting. Need to add + # some precedence rules here. + + # Shift precedence comes from the token + sprec, slevel = Precedence.get(a, ('right', 0)) + + # Reduce precedence comes from rule being reduced (p) + rprec, rlevel = Productions[p.number].prec + + if (slevel < rlevel) or ((slevel == rlevel) and (rprec == 'left')): + # We really need to reduce here. + st_action[a] = -p.number + st_actionp[a] = p + if not slevel and not rlevel: + log.info(' ! shift/reduce conflict for %s resolved as reduce', a) + self.sr_conflicts.append((st, a, 'reduce')) + Productions[p.number].reduced += 1 + elif (slevel == rlevel) and (rprec == 'nonassoc'): + st_action[a] = None + else: + # Hmmm. Guess we'll keep the shift + if not rlevel: + log.info(' ! shift/reduce conflict for %s resolved as shift', a) + self.sr_conflicts.append((st, a, 'shift')) + elif r < 0: + # Reduce/reduce conflict. In this case, we favor the rule + # that was defined first in the grammar file + oldp = Productions[-r] + pp = Productions[p.number] + if oldp.line > pp.line: + st_action[a] = -p.number + st_actionp[a] = p + chosenp, rejectp = pp, oldp + Productions[p.number].reduced += 1 + Productions[oldp.number].reduced -= 1 + else: + chosenp, rejectp = oldp, pp + self.rr_conflicts.append((st, chosenp, rejectp)) + log.info(' ! reduce/reduce conflict for %s resolved using rule %d (%s)', + a, st_actionp[a].number, st_actionp[a]) + else: + raise LALRError('Unknown conflict in state %d' % st) + else: + st_action[a] = -p.number + st_actionp[a] = p + Productions[p.number].reduced += 1 + else: + i = p.lr_index + a = p.prod[i+1] # Get symbol right after the "." + if a in self.grammar.Terminals: + g = self.lr0_goto(I, a) + j = self.lr0_cidhash.get(id(g), -1) + if j >= 0: + # We are in a shift state + actlist.append((a, p, 'shift and go to state %d' % j)) + r = st_action.get(a) + if r is not None: + # Whoa have a shift/reduce or shift/shift conflict + if r > 0: + if r != j: + raise LALRError('Shift/shift conflict in state %d' % st) + elif r < 0: + # Do a precedence check. + # - if precedence of reduce rule is higher, we reduce. + # - if precedence of reduce is same and left assoc, we reduce. + # - otherwise we shift + + # Shift precedence comes from the token + sprec, slevel = Precedence.get(a, ('right', 0)) + + # Reduce precedence comes from the rule that could have been reduced + rprec, rlevel = Productions[st_actionp[a].number].prec + + if (slevel > rlevel) or ((slevel == rlevel) and (rprec == 'right')): + # We decide to shift here... highest precedence to shift + Productions[st_actionp[a].number].reduced -= 1 + st_action[a] = j + st_actionp[a] = p + if not rlevel: + log.info(' ! shift/reduce conflict for %s resolved as shift', a) + self.sr_conflicts.append((st, a, 'shift')) + elif (slevel == rlevel) and (rprec == 'nonassoc'): + st_action[a] = None + else: + # Hmmm. Guess we'll keep the reduce + if not slevel and not rlevel: + log.info(' ! shift/reduce conflict for %s resolved as reduce', a) + self.sr_conflicts.append((st, a, 'reduce')) + + else: + raise LALRError('Unknown conflict in state %d' % st) + else: + st_action[a] = j + st_actionp[a] = p + + # Print the actions associated with each terminal + _actprint = {} + for a, p, m in actlist: + if a in st_action: + if p is st_actionp[a]: + log.info(' %-15s %s', a, m) + _actprint[(a, m)] = 1 + log.info('') + # Print the actions that were not used. (debugging) + not_used = 0 + for a, p, m in actlist: + if a in st_action: + if p is not st_actionp[a]: + if not (a, m) in _actprint: + log.debug(' ! %-15s [ %s ]', a, m) + not_used = 1 + _actprint[(a, m)] = 1 + if not_used: + log.debug('') + + # Construct the goto table for this state + + nkeys = {} + for ii in I: + for s in ii.usyms: + if s in self.grammar.Nonterminals: + nkeys[s] = None + for n in nkeys: + g = self.lr0_goto(I, n) + j = self.lr0_cidhash.get(id(g), -1) + if j >= 0: + st_goto[n] = j + log.info(' %-30s shift and go to state %d', n, j) + + action[st] = st_action + actionp[st] = st_actionp + goto[st] = st_goto + st += 1 + + # ----------------------------------------------------------------------------- + # write() + # + # This function writes the LR parsing tables to a file + # ----------------------------------------------------------------------------- + + def write_table(self, tabmodule, outputdir='', signature=''): + if isinstance(tabmodule, types.ModuleType): + raise IOError("Won't overwrite existing tabmodule") + + basemodulename = tabmodule.split('.')[-1] + filename = os.path.join(outputdir, basemodulename) + '.py' + try: + f = open(filename, 'w') + + f.write(''' +# %s +# This file is automatically generated. Do not edit. +_tabversion = %r + +_lr_method = %r + +_lr_signature = %r + ''' % (os.path.basename(filename), __tabversion__, self.lr_method, signature)) + + # Change smaller to 0 to go back to original tables + smaller = 1 + + # Factor out names to try and make smaller + if smaller: + items = {} + + for s, nd in self.lr_action.items(): + for name, v in nd.items(): + i = items.get(name) + if not i: + i = ([], []) + items[name] = i + i[0].append(s) + i[1].append(v) + + f.write('\n_lr_action_items = {') + for k, v in items.items(): + f.write('%r:([' % k) + for i in v[0]: + f.write('%r,' % i) + f.write('],[') + for i in v[1]: + f.write('%r,' % i) + + f.write(']),') + f.write('}\n') + + f.write(''' +_lr_action = {} +for _k, _v in _lr_action_items.items(): + for _x,_y in zip(_v[0],_v[1]): + if not _x in _lr_action: _lr_action[_x] = {} + _lr_action[_x][_k] = _y +del _lr_action_items +''') + + else: + f.write('\n_lr_action = { ') + for k, v in self.lr_action.items(): + f.write('(%r,%r):%r,' % (k[0], k[1], v)) + f.write('}\n') + + if smaller: + # Factor out names to try and make smaller + items = {} + + for s, nd in self.lr_goto.items(): + for name, v in nd.items(): + i = items.get(name) + if not i: + i = ([], []) + items[name] = i + i[0].append(s) + i[1].append(v) + + f.write('\n_lr_goto_items = {') + for k, v in items.items(): + f.write('%r:([' % k) + for i in v[0]: + f.write('%r,' % i) + f.write('],[') + for i in v[1]: + f.write('%r,' % i) + + f.write(']),') + f.write('}\n') + + f.write(''' +_lr_goto = {} +for _k, _v in _lr_goto_items.items(): + for _x, _y in zip(_v[0], _v[1]): + if not _x in _lr_goto: _lr_goto[_x] = {} + _lr_goto[_x][_k] = _y +del _lr_goto_items +''') + else: + f.write('\n_lr_goto = { ') + for k, v in self.lr_goto.items(): + f.write('(%r,%r):%r,' % (k[0], k[1], v)) + f.write('}\n') + + # Write production table + f.write('_lr_productions = [\n') + for p in self.lr_productions: + if p.func: + f.write(' (%r,%r,%d,%r,%r,%d),\n' % (p.str, p.name, p.len, + p.func, os.path.basename(p.file), p.line)) + else: + f.write(' (%r,%r,%d,None,None,None),\n' % (str(p), p.name, p.len)) + f.write(']\n') + f.close() + + except IOError as e: + raise + + + # ----------------------------------------------------------------------------- + # pickle_table() + # + # This function pickles the LR parsing tables to a supplied file object + # ----------------------------------------------------------------------------- + + def pickle_table(self, filename, signature=''): + try: + import cPickle as pickle + except ImportError: + import pickle + with open(filename, 'wb') as outf: + pickle.dump(__tabversion__, outf, pickle_protocol) + pickle.dump(self.lr_method, outf, pickle_protocol) + pickle.dump(signature, outf, pickle_protocol) + pickle.dump(self.lr_action, outf, pickle_protocol) + pickle.dump(self.lr_goto, outf, pickle_protocol) + + outp = [] + for p in self.lr_productions: + if p.func: + outp.append((p.str, p.name, p.len, p.func, os.path.basename(p.file), p.line)) + else: + outp.append((str(p), p.name, p.len, None, None, None)) + pickle.dump(outp, outf, pickle_protocol) + +# ----------------------------------------------------------------------------- +# === INTROSPECTION === +# +# The following functions and classes are used to implement the PLY +# introspection features followed by the yacc() function itself. +# ----------------------------------------------------------------------------- + +# ----------------------------------------------------------------------------- +# get_caller_module_dict() +# +# This function returns a dictionary containing all of the symbols defined within +# a caller further down the call stack. This is used to get the environment +# associated with the yacc() call if none was provided. +# ----------------------------------------------------------------------------- + +def get_caller_module_dict(levels): + f = sys._getframe(levels) + ldict = f.f_globals.copy() + if f.f_globals != f.f_locals: + ldict.update(f.f_locals) + return ldict + +# ----------------------------------------------------------------------------- +# parse_grammar() +# +# This takes a raw grammar rule string and parses it into production data +# ----------------------------------------------------------------------------- +def parse_grammar(doc, file, line): + grammar = [] + # Split the doc string into lines + pstrings = doc.splitlines() + lastp = None + dline = line + for ps in pstrings: + dline += 1 + p = ps.split() + if not p: + continue + try: + if p[0] == '|': + # This is a continuation of a previous rule + if not lastp: + raise SyntaxError("%s:%d: Misplaced '|'" % (file, dline)) + prodname = lastp + syms = p[1:] + else: + prodname = p[0] + lastp = prodname + syms = p[2:] + assign = p[1] + if assign != ':' and assign != '::=': + raise SyntaxError("%s:%d: Syntax error. Expected ':'" % (file, dline)) + + grammar.append((file, dline, prodname, syms)) + except SyntaxError: + raise + except Exception: + raise SyntaxError('%s:%d: Syntax error in rule %r' % (file, dline, ps.strip())) + + return grammar + +# ----------------------------------------------------------------------------- +# ParserReflect() +# +# This class represents information extracted for building a parser including +# start symbol, error function, tokens, precedence list, action functions, +# etc. +# ----------------------------------------------------------------------------- +class ParserReflect(object): + def __init__(self, pdict, log=None): + self.pdict = pdict + self.start = None + self.error_func = None + self.tokens = None + self.modules = set() + self.grammar = [] + self.error = False + + if log is None: + self.log = PlyLogger(sys.stderr) + else: + self.log = log + + # Get all of the basic information + def get_all(self): + self.get_start() + self.get_error_func() + self.get_tokens() + self.get_precedence() + self.get_pfunctions() + + # Validate all of the information + def validate_all(self): + self.validate_start() + self.validate_error_func() + self.validate_tokens() + self.validate_precedence() + self.validate_pfunctions() + self.validate_modules() + return self.error + + # Compute a signature over the grammar + def signature(self): + parts = [] + try: + if self.start: + parts.append(self.start) + if self.prec: + parts.append(''.join([''.join(p) for p in self.prec])) + if self.tokens: + parts.append(' '.join(self.tokens)) + for f in self.pfuncs: + if f[3]: + parts.append(f[3]) + except (TypeError, ValueError): + pass + return ''.join(parts) + + # ----------------------------------------------------------------------------- + # validate_modules() + # + # This method checks to see if there are duplicated p_rulename() functions + # in the parser module file. Without this function, it is really easy for + # users to make mistakes by cutting and pasting code fragments (and it's a real + # bugger to try and figure out why the resulting parser doesn't work). Therefore, + # we just do a little regular expression pattern matching of def statements + # to try and detect duplicates. + # ----------------------------------------------------------------------------- + + def validate_modules(self): + # Match def p_funcname( + fre = re.compile(r'\s*def\s+(p_[a-zA-Z_0-9]*)\(') + + for module in self.modules: + try: + lines, linen = inspect.getsourcelines(module) + except IOError: + continue + + counthash = {} + for linen, line in enumerate(lines): + linen += 1 + m = fre.match(line) + if m: + name = m.group(1) + prev = counthash.get(name) + if not prev: + counthash[name] = linen + else: + filename = inspect.getsourcefile(module) + self.log.warning('%s:%d: Function %s redefined. Previously defined on line %d', + filename, linen, name, prev) + + # Get the start symbol + def get_start(self): + self.start = self.pdict.get('start') + + # Validate the start symbol + def validate_start(self): + if self.start is not None: + if not isinstance(self.start, string_types): + self.log.error("'start' must be a string") + + # Look for error handler + def get_error_func(self): + self.error_func = self.pdict.get('p_error') + + # Validate the error function + def validate_error_func(self): + if self.error_func: + if isinstance(self.error_func, types.FunctionType): + ismethod = 0 + elif isinstance(self.error_func, types.MethodType): + ismethod = 1 + else: + self.log.error("'p_error' defined, but is not a function or method") + self.error = True + return + + eline = self.error_func.__code__.co_firstlineno + efile = self.error_func.__code__.co_filename + module = inspect.getmodule(self.error_func) + self.modules.add(module) + + argcount = self.error_func.__code__.co_argcount - ismethod + if argcount != 1: + self.log.error('%s:%d: p_error() requires 1 argument', efile, eline) + self.error = True + + # Get the tokens map + def get_tokens(self): + tokens = self.pdict.get('tokens') + if not tokens: + self.log.error('No token list is defined') + self.error = True + return + + if not isinstance(tokens, (list, tuple)): + self.log.error('tokens must be a list or tuple') + self.error = True + return + + if not tokens: + self.log.error('tokens is empty') + self.error = True + return + + self.tokens = tokens + + # Validate the tokens + def validate_tokens(self): + # Validate the tokens. + if 'error' in self.tokens: + self.log.error("Illegal token name 'error'. Is a reserved word") + self.error = True + return + + terminals = set() + for n in self.tokens: + if n in terminals: + self.log.warning('Token %r multiply defined', n) + terminals.add(n) + + # Get the precedence map (if any) + def get_precedence(self): + self.prec = self.pdict.get('precedence') + + # Validate and parse the precedence map + def validate_precedence(self): + preclist = [] + if self.prec: + if not isinstance(self.prec, (list, tuple)): + self.log.error('precedence must be a list or tuple') + self.error = True + return + for level, p in enumerate(self.prec): + if not isinstance(p, (list, tuple)): + self.log.error('Bad precedence table') + self.error = True + return + + if len(p) < 2: + self.log.error('Malformed precedence entry %s. Must be (assoc, term, ..., term)', p) + self.error = True + return + assoc = p[0] + if not isinstance(assoc, string_types): + self.log.error('precedence associativity must be a string') + self.error = True + return + for term in p[1:]: + if not isinstance(term, string_types): + self.log.error('precedence items must be strings') + self.error = True + return + preclist.append((term, assoc, level+1)) + self.preclist = preclist + + # Get all p_functions from the grammar + def get_pfunctions(self): + p_functions = [] + for name, item in self.pdict.items(): + if not name.startswith('p_') or name == 'p_error': + continue + if isinstance(item, (types.FunctionType, types.MethodType)): + line = getattr(item, 'co_firstlineno', item.__code__.co_firstlineno) + module = inspect.getmodule(item) + p_functions.append((line, module, name, item.__doc__)) + + # Sort all of the actions by line number; make sure to stringify + # modules to make them sortable, since `line` may not uniquely sort all + # p functions + p_functions.sort(key=lambda p_function: ( + p_function[0], + str(p_function[1]), + p_function[2], + p_function[3])) + self.pfuncs = p_functions + + # Validate all of the p_functions + def validate_pfunctions(self): + grammar = [] + # Check for non-empty symbols + if len(self.pfuncs) == 0: + self.log.error('no rules of the form p_rulename are defined') + self.error = True + return + + for line, module, name, doc in self.pfuncs: + file = inspect.getsourcefile(module) + func = self.pdict[name] + if isinstance(func, types.MethodType): + reqargs = 2 + else: + reqargs = 1 + if func.__code__.co_argcount > reqargs: + self.log.error('%s:%d: Rule %r has too many arguments', file, line, func.__name__) + self.error = True + elif func.__code__.co_argcount < reqargs: + self.log.error('%s:%d: Rule %r requires an argument', file, line, func.__name__) + self.error = True + elif not func.__doc__: + self.log.warning('%s:%d: No documentation string specified in function %r (ignored)', + file, line, func.__name__) + else: + try: + parsed_g = parse_grammar(doc, file, line) + for g in parsed_g: + grammar.append((name, g)) + except SyntaxError as e: + self.log.error(str(e)) + self.error = True + + # Looks like a valid grammar rule + # Mark the file in which defined. + self.modules.add(module) + + # Secondary validation step that looks for p_ definitions that are not functions + # or functions that look like they might be grammar rules. + + for n, v in self.pdict.items(): + if n.startswith('p_') and isinstance(v, (types.FunctionType, types.MethodType)): + continue + if n.startswith('t_'): + continue + if n.startswith('p_') and n != 'p_error': + self.log.warning('%r not defined as a function', n) + if ((isinstance(v, types.FunctionType) and v.__code__.co_argcount == 1) or + (isinstance(v, types.MethodType) and v.__func__.__code__.co_argcount == 2)): + if v.__doc__: + try: + doc = v.__doc__.split(' ') + if doc[1] == ':': + self.log.warning('%s:%d: Possible grammar rule %r defined without p_ prefix', + v.__code__.co_filename, v.__code__.co_firstlineno, n) + except IndexError: + pass + + self.grammar = grammar + +# ----------------------------------------------------------------------------- +# yacc(module) +# +# Build a parser +# ----------------------------------------------------------------------------- + +def yacc(method='LALR', debug=yaccdebug, module=None, tabmodule=tab_module, start=None, + check_recursion=True, optimize=False, write_tables=True, debugfile=debug_file, + outputdir=None, debuglog=None, errorlog=None, picklefile=None): + + if tabmodule is None: + tabmodule = tab_module + + # Reference to the parsing method of the last built parser + global parse + + # If pickling is enabled, table files are not created + if picklefile: + write_tables = 0 + + if errorlog is None: + errorlog = PlyLogger(sys.stderr) + + # Get the module dictionary used for the parser + if module: + _items = [(k, getattr(module, k)) for k in dir(module)] + pdict = dict(_items) + # If no __file__ attribute is available, try to obtain it from the __module__ instead + if '__file__' not in pdict: + pdict['__file__'] = sys.modules[pdict['__module__']].__file__ + else: + pdict = get_caller_module_dict(2) + + if outputdir is None: + # If no output directory is set, the location of the output files + # is determined according to the following rules: + # - If tabmodule specifies a package, files go into that package directory + # - Otherwise, files go in the same directory as the specifying module + if isinstance(tabmodule, types.ModuleType): + srcfile = tabmodule.__file__ + else: + if '.' not in tabmodule: + srcfile = pdict['__file__'] + else: + parts = tabmodule.split('.') + pkgname = '.'.join(parts[:-1]) + exec('import %s' % pkgname) + srcfile = getattr(sys.modules[pkgname], '__file__', '') + outputdir = os.path.dirname(srcfile) + + # Determine if the module is package of a package or not. + # If so, fix the tabmodule setting so that tables load correctly + pkg = pdict.get('__package__') + if pkg and isinstance(tabmodule, str): + if '.' not in tabmodule: + tabmodule = pkg + '.' + tabmodule + + + + # Set start symbol if it's specified directly using an argument + if start is not None: + pdict['start'] = start + + # Collect parser information from the dictionary + pinfo = ParserReflect(pdict, log=errorlog) + pinfo.get_all() + + if pinfo.error: + raise YaccError('Unable to build parser') + + # Check signature against table files (if any) + signature = pinfo.signature() + + # Read the tables + try: + lr = LRTable() + if picklefile: + read_signature = lr.read_pickle(picklefile) + else: + read_signature = lr.read_table(tabmodule) + if optimize or (read_signature == signature): + try: + lr.bind_callables(pinfo.pdict) + parser = LRParser(lr, pinfo.error_func) + parse = parser.parse + return parser + except Exception as e: + errorlog.warning('There was a problem loading the table file: %r', e) + except VersionError as e: + errorlog.warning(str(e)) + except ImportError: + pass + + if debuglog is None: + if debug: + try: + debuglog = PlyLogger(open(os.path.join(outputdir, debugfile), 'w')) + except IOError as e: + errorlog.warning("Couldn't open %r. %s" % (debugfile, e)) + debuglog = NullLogger() + else: + debuglog = NullLogger() + + debuglog.info('Created by PLY version %s (http://www.dabeaz.com/ply)', __version__) + + errors = False + + # Validate the parser information + if pinfo.validate_all(): + raise YaccError('Unable to build parser') + + if not pinfo.error_func: + errorlog.warning('no p_error() function is defined') + + # Create a grammar object + grammar = Grammar(pinfo.tokens) + + # Set precedence level for terminals + for term, assoc, level in pinfo.preclist: + try: + grammar.set_precedence(term, assoc, level) + except GrammarError as e: + errorlog.warning('%s', e) + + # Add productions to the grammar + for funcname, gram in pinfo.grammar: + file, line, prodname, syms = gram + try: + grammar.add_production(prodname, syms, funcname, file, line) + except GrammarError as e: + errorlog.error('%s', e) + errors = True + + # Set the grammar start symbols + try: + if start is None: + grammar.set_start(pinfo.start) + else: + grammar.set_start(start) + except GrammarError as e: + errorlog.error(str(e)) + errors = True + + if errors: + raise YaccError('Unable to build parser') + + # Verify the grammar structure + undefined_symbols = grammar.undefined_symbols() + for sym, prod in undefined_symbols: + errorlog.error('%s:%d: Symbol %r used, but not defined as a token or a rule', prod.file, prod.line, sym) + errors = True + + unused_terminals = grammar.unused_terminals() + if unused_terminals: + debuglog.info('') + debuglog.info('Unused terminals:') + debuglog.info('') + for term in unused_terminals: + errorlog.warning('Token %r defined, but not used', term) + debuglog.info(' %s', term) + + # Print out all productions to the debug log + if debug: + debuglog.info('') + debuglog.info('Grammar') + debuglog.info('') + for n, p in enumerate(grammar.Productions): + debuglog.info('Rule %-5d %s', n, p) + + # Find unused non-terminals + unused_rules = grammar.unused_rules() + for prod in unused_rules: + errorlog.warning('%s:%d: Rule %r defined, but not used', prod.file, prod.line, prod.name) + + if len(unused_terminals) == 1: + errorlog.warning('There is 1 unused token') + if len(unused_terminals) > 1: + errorlog.warning('There are %d unused tokens', len(unused_terminals)) + + if len(unused_rules) == 1: + errorlog.warning('There is 1 unused rule') + if len(unused_rules) > 1: + errorlog.warning('There are %d unused rules', len(unused_rules)) + + if debug: + debuglog.info('') + debuglog.info('Terminals, with rules where they appear') + debuglog.info('') + terms = list(grammar.Terminals) + terms.sort() + for term in terms: + debuglog.info('%-20s : %s', term, ' '.join([str(s) for s in grammar.Terminals[term]])) + + debuglog.info('') + debuglog.info('Nonterminals, with rules where they appear') + debuglog.info('') + nonterms = list(grammar.Nonterminals) + nonterms.sort() + for nonterm in nonterms: + debuglog.info('%-20s : %s', nonterm, ' '.join([str(s) for s in grammar.Nonterminals[nonterm]])) + debuglog.info('') + + if check_recursion: + unreachable = grammar.find_unreachable() + for u in unreachable: + errorlog.warning('Symbol %r is unreachable', u) + + infinite = grammar.infinite_cycles() + for inf in infinite: + errorlog.error('Infinite recursion detected for symbol %r', inf) + errors = True + + unused_prec = grammar.unused_precedence() + for term, assoc in unused_prec: + errorlog.error('Precedence rule %r defined for unknown symbol %r', assoc, term) + errors = True + + if errors: + raise YaccError('Unable to build parser') + + # Run the LRGeneratedTable on the grammar + if debug: + errorlog.debug('Generating %s tables', method) + + lr = LRGeneratedTable(grammar, method, debuglog) + + if debug: + num_sr = len(lr.sr_conflicts) + + # Report shift/reduce and reduce/reduce conflicts + if num_sr == 1: + errorlog.warning('1 shift/reduce conflict') + elif num_sr > 1: + errorlog.warning('%d shift/reduce conflicts', num_sr) + + num_rr = len(lr.rr_conflicts) + if num_rr == 1: + errorlog.warning('1 reduce/reduce conflict') + elif num_rr > 1: + errorlog.warning('%d reduce/reduce conflicts', num_rr) + + # Write out conflicts to the output file + if debug and (lr.sr_conflicts or lr.rr_conflicts): + debuglog.warning('') + debuglog.warning('Conflicts:') + debuglog.warning('') + + for state, tok, resolution in lr.sr_conflicts: + debuglog.warning('shift/reduce conflict for %s in state %d resolved as %s', tok, state, resolution) + + already_reported = set() + for state, rule, rejected in lr.rr_conflicts: + if (state, id(rule), id(rejected)) in already_reported: + continue + debuglog.warning('reduce/reduce conflict in state %d resolved using rule (%s)', state, rule) + debuglog.warning('rejected rule (%s) in state %d', rejected, state) + errorlog.warning('reduce/reduce conflict in state %d resolved using rule (%s)', state, rule) + errorlog.warning('rejected rule (%s) in state %d', rejected, state) + already_reported.add((state, id(rule), id(rejected))) + + warned_never = [] + for state, rule, rejected in lr.rr_conflicts: + if not rejected.reduced and (rejected not in warned_never): + debuglog.warning('Rule (%s) is never reduced', rejected) + errorlog.warning('Rule (%s) is never reduced', rejected) + warned_never.append(rejected) + + # Write the table file if requested + if write_tables: + try: + lr.write_table(tabmodule, outputdir, signature) + except IOError as e: + errorlog.warning("Couldn't create %r. %s" % (tabmodule, e)) + + # Write a pickled version of the tables + if picklefile: + try: + lr.pickle_table(picklefile, signature) + except IOError as e: + errorlog.warning("Couldn't create %r. %s" % (picklefile, e)) + + # Build the parser + lr.bind_callables(pinfo.pdict) + parser = LRParser(lr, pinfo.error_func) + + parse = parser.parse + return parser diff --git a/.venv/Lib/site-packages/pycparser/ply/ygen.py b/.venv/Lib/site-packages/pycparser/ply/ygen.py new file mode 100644 index 00000000..acf5ca1a --- /dev/null +++ b/.venv/Lib/site-packages/pycparser/ply/ygen.py @@ -0,0 +1,74 @@ +# ply: ygen.py +# +# This is a support program that auto-generates different versions of the YACC parsing +# function with different features removed for the purposes of performance. +# +# Users should edit the method LParser.parsedebug() in yacc.py. The source code +# for that method is then used to create the other methods. See the comments in +# yacc.py for further details. + +import os.path +import shutil + +def get_source_range(lines, tag): + srclines = enumerate(lines) + start_tag = '#--! %s-start' % tag + end_tag = '#--! %s-end' % tag + + for start_index, line in srclines: + if line.strip().startswith(start_tag): + break + + for end_index, line in srclines: + if line.strip().endswith(end_tag): + break + + return (start_index + 1, end_index) + +def filter_section(lines, tag): + filtered_lines = [] + include = True + tag_text = '#--! %s' % tag + for line in lines: + if line.strip().startswith(tag_text): + include = not include + elif include: + filtered_lines.append(line) + return filtered_lines + +def main(): + dirname = os.path.dirname(__file__) + shutil.copy2(os.path.join(dirname, 'yacc.py'), os.path.join(dirname, 'yacc.py.bak')) + with open(os.path.join(dirname, 'yacc.py'), 'r') as f: + lines = f.readlines() + + parse_start, parse_end = get_source_range(lines, 'parsedebug') + parseopt_start, parseopt_end = get_source_range(lines, 'parseopt') + parseopt_notrack_start, parseopt_notrack_end = get_source_range(lines, 'parseopt-notrack') + + # Get the original source + orig_lines = lines[parse_start:parse_end] + + # Filter the DEBUG sections out + parseopt_lines = filter_section(orig_lines, 'DEBUG') + + # Filter the TRACKING sections out + parseopt_notrack_lines = filter_section(parseopt_lines, 'TRACKING') + + # Replace the parser source sections with updated versions + lines[parseopt_notrack_start:parseopt_notrack_end] = parseopt_notrack_lines + lines[parseopt_start:parseopt_end] = parseopt_lines + + lines = [line.rstrip()+'\n' for line in lines] + with open(os.path.join(dirname, 'yacc.py'), 'w') as f: + f.writelines(lines) + + print('Updated yacc.py') + +if __name__ == '__main__': + main() + + + + + diff --git a/.venv/Lib/site-packages/pycparser/plyparser.py b/.venv/Lib/site-packages/pycparser/plyparser.py new file mode 100644 index 00000000..b8f4c439 --- /dev/null +++ b/.venv/Lib/site-packages/pycparser/plyparser.py @@ -0,0 +1,133 @@ +#----------------------------------------------------------------- +# plyparser.py +# +# PLYParser class and other utilities for simplifying programming +# parsers with PLY +# +# Eli Bendersky [https://eli.thegreenplace.net/] +# License: BSD +#----------------------------------------------------------------- + +import warnings + +class Coord(object): + """ Coordinates of a syntactic element. Consists of: + - File name + - Line number + - (optional) column number, for the Lexer + """ + __slots__ = ('file', 'line', 'column', '__weakref__') + def __init__(self, file, line, column=None): + self.file = file + self.line = line + self.column = column + + def __str__(self): + str = "%s:%s" % (self.file, self.line) + if self.column: str += ":%s" % self.column + return str + + +class ParseError(Exception): pass + + +class PLYParser(object): + def _create_opt_rule(self, rulename): + """ Given a rule name, creates an optional ply.yacc rule + for it. The name of the optional rule is + _opt + """ + optname = rulename + '_opt' + + def optrule(self, p): + p[0] = p[1] + + optrule.__doc__ = '%s : empty\n| %s' % (optname, rulename) + optrule.__name__ = 'p_%s' % optname + setattr(self.__class__, optrule.__name__, optrule) + + def _coord(self, lineno, column=None): + return Coord( + file=self.clex.filename, + line=lineno, + column=column) + + def _token_coord(self, p, token_idx): + """ Returns the coordinates for the YaccProduction object 'p' indexed + with 'token_idx'. The coordinate includes the 'lineno' and + 'column'. Both follow the lex semantic, starting from 1. + """ + last_cr = p.lexer.lexer.lexdata.rfind('\n', 0, p.lexpos(token_idx)) + if last_cr < 0: + last_cr = -1 + column = (p.lexpos(token_idx) - (last_cr)) + return self._coord(p.lineno(token_idx), column) + + def _parse_error(self, msg, coord): + raise ParseError("%s: %s" % (coord, msg)) + + +def parameterized(*params): + """ Decorator to create parameterized rules. + + Parameterized rule methods must be named starting with 'p_' and contain + 'xxx', and their docstrings may contain 'xxx' and 'yyy'. These will be + replaced by the given parameter tuples. For example, ``p_xxx_rule()`` with + docstring 'xxx_rule : yyy' when decorated with + ``@parameterized(('id', 'ID'))`` produces ``p_id_rule()`` with the docstring + 'id_rule : ID'. Using multiple tuples produces multiple rules. + """ + def decorate(rule_func): + rule_func._params = params + return rule_func + return decorate + + +def template(cls): + """ Class decorator to generate rules from parameterized rule templates. + + See `parameterized` for more information on parameterized rules. + """ + issued_nodoc_warning = False + for attr_name in dir(cls): + if attr_name.startswith('p_'): + method = getattr(cls, attr_name) + if hasattr(method, '_params'): + # Remove the template method + delattr(cls, attr_name) + # Create parameterized rules from this method; only run this if + # the method has a docstring. This is to address an issue when + # pycparser's users are installed in -OO mode which strips + # docstrings away. + # See: https://github.com/eliben/pycparser/pull/198/ and + # https://github.com/eliben/pycparser/issues/197 + # for discussion. + if method.__doc__ is not None: + _create_param_rules(cls, method) + elif not issued_nodoc_warning: + warnings.warn( + 'parsing methods must have __doc__ for pycparser to work properly', + RuntimeWarning, + stacklevel=2) + issued_nodoc_warning = True + return cls + + +def _create_param_rules(cls, func): + """ Create ply.yacc rules based on a parameterized rule function + + Generates new methods (one per each pair of parameters) based on the + template rule function `func`, and attaches them to `cls`. The rule + function's parameters must be accessible via its `_params` attribute. + """ + for xxx, yyy in func._params: + # Use the template method's body for each new method + def param_rule(self, p): + func(self, p) + + # Substitute in the params for the grammar rule and function name + param_rule.__doc__ = func.__doc__.replace('xxx', xxx).replace('yyy', yyy) + param_rule.__name__ = func.__name__.replace('xxx', xxx) + + # Attach the new method to the class + setattr(cls, param_rule.__name__, param_rule) diff --git a/.venv/Lib/site-packages/pycparser/yacctab.py b/.venv/Lib/site-packages/pycparser/yacctab.py new file mode 100644 index 00000000..0622c366 --- /dev/null +++ b/.venv/Lib/site-packages/pycparser/yacctab.py @@ -0,0 +1,366 @@ + +# yacctab.py +# This file is automatically generated. Do not edit. +_tabversion = '3.10' + +_lr_method = 'LALR' + +_lr_signature = 'translation_unit_or_emptyleftLORleftLANDleftORleftXORleftANDleftEQNEleftGTGELTLEleftRSHIFTLSHIFTleftPLUSMINUSleftTIMESDIVIDEMODAUTO BREAK CASE CHAR CONST CONTINUE DEFAULT DO DOUBLE ELSE ENUM EXTERN FLOAT FOR GOTO IF INLINE INT LONG REGISTER OFFSETOF RESTRICT RETURN SHORT SIGNED SIZEOF STATIC STRUCT SWITCH TYPEDEF UNION UNSIGNED VOID VOLATILE WHILE __INT128 _BOOL _COMPLEX _NORETURN _THREAD_LOCAL _STATIC_ASSERT _ATOMIC _ALIGNOF _ALIGNAS ID TYPEID INT_CONST_DEC INT_CONST_OCT INT_CONST_HEX INT_CONST_BIN INT_CONST_CHAR FLOAT_CONST HEX_FLOAT_CONST CHAR_CONST WCHAR_CONST U8CHAR_CONST U16CHAR_CONST U32CHAR_CONST STRING_LITERAL WSTRING_LITERAL U8STRING_LITERAL U16STRING_LITERAL U32STRING_LITERAL PLUS MINUS TIMES DIVIDE MOD OR AND NOT XOR LSHIFT RSHIFT LOR LAND LNOT LT LE GT GE EQ NE EQUALS TIMESEQUAL DIVEQUAL MODEQUAL PLUSEQUAL MINUSEQUAL LSHIFTEQUAL RSHIFTEQUAL ANDEQUAL XOREQUAL OREQUAL PLUSPLUS MINUSMINUS ARROW CONDOP LPAREN RPAREN LBRACKET RBRACKET LBRACE RBRACE COMMA PERIOD SEMI COLON ELLIPSIS PPHASH PPPRAGMA PPPRAGMASTRabstract_declarator_opt : empty\n| abstract_declaratorassignment_expression_opt : empty\n| assignment_expressionblock_item_list_opt : empty\n| block_item_listdeclaration_list_opt : empty\n| declaration_listdeclaration_specifiers_no_type_opt : empty\n| declaration_specifiers_no_typedesignation_opt : empty\n| designationexpression_opt : empty\n| expressionid_init_declarator_list_opt : empty\n| id_init_declarator_listidentifier_list_opt : empty\n| identifier_listinit_declarator_list_opt : empty\n| init_declarator_listinitializer_list_opt : empty\n| initializer_listparameter_type_list_opt : empty\n| parameter_type_liststruct_declarator_list_opt : empty\n| struct_declarator_listtype_qualifier_list_opt : empty\n| type_qualifier_list direct_id_declarator : ID\n direct_id_declarator : LPAREN id_declarator RPAREN\n direct_id_declarator : direct_id_declarator LBRACKET type_qualifier_list_opt assignment_expression_opt RBRACKET\n direct_id_declarator : direct_id_declarator LBRACKET STATIC type_qualifier_list_opt assignment_expression RBRACKET\n | direct_id_declarator LBRACKET type_qualifier_list STATIC assignment_expression RBRACKET\n direct_id_declarator : direct_id_declarator LBRACKET type_qualifier_list_opt TIMES RBRACKET\n direct_id_declarator : direct_id_declarator LPAREN parameter_type_list RPAREN\n | direct_id_declarator LPAREN identifier_list_opt RPAREN\n direct_typeid_declarator : TYPEID\n direct_typeid_declarator : LPAREN typeid_declarator RPAREN\n direct_typeid_declarator : direct_typeid_declarator LBRACKET type_qualifier_list_opt assignment_expression_opt RBRACKET\n direct_typeid_declarator : direct_typeid_declarator LBRACKET STATIC type_qualifier_list_opt assignment_expression RBRACKET\n | direct_typeid_declarator LBRACKET type_qualifier_list STATIC assignment_expression RBRACKET\n direct_typeid_declarator : direct_typeid_declarator LBRACKET type_qualifier_list_opt TIMES RBRACKET\n direct_typeid_declarator : direct_typeid_declarator LPAREN parameter_type_list RPAREN\n | direct_typeid_declarator LPAREN identifier_list_opt RPAREN\n direct_typeid_noparen_declarator : TYPEID\n direct_typeid_noparen_declarator : direct_typeid_noparen_declarator LBRACKET type_qualifier_list_opt assignment_expression_opt RBRACKET\n direct_typeid_noparen_declarator : direct_typeid_noparen_declarator LBRACKET STATIC type_qualifier_list_opt assignment_expression RBRACKET\n | direct_typeid_noparen_declarator LBRACKET type_qualifier_list STATIC assignment_expression RBRACKET\n direct_typeid_noparen_declarator : direct_typeid_noparen_declarator LBRACKET type_qualifier_list_opt TIMES RBRACKET\n direct_typeid_noparen_declarator : direct_typeid_noparen_declarator LPAREN parameter_type_list RPAREN\n | direct_typeid_noparen_declarator LPAREN identifier_list_opt RPAREN\n id_declarator : direct_id_declarator\n id_declarator : pointer direct_id_declarator\n typeid_declarator : direct_typeid_declarator\n typeid_declarator : pointer direct_typeid_declarator\n typeid_noparen_declarator : direct_typeid_noparen_declarator\n typeid_noparen_declarator : pointer direct_typeid_noparen_declarator\n translation_unit_or_empty : translation_unit\n | empty\n translation_unit : external_declaration\n translation_unit : translation_unit external_declaration\n external_declaration : function_definition\n external_declaration : declaration\n external_declaration : pp_directive\n | pppragma_directive\n external_declaration : SEMI\n external_declaration : static_assert\n static_assert : _STATIC_ASSERT LPAREN constant_expression COMMA unified_string_literal RPAREN\n | _STATIC_ASSERT LPAREN constant_expression RPAREN\n pp_directive : PPHASH\n pppragma_directive : PPPRAGMA\n | PPPRAGMA PPPRAGMASTR\n function_definition : id_declarator declaration_list_opt compound_statement\n function_definition : declaration_specifiers id_declarator declaration_list_opt compound_statement\n statement : labeled_statement\n | expression_statement\n | compound_statement\n | selection_statement\n | iteration_statement\n | jump_statement\n | pppragma_directive\n | static_assert\n pragmacomp_or_statement : pppragma_directive statement\n | statement\n decl_body : declaration_specifiers init_declarator_list_opt\n | declaration_specifiers_no_type id_init_declarator_list_opt\n declaration : decl_body SEMI\n declaration_list : declaration\n | declaration_list declaration\n declaration_specifiers_no_type : type_qualifier declaration_specifiers_no_type_opt\n declaration_specifiers_no_type : storage_class_specifier declaration_specifiers_no_type_opt\n declaration_specifiers_no_type : function_specifier declaration_specifiers_no_type_opt\n declaration_specifiers_no_type : atomic_specifier declaration_specifiers_no_type_opt\n declaration_specifiers_no_type : alignment_specifier declaration_specifiers_no_type_opt\n declaration_specifiers : declaration_specifiers type_qualifier\n declaration_specifiers : declaration_specifiers storage_class_specifier\n declaration_specifiers : declaration_specifiers function_specifier\n declaration_specifiers : declaration_specifiers type_specifier_no_typeid\n declaration_specifiers : type_specifier\n declaration_specifiers : declaration_specifiers_no_type type_specifier\n declaration_specifiers : declaration_specifiers alignment_specifier\n storage_class_specifier : AUTO\n | REGISTER\n | STATIC\n | EXTERN\n | TYPEDEF\n | _THREAD_LOCAL\n function_specifier : INLINE\n | _NORETURN\n type_specifier_no_typeid : VOID\n | _BOOL\n | CHAR\n | SHORT\n | INT\n | LONG\n | FLOAT\n | DOUBLE\n | _COMPLEX\n | SIGNED\n | UNSIGNED\n | __INT128\n type_specifier : typedef_name\n | enum_specifier\n | struct_or_union_specifier\n | type_specifier_no_typeid\n | atomic_specifier\n atomic_specifier : _ATOMIC LPAREN type_name RPAREN\n type_qualifier : CONST\n | RESTRICT\n | VOLATILE\n | _ATOMIC\n init_declarator_list : init_declarator\n | init_declarator_list COMMA init_declarator\n init_declarator : declarator\n | declarator EQUALS initializer\n id_init_declarator_list : id_init_declarator\n | id_init_declarator_list COMMA init_declarator\n id_init_declarator : id_declarator\n | id_declarator EQUALS initializer\n specifier_qualifier_list : specifier_qualifier_list type_specifier_no_typeid\n specifier_qualifier_list : specifier_qualifier_list type_qualifier\n specifier_qualifier_list : type_specifier\n specifier_qualifier_list : type_qualifier_list type_specifier\n specifier_qualifier_list : alignment_specifier\n specifier_qualifier_list : specifier_qualifier_list alignment_specifier\n struct_or_union_specifier : struct_or_union ID\n | struct_or_union TYPEID\n struct_or_union_specifier : struct_or_union brace_open struct_declaration_list brace_close\n | struct_or_union brace_open brace_close\n struct_or_union_specifier : struct_or_union ID brace_open struct_declaration_list brace_close\n | struct_or_union ID brace_open brace_close\n | struct_or_union TYPEID brace_open struct_declaration_list brace_close\n | struct_or_union TYPEID brace_open brace_close\n struct_or_union : STRUCT\n | UNION\n struct_declaration_list : struct_declaration\n | struct_declaration_list struct_declaration\n struct_declaration : specifier_qualifier_list struct_declarator_list_opt SEMI\n struct_declaration : SEMI\n struct_declaration : pppragma_directive\n struct_declarator_list : struct_declarator\n | struct_declarator_list COMMA struct_declarator\n struct_declarator : declarator\n struct_declarator : declarator COLON constant_expression\n | COLON constant_expression\n enum_specifier : ENUM ID\n | ENUM TYPEID\n enum_specifier : ENUM brace_open enumerator_list brace_close\n enum_specifier : ENUM ID brace_open enumerator_list brace_close\n | ENUM TYPEID brace_open enumerator_list brace_close\n enumerator_list : enumerator\n | enumerator_list COMMA\n | enumerator_list COMMA enumerator\n alignment_specifier : _ALIGNAS LPAREN type_name RPAREN\n | _ALIGNAS LPAREN constant_expression RPAREN\n enumerator : ID\n | ID EQUALS constant_expression\n declarator : id_declarator\n | typeid_declarator\n pointer : TIMES type_qualifier_list_opt\n | TIMES type_qualifier_list_opt pointer\n type_qualifier_list : type_qualifier\n | type_qualifier_list type_qualifier\n parameter_type_list : parameter_list\n | parameter_list COMMA ELLIPSIS\n parameter_list : parameter_declaration\n | parameter_list COMMA parameter_declaration\n parameter_declaration : declaration_specifiers id_declarator\n | declaration_specifiers typeid_noparen_declarator\n parameter_declaration : declaration_specifiers abstract_declarator_opt\n identifier_list : identifier\n | identifier_list COMMA identifier\n initializer : assignment_expression\n initializer : brace_open initializer_list_opt brace_close\n | brace_open initializer_list COMMA brace_close\n initializer_list : designation_opt initializer\n | initializer_list COMMA designation_opt initializer\n designation : designator_list EQUALS\n designator_list : designator\n | designator_list designator\n designator : LBRACKET constant_expression RBRACKET\n | PERIOD identifier\n type_name : specifier_qualifier_list abstract_declarator_opt\n abstract_declarator : pointer\n abstract_declarator : pointer direct_abstract_declarator\n abstract_declarator : direct_abstract_declarator\n direct_abstract_declarator : LPAREN abstract_declarator RPAREN direct_abstract_declarator : direct_abstract_declarator LBRACKET assignment_expression_opt RBRACKET\n direct_abstract_declarator : LBRACKET type_qualifier_list_opt assignment_expression_opt RBRACKET\n direct_abstract_declarator : direct_abstract_declarator LBRACKET TIMES RBRACKET\n direct_abstract_declarator : LBRACKET TIMES RBRACKET\n direct_abstract_declarator : direct_abstract_declarator LPAREN parameter_type_list_opt RPAREN\n direct_abstract_declarator : LPAREN parameter_type_list_opt RPAREN\n block_item : declaration\n | statement\n block_item_list : block_item\n | block_item_list block_item\n compound_statement : brace_open block_item_list_opt brace_close labeled_statement : ID COLON pragmacomp_or_statement labeled_statement : CASE constant_expression COLON pragmacomp_or_statement labeled_statement : DEFAULT COLON pragmacomp_or_statement selection_statement : IF LPAREN expression RPAREN pragmacomp_or_statement selection_statement : IF LPAREN expression RPAREN statement ELSE pragmacomp_or_statement selection_statement : SWITCH LPAREN expression RPAREN pragmacomp_or_statement iteration_statement : WHILE LPAREN expression RPAREN pragmacomp_or_statement iteration_statement : DO pragmacomp_or_statement WHILE LPAREN expression RPAREN SEMI iteration_statement : FOR LPAREN expression_opt SEMI expression_opt SEMI expression_opt RPAREN pragmacomp_or_statement iteration_statement : FOR LPAREN declaration expression_opt SEMI expression_opt RPAREN pragmacomp_or_statement jump_statement : GOTO ID SEMI jump_statement : BREAK SEMI jump_statement : CONTINUE SEMI jump_statement : RETURN expression SEMI\n | RETURN SEMI\n expression_statement : expression_opt SEMI expression : assignment_expression\n | expression COMMA assignment_expression\n assignment_expression : LPAREN compound_statement RPAREN typedef_name : TYPEID assignment_expression : conditional_expression\n | unary_expression assignment_operator assignment_expression\n assignment_operator : EQUALS\n | XOREQUAL\n | TIMESEQUAL\n | DIVEQUAL\n | MODEQUAL\n | PLUSEQUAL\n | MINUSEQUAL\n | LSHIFTEQUAL\n | RSHIFTEQUAL\n | ANDEQUAL\n | OREQUAL\n constant_expression : conditional_expression conditional_expression : binary_expression\n | binary_expression CONDOP expression COLON conditional_expression\n binary_expression : cast_expression\n | binary_expression TIMES binary_expression\n | binary_expression DIVIDE binary_expression\n | binary_expression MOD binary_expression\n | binary_expression PLUS binary_expression\n | binary_expression MINUS binary_expression\n | binary_expression RSHIFT binary_expression\n | binary_expression LSHIFT binary_expression\n | binary_expression LT binary_expression\n | binary_expression LE binary_expression\n | binary_expression GE binary_expression\n | binary_expression GT binary_expression\n | binary_expression EQ binary_expression\n | binary_expression NE binary_expression\n | binary_expression AND binary_expression\n | binary_expression OR binary_expression\n | binary_expression XOR binary_expression\n | binary_expression LAND binary_expression\n | binary_expression LOR binary_expression\n cast_expression : unary_expression cast_expression : LPAREN type_name RPAREN cast_expression unary_expression : postfix_expression unary_expression : PLUSPLUS unary_expression\n | MINUSMINUS unary_expression\n | unary_operator cast_expression\n unary_expression : SIZEOF unary_expression\n | SIZEOF LPAREN type_name RPAREN\n | _ALIGNOF LPAREN type_name RPAREN\n unary_operator : AND\n | TIMES\n | PLUS\n | MINUS\n | NOT\n | LNOT\n postfix_expression : primary_expression postfix_expression : postfix_expression LBRACKET expression RBRACKET postfix_expression : postfix_expression LPAREN argument_expression_list RPAREN\n | postfix_expression LPAREN RPAREN\n postfix_expression : postfix_expression PERIOD ID\n | postfix_expression PERIOD TYPEID\n | postfix_expression ARROW ID\n | postfix_expression ARROW TYPEID\n postfix_expression : postfix_expression PLUSPLUS\n | postfix_expression MINUSMINUS\n postfix_expression : LPAREN type_name RPAREN brace_open initializer_list brace_close\n | LPAREN type_name RPAREN brace_open initializer_list COMMA brace_close\n primary_expression : identifier primary_expression : constant primary_expression : unified_string_literal\n | unified_wstring_literal\n primary_expression : LPAREN expression RPAREN primary_expression : OFFSETOF LPAREN type_name COMMA offsetof_member_designator RPAREN\n offsetof_member_designator : identifier\n | offsetof_member_designator PERIOD identifier\n | offsetof_member_designator LBRACKET expression RBRACKET\n argument_expression_list : assignment_expression\n | argument_expression_list COMMA assignment_expression\n identifier : ID constant : INT_CONST_DEC\n | INT_CONST_OCT\n | INT_CONST_HEX\n | INT_CONST_BIN\n | INT_CONST_CHAR\n constant : FLOAT_CONST\n | HEX_FLOAT_CONST\n constant : CHAR_CONST\n | WCHAR_CONST\n | U8CHAR_CONST\n | U16CHAR_CONST\n | U32CHAR_CONST\n unified_string_literal : STRING_LITERAL\n | unified_string_literal STRING_LITERAL\n unified_wstring_literal : WSTRING_LITERAL\n | U8STRING_LITERAL\n | U16STRING_LITERAL\n | U32STRING_LITERAL\n | unified_wstring_literal WSTRING_LITERAL\n | unified_wstring_literal U8STRING_LITERAL\n | unified_wstring_literal U16STRING_LITERAL\n | unified_wstring_literal U32STRING_LITERAL\n brace_open : LBRACE\n brace_close : RBRACE\n empty : ' + +_lr_action_items = {'INT_CONST_CHAR':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,146,149,150,151,165,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,132,-335,-28,-182,-27,132,-337,-87,-72,-337,132,-286,-285,132,132,-283,-287,-288,132,-284,132,132,132,-336,-183,132,132,-28,-337,132,-28,-337,-337,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,-337,-76,-79,-82,-75,132,-77,132,132,-81,-215,-214,-80,-216,132,-78,132,132,-69,-284,132,132,-284,132,132,-244,-247,-245,-241,-242,-246,-248,132,-250,-251,-243,-249,-12,132,132,-11,132,132,132,132,-234,-233,132,-231,132,132,-217,132,-230,132,-84,-218,132,132,132,-337,-337,-198,132,132,132,-337,-284,-229,-232,132,-221,132,-83,-219,-68,132,-28,-337,132,-11,132,132,-220,132,132,132,-284,132,132,132,-337,132,-225,-224,-222,-84,132,132,132,-226,-223,132,-228,-227,]),'VOID':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,40,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,71,75,76,80,81,82,85,86,87,89,90,91,93,94,95,96,97,98,99,100,101,105,109,111,118,119,120,121,122,123,124,129,142,147,172,174,177,180,181,182,184,185,186,187,188,189,190,191,192,198,200,211,214,223,229,231,233,239,240,241,267,269,275,278,279,280,284,285,286,289,291,298,300,301,302,303,305,308,312,313,314,315,316,317,318,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,446,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[6,-337,-113,-128,6,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,6,-120,-115,-65,-102,-126,-131,-108,-238,-111,-122,-63,-129,6,-29,-121,-116,-62,-112,-70,-52,-123,-117,-337,-337,-119,-337,-114,-130,6,-118,-71,-103,-337,-9,-131,-91,-10,-96,-98,6,-131,-95,-101,-97,6,-53,-126,6,-88,6,6,-93,6,-147,-335,-146,6,-167,-166,-182,-100,-126,6,-87,-90,-94,-92,-61,-72,6,-144,-142,6,6,6,-73,6,-89,6,6,6,-149,-159,-160,-156,-336,6,-183,-30,6,6,-74,6,6,6,6,-174,-175,6,-143,-140,6,-141,-145,-76,-79,-82,-75,-77,6,-81,-215,-214,-80,-216,-78,-127,6,-153,6,-151,-148,-157,-168,-69,-36,-35,6,6,6,-234,-233,6,-231,-217,-230,-81,-84,-218,-152,-150,-158,-170,-169,-31,-34,6,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'LBRACKET':([2,3,5,6,7,10,11,12,13,18,20,22,23,26,27,30,33,34,35,36,39,42,43,44,46,48,49,50,54,56,58,60,62,68,71,73,76,77,80,81,82,86,96,97,98,100,101,103,104,105,106,109,111,127,132,133,134,136,138,139,140,141,142,143,145,147,148,152,153,154,156,160,161,163,164,166,167,168,169,176,177,187,191,198,199,200,211,216,227,230,235,236,237,238,240,241,261,263,269,275,276,278,279,280,283,310,312,314,316,317,328,340,341,342,344,345,347,355,356,371,376,402,403,404,405,407,411,414,442,443,448,449,453,454,457,458,464,465,470,472,474,482,483,488,489,490,492,511,512,518,519,520,526,527,529,530,531,532,544,545,547,550,551,559,560,563,565,570,571,572,],[-113,-128,-124,-110,-106,-104,-107,-125,-105,-99,-109,-120,-115,-102,-126,-108,-238,-111,-337,-122,-129,-29,-121,-116,-112,117,-123,-117,-119,-114,-130,-118,-103,-96,-98,128,-131,-37,-95,-101,-97,117,-147,-335,-146,-167,-166,-28,-180,-182,-27,-100,-126,128,-317,-321,-318,-303,-324,-330,-313,-319,-144,-301,-314,-142,-327,-325,-304,-322,-302,-315,-289,-328,-316,-329,-320,265,-323,-312,282,-149,-336,-183,-181,-30,282,-38,373,-326,-334,-332,-331,-333,-174,-175,-298,-297,-143,-140,282,282,-141,-145,421,-312,-127,-153,-151,-148,-168,-36,-35,282,282,459,-45,-44,-43,-199,373,-296,-295,-294,-293,-292,-305,421,-152,-150,-170,-169,-31,-34,282,459,-39,-42,-202,373,-200,-290,-291,373,-213,-207,-211,-33,-32,-41,-40,-201,549,-307,-209,-208,-210,-212,-51,-50,-306,373,-299,-46,-49,-308,-300,-48,-47,-309,]),'WCHAR_CONST':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,146,149,150,151,165,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,133,-335,-28,-182,-27,133,-337,-87,-72,-337,133,-286,-285,133,133,-283,-287,-288,133,-284,133,133,133,-336,-183,133,133,-28,-337,133,-28,-337,-337,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,-337,-76,-79,-82,-75,133,-77,133,133,-81,-215,-214,-80,-216,133,-78,133,133,-69,-284,133,133,-284,133,133,-244,-247,-245,-241,-242,-246,-248,133,-250,-251,-243,-249,-12,133,133,-11,133,133,133,133,-234,-233,133,-231,133,133,-217,133,-230,133,-84,-218,133,133,133,-337,-337,-198,133,133,133,-337,-284,-229,-232,133,-221,133,-83,-219,-68,133,-28,-337,133,-11,133,133,-220,133,133,133,-284,133,133,133,-337,133,-225,-224,-222,-84,133,133,133,-226,-223,133,-228,-227,]),'FLOAT_CONST':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,146,149,150,151,165,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,134,-335,-28,-182,-27,134,-337,-87,-72,-337,134,-286,-285,134,134,-283,-287,-288,134,-284,134,134,134,-336,-183,134,134,-28,-337,134,-28,-337,-337,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,-337,-76,-79,-82,-75,134,-77,134,134,-81,-215,-214,-80,-216,134,-78,134,134,-69,-284,134,134,-284,134,134,-244,-247,-245,-241,-242,-246,-248,134,-250,-251,-243,-249,-12,134,134,-11,134,134,134,134,-234,-233,134,-231,134,134,-217,134,-230,134,-84,-218,134,134,134,-337,-337,-198,134,134,134,-337,-284,-229,-232,134,-221,134,-83,-219,-68,134,-28,-337,134,-11,134,134,-220,134,134,134,-284,134,134,134,-337,134,-225,-224,-222,-84,134,134,134,-226,-223,134,-228,-227,]),'MINUS':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,132,133,134,135,136,137,138,139,140,141,143,144,145,146,148,149,150,151,152,153,154,156,158,160,161,162,163,164,165,166,167,168,169,171,173,174,175,176,181,191,198,201,204,205,206,218,219,220,224,227,229,230,231,232,233,234,235,236,237,238,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,263,265,266,268,273,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,310,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,478,480,481,482,483,484,487,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,547,549,550,551,553,554,555,557,558,565,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,135,-335,-28,-182,-27,135,-337,-87,-72,-337,135,-317,-321,-318,-286,-303,-285,-324,-330,-313,-319,-301,-274,-314,135,-327,135,-283,-287,-325,-304,-322,-302,-255,-315,-289,245,-328,-316,-288,-329,-320,-276,-323,135,-284,135,135,-312,135,-336,-183,135,135,-28,-337,135,-28,-337,-274,-337,135,-326,135,-280,135,-277,-334,-332,-331,-333,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,-298,-297,135,135,-279,-278,-337,-76,-79,-82,-75,135,-77,135,135,-81,-215,-214,-80,-216,135,-78,-312,135,135,-69,-284,135,135,-284,135,135,-244,-247,-245,-241,-242,-246,-248,135,-250,-251,-243,-249,-12,135,135,-11,245,245,245,-260,245,245,245,-259,245,245,-257,-256,245,245,245,245,245,-258,-296,-295,-294,-293,-292,-305,135,135,135,135,-234,-233,135,-231,135,135,-217,135,-230,135,-84,-218,135,135,135,-337,-337,-198,135,-281,-282,135,-290,-291,135,-275,-337,-284,-229,-232,135,-221,135,-83,-219,-68,135,-28,-337,135,-11,135,135,-220,135,135,135,-284,135,135,-306,135,-337,-299,135,-225,-224,-222,-84,-300,135,135,135,-226,-223,135,-228,-227,]),'RPAREN':([2,3,5,6,7,10,11,12,13,18,20,22,23,26,27,30,33,34,35,36,39,42,43,44,46,48,49,50,54,56,58,60,62,68,71,73,76,77,80,81,82,86,96,98,100,101,103,104,105,106,107,109,111,118,125,127,129,132,133,134,136,138,139,140,141,142,143,144,145,147,148,152,153,154,156,157,158,159,160,161,162,163,164,166,167,168,169,176,177,178,183,187,191,198,199,200,203,207,208,209,210,211,212,213,215,216,221,222,224,225,230,232,234,235,236,237,238,240,241,261,263,266,268,269,270,271,272,273,274,275,276,277,278,279,280,281,283,294,312,314,316,317,328,340,341,342,343,344,345,346,347,348,355,356,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,408,409,411,414,415,416,417,418,422,433,439,442,443,448,449,452,453,454,457,458,460,461,462,463,464,465,468,476,478,480,482,483,486,487,489,490,492,495,501,503,507,511,512,516,517,518,519,524,525,526,527,529,530,531,532,544,545,547,551,553,556,559,560,563,565,566,567,570,571,572,573,],[-113,-128,-124,-110,-106,-104,-107,-125,-105,-99,-109,-120,-115,-102,-126,-108,-238,-111,-337,-122,-129,-29,-121,-116,-112,-52,-123,-117,-119,-114,-130,-118,-103,-96,-98,-54,-131,-37,-95,-101,-97,-53,-147,-146,-167,-166,-28,-180,-182,-27,200,-100,-126,-337,216,-55,-337,-317,-321,-318,-303,-324,-330,-313,-319,-144,-301,-274,-314,-142,-327,-325,-304,-322,-302,240,-255,241,-315,-289,-253,-328,-316,-329,-320,-276,-323,-312,-337,-252,312,-149,-336,-183,-181,-30,332,340,-17,341,-186,-337,-18,-184,-191,-38,355,356,-274,-239,-326,-280,-277,-334,-332,-331,-333,-174,-175,-298,-297,407,-279,-143,411,413,-235,-278,-203,-140,-204,-1,-337,-141,-145,-2,-206,-14,-127,-153,-151,-148,-168,-36,-35,-337,-190,-204,-56,-188,-45,-189,-44,-43,476,477,478,479,480,-261,-273,-262,-260,-264,-268,-263,-259,-266,-271,-257,-256,-265,-272,-267,-269,-270,-258,-296,-295,-294,-293,-292,-310,483,-305,-205,-23,-24,489,490,-337,-13,-218,-152,-150,-170,-169,510,-31,-34,-204,-57,-337,-192,-185,-187,-39,-42,-240,-237,-281,-282,-290,-291,-236,-275,-213,-207,-211,532,535,537,539,-33,-32,544,545,-41,-40,-254,-311,547,-307,-209,-208,-210,-212,-51,-50,-306,-299,-337,568,-46,-49,-308,-300,-337,574,-48,-47,-309,577,]),'STRUCT':([0,1,3,7,10,11,13,14,16,17,19,20,21,25,26,27,29,30,38,39,40,42,45,47,48,52,53,55,58,59,61,62,63,64,65,66,67,75,85,86,87,90,91,93,94,95,97,99,105,118,119,120,121,122,123,124,129,172,174,180,181,182,184,185,186,188,189,190,191,198,200,214,223,229,231,233,239,240,241,267,278,284,285,286,289,291,298,300,301,302,303,305,308,312,313,315,318,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,446,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[24,-337,-128,-106,-104,-107,-105,-64,-60,-67,-66,-109,24,-65,-102,-337,-131,-108,-63,-129,24,-29,-62,-70,-52,-337,-337,-337,-130,24,-71,-103,-337,-9,-131,-91,-10,24,24,-53,-337,-88,24,24,-93,24,-335,24,-182,24,-87,-90,-94,-92,-61,-72,24,24,24,-73,24,-89,24,24,24,-159,-160,-156,-336,-183,-30,24,-74,24,24,24,24,-174,-175,24,24,-76,-79,-82,-75,-77,24,-81,-215,-214,-80,-216,-78,-127,24,24,-157,-69,-36,-35,24,24,24,-234,-233,24,-231,-217,-230,-81,-84,-218,-158,-31,-34,24,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'LONG':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,40,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,71,75,76,80,81,82,85,86,87,89,90,91,93,94,95,96,97,98,99,100,101,105,109,111,118,119,120,121,122,123,124,129,142,147,172,174,177,180,181,182,184,185,186,187,188,189,190,191,192,198,200,211,214,223,229,231,233,239,240,241,267,269,275,278,279,280,284,285,286,289,291,298,300,301,302,303,305,308,312,313,314,315,316,317,318,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,446,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[23,-337,-113,-128,23,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,23,-120,-115,-65,-102,-126,-131,-108,-238,-111,-122,-63,-129,23,-29,-121,-116,-62,-112,-70,-52,-123,-117,-337,-337,-119,-337,-114,-130,23,-118,-71,-103,-337,-9,-131,-91,-10,-96,-98,23,-131,-95,-101,-97,23,-53,-126,23,-88,23,23,-93,23,-147,-335,-146,23,-167,-166,-182,-100,-126,23,-87,-90,-94,-92,-61,-72,23,-144,-142,23,23,23,-73,23,-89,23,23,23,-149,-159,-160,-156,-336,23,-183,-30,23,23,-74,23,23,23,23,-174,-175,23,-143,-140,23,-141,-145,-76,-79,-82,-75,-77,23,-81,-215,-214,-80,-216,-78,-127,23,-153,23,-151,-148,-157,-168,-69,-36,-35,23,23,23,-234,-233,23,-231,-217,-230,-81,-84,-218,-152,-150,-158,-170,-169,-31,-34,23,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'PLUS':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,132,133,134,135,136,137,138,139,140,141,143,144,145,146,148,149,150,151,152,153,154,156,158,160,161,162,163,164,165,166,167,168,169,171,173,174,175,176,181,191,198,201,204,205,206,218,219,220,224,227,229,230,231,232,233,234,235,236,237,238,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,263,265,266,268,273,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,310,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,478,480,481,482,483,484,487,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,547,549,550,551,553,554,555,557,558,565,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,137,-335,-28,-182,-27,137,-337,-87,-72,-337,137,-317,-321,-318,-286,-303,-285,-324,-330,-313,-319,-301,-274,-314,137,-327,137,-283,-287,-325,-304,-322,-302,-255,-315,-289,249,-328,-316,-288,-329,-320,-276,-323,137,-284,137,137,-312,137,-336,-183,137,137,-28,-337,137,-28,-337,-274,-337,137,-326,137,-280,137,-277,-334,-332,-331,-333,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,-298,-297,137,137,-279,-278,-337,-76,-79,-82,-75,137,-77,137,137,-81,-215,-214,-80,-216,137,-78,-312,137,137,-69,-284,137,137,-284,137,137,-244,-247,-245,-241,-242,-246,-248,137,-250,-251,-243,-249,-12,137,137,-11,249,249,249,-260,249,249,249,-259,249,249,-257,-256,249,249,249,249,249,-258,-296,-295,-294,-293,-292,-305,137,137,137,137,-234,-233,137,-231,137,137,-217,137,-230,137,-84,-218,137,137,137,-337,-337,-198,137,-281,-282,137,-290,-291,137,-275,-337,-284,-229,-232,137,-221,137,-83,-219,-68,137,-28,-337,137,-11,137,137,-220,137,137,137,-284,137,137,-306,137,-337,-299,137,-225,-224,-222,-84,-300,137,137,137,-226,-223,137,-228,-227,]),'ELLIPSIS':([350,],[462,]),'U32STRING_LITERAL':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,139,146,148,149,150,151,153,163,165,166,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,235,236,237,238,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,139,-335,-28,-182,-27,139,-337,-87,-72,-337,139,-286,-285,-330,139,-327,139,-283,-287,235,-328,-288,-329,139,-284,139,139,139,-336,-183,139,139,-28,-337,139,-28,-337,-337,139,139,139,-334,-332,-331,-333,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,-337,-76,-79,-82,-75,139,-77,139,139,-81,-215,-214,-80,-216,139,-78,139,139,-69,-284,139,139,-284,139,139,-244,-247,-245,-241,-242,-246,-248,139,-250,-251,-243,-249,-12,139,139,-11,139,139,139,139,-234,-233,139,-231,139,139,-217,139,-230,139,-84,-218,139,139,139,-337,-337,-198,139,139,139,-337,-284,-229,-232,139,-221,139,-83,-219,-68,139,-28,-337,139,-11,139,139,-220,139,139,139,-284,139,139,139,-337,139,-225,-224,-222,-84,139,139,139,-226,-223,139,-228,-227,]),'GT':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-255,-315,-289,250,-328,-316,-329,-320,-276,-323,-312,-336,-274,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-261,250,-262,-260,-264,250,-263,-259,-266,250,-257,-256,-265,250,250,250,250,-258,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'GOTO':([61,97,119,124,181,191,284,285,286,289,291,298,300,301,302,303,305,307,308,332,424,425,428,429,432,435,437,438,439,440,496,497,500,502,505,506,510,535,536,537,539,554,555,557,558,569,574,575,576,577,578,579,],[-71,-335,-87,-72,287,-336,-76,-79,-82,-75,-77,287,-81,-215,-214,-80,-216,287,-78,-69,-234,-233,-231,287,-217,-230,287,-84,-218,287,-229,-232,-221,287,-83,-219,-68,287,-220,287,287,-225,-224,-222,-84,287,287,-226,-223,287,-228,-227,]),'ENUM':([0,1,3,7,10,11,13,14,16,17,19,20,21,25,26,27,29,30,38,39,40,42,45,47,48,52,53,55,58,59,61,62,63,64,65,66,67,75,85,86,87,90,91,93,94,95,97,99,105,118,119,120,121,122,123,124,129,172,174,180,181,182,184,185,186,188,189,190,191,198,200,214,223,229,231,233,239,240,241,267,278,284,285,286,289,291,298,300,301,302,303,305,308,312,313,315,318,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,446,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[32,-337,-128,-106,-104,-107,-105,-64,-60,-67,-66,-109,32,-65,-102,-337,-131,-108,-63,-129,32,-29,-62,-70,-52,-337,-337,-337,-130,32,-71,-103,-337,-9,-131,-91,-10,32,32,-53,-337,-88,32,32,-93,32,-335,32,-182,32,-87,-90,-94,-92,-61,-72,32,32,32,-73,32,-89,32,32,32,-159,-160,-156,-336,-183,-30,32,-74,32,32,32,32,-174,-175,32,32,-76,-79,-82,-75,-77,32,-81,-215,-214,-80,-216,-78,-127,32,32,-157,-69,-36,-35,32,32,32,-234,-233,32,-231,-217,-230,-81,-84,-218,-158,-31,-34,32,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'PERIOD':([97,132,133,134,136,138,139,140,141,143,145,148,152,153,154,156,160,161,163,164,166,167,168,169,176,191,227,230,235,236,237,238,261,263,310,371,376,402,403,404,405,407,411,470,472,474,482,483,488,520,526,527,547,550,551,563,565,572,],[-335,-317,-321,-318,-303,-324,-330,-313,-319,-301,-314,-327,-325,-304,-322,-302,-315,-289,-328,-316,-329,-320,264,-323,-312,-336,372,-326,-334,-332,-331,-333,-298,-297,-312,-199,372,-296,-295,-294,-293,-292,-305,-202,372,-200,-290,-291,372,-201,548,-307,-306,372,-299,-308,-300,-309,]),'GE':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-255,-315,-289,254,-328,-316,-329,-320,-276,-323,-312,-336,-274,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-261,254,-262,-260,-264,254,-263,-259,-266,254,-257,-256,-265,254,254,254,254,-258,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'INT_CONST_DEC':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,146,149,150,151,165,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,140,-335,-28,-182,-27,140,-337,-87,-72,-337,140,-286,-285,140,140,-283,-287,-288,140,-284,140,140,140,-336,-183,140,140,-28,-337,140,-28,-337,-337,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,-337,-76,-79,-82,-75,140,-77,140,140,-81,-215,-214,-80,-216,140,-78,140,140,-69,-284,140,140,-284,140,140,-244,-247,-245,-241,-242,-246,-248,140,-250,-251,-243,-249,-12,140,140,-11,140,140,140,140,-234,-233,140,-231,140,140,-217,140,-230,140,-84,-218,140,140,140,-337,-337,-198,140,140,140,-337,-284,-229,-232,140,-221,140,-83,-219,-68,140,-28,-337,140,-11,140,140,-220,140,140,140,-284,140,140,140,-337,140,-225,-224,-222,-84,140,140,140,-226,-223,140,-228,-227,]),'ARROW':([132,133,134,136,138,139,140,141,143,145,148,152,153,154,156,160,161,163,164,166,167,168,169,176,191,230,235,236,237,238,261,263,310,402,403,404,405,407,411,482,483,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-314,-327,-325,-304,-322,-302,-315,-289,-328,-316,-329,-320,262,-323,-312,-336,-326,-334,-332,-331,-333,-298,-297,-312,-296,-295,-294,-293,-292,-305,-290,-291,-306,-299,-300,]),'_STATIC_ASSERT':([0,14,16,17,19,25,38,45,47,59,61,97,119,123,124,180,181,191,223,284,285,286,289,291,298,300,301,302,303,305,307,308,332,424,425,428,429,432,435,437,438,439,440,496,497,500,502,505,506,510,535,536,537,539,554,555,557,558,569,574,575,576,577,578,579,],[41,-64,-60,-67,-66,-65,-63,-62,-70,41,-71,-335,-87,-61,-72,-73,41,-336,-74,-76,-79,-82,-75,-77,41,-81,-215,-214,-80,-216,41,-78,-69,-234,-233,-231,41,-217,-230,41,-84,-218,41,-229,-232,-221,41,-83,-219,-68,41,-220,41,41,-225,-224,-222,-84,41,41,-226,-223,41,-228,-227,]),'CHAR':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,40,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,71,75,76,80,81,82,85,86,87,89,90,91,93,94,95,96,97,98,99,100,101,105,109,111,118,119,120,121,122,123,124,129,142,147,172,174,177,180,181,182,184,185,186,187,188,189,190,191,192,198,200,211,214,223,229,231,233,239,240,241,267,269,275,278,279,280,284,285,286,289,291,298,300,301,302,303,305,308,312,313,314,315,316,317,318,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,446,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[46,-337,-113,-128,46,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,46,-120,-115,-65,-102,-126,-131,-108,-238,-111,-122,-63,-129,46,-29,-121,-116,-62,-112,-70,-52,-123,-117,-337,-337,-119,-337,-114,-130,46,-118,-71,-103,-337,-9,-131,-91,-10,-96,-98,46,-131,-95,-101,-97,46,-53,-126,46,-88,46,46,-93,46,-147,-335,-146,46,-167,-166,-182,-100,-126,46,-87,-90,-94,-92,-61,-72,46,-144,-142,46,46,46,-73,46,-89,46,46,46,-149,-159,-160,-156,-336,46,-183,-30,46,46,-74,46,46,46,46,-174,-175,46,-143,-140,46,-141,-145,-76,-79,-82,-75,-77,46,-81,-215,-214,-80,-216,-78,-127,46,-153,46,-151,-148,-157,-168,-69,-36,-35,46,46,46,-234,-233,46,-231,-217,-230,-81,-84,-218,-152,-150,-158,-170,-169,-31,-34,46,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'HEX_FLOAT_CONST':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,146,149,150,151,165,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,141,-335,-28,-182,-27,141,-337,-87,-72,-337,141,-286,-285,141,141,-283,-287,-288,141,-284,141,141,141,-336,-183,141,141,-28,-337,141,-28,-337,-337,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,-337,-76,-79,-82,-75,141,-77,141,141,-81,-215,-214,-80,-216,141,-78,141,141,-69,-284,141,141,-284,141,141,-244,-247,-245,-241,-242,-246,-248,141,-250,-251,-243,-249,-12,141,141,-11,141,141,141,141,-234,-233,141,-231,141,141,-217,141,-230,141,-84,-218,141,141,141,-337,-337,-198,141,141,141,-337,-284,-229,-232,141,-221,141,-83,-219,-68,141,-28,-337,141,-11,141,141,-220,141,141,141,-284,141,141,141,-337,141,-225,-224,-222,-84,141,141,141,-226,-223,141,-228,-227,]),'DOUBLE':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,40,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,71,75,76,80,81,82,85,86,87,89,90,91,93,94,95,96,97,98,99,100,101,105,109,111,118,119,120,121,122,123,124,129,142,147,172,174,177,180,181,182,184,185,186,187,188,189,190,191,192,198,200,211,214,223,229,231,233,239,240,241,267,269,275,278,279,280,284,285,286,289,291,298,300,301,302,303,305,308,312,313,314,315,316,317,318,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,446,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[50,-337,-113,-128,50,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,50,-120,-115,-65,-102,-126,-131,-108,-238,-111,-122,-63,-129,50,-29,-121,-116,-62,-112,-70,-52,-123,-117,-337,-337,-119,-337,-114,-130,50,-118,-71,-103,-337,-9,-131,-91,-10,-96,-98,50,-131,-95,-101,-97,50,-53,-126,50,-88,50,50,-93,50,-147,-335,-146,50,-167,-166,-182,-100,-126,50,-87,-90,-94,-92,-61,-72,50,-144,-142,50,50,50,-73,50,-89,50,50,50,-149,-159,-160,-156,-336,50,-183,-30,50,50,-74,50,50,50,50,-174,-175,50,-143,-140,50,-141,-145,-76,-79,-82,-75,-77,50,-81,-215,-214,-80,-216,-78,-127,50,-153,50,-151,-148,-157,-168,-69,-36,-35,50,50,50,-234,-233,50,-231,-217,-230,-81,-84,-218,-152,-150,-158,-170,-169,-31,-34,50,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'MINUSEQUAL':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,160,161,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-315,-289,-328,-316,-329,-320,-276,-323,-312,-336,358,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'INT_CONST_OCT':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,146,149,150,151,165,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,145,-335,-28,-182,-27,145,-337,-87,-72,-337,145,-286,-285,145,145,-283,-287,-288,145,-284,145,145,145,-336,-183,145,145,-28,-337,145,-28,-337,-337,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,-337,-76,-79,-82,-75,145,-77,145,145,-81,-215,-214,-80,-216,145,-78,145,145,-69,-284,145,145,-284,145,145,-244,-247,-245,-241,-242,-246,-248,145,-250,-251,-243,-249,-12,145,145,-11,145,145,145,145,-234,-233,145,-231,145,145,-217,145,-230,145,-84,-218,145,145,145,-337,-337,-198,145,145,145,-337,-284,-229,-232,145,-221,145,-83,-219,-68,145,-28,-337,145,-11,145,145,-220,145,145,145,-284,145,145,145,-337,145,-225,-224,-222,-84,145,145,145,-226,-223,145,-228,-227,]),'TIMESEQUAL':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,160,161,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-315,-289,-328,-316,-329,-320,-276,-323,-312,-336,367,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'OR':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-255,-315,-289,259,-328,-316,-329,-320,-276,-323,-312,-336,-274,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-261,259,-262,-260,-264,-268,-263,-259,-266,-271,-257,-256,-265,259,-267,-269,-270,-258,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'SHORT':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,40,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,71,75,76,80,81,82,85,86,87,89,90,91,93,94,95,96,97,98,99,100,101,105,109,111,118,119,120,121,122,123,124,129,142,147,172,174,177,180,181,182,184,185,186,187,188,189,190,191,192,198,200,211,214,223,229,231,233,239,240,241,267,269,275,278,279,280,284,285,286,289,291,298,300,301,302,303,305,308,312,313,314,315,316,317,318,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,446,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[2,-337,-113,-128,2,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,2,-120,-115,-65,-102,-126,-131,-108,-238,-111,-122,-63,-129,2,-29,-121,-116,-62,-112,-70,-52,-123,-117,-337,-337,-119,-337,-114,-130,2,-118,-71,-103,-337,-9,-131,-91,-10,-96,-98,2,-131,-95,-101,-97,2,-53,-126,2,-88,2,2,-93,2,-147,-335,-146,2,-167,-166,-182,-100,-126,2,-87,-90,-94,-92,-61,-72,2,-144,-142,2,2,2,-73,2,-89,2,2,2,-149,-159,-160,-156,-336,2,-183,-30,2,2,-74,2,2,2,2,-174,-175,2,-143,-140,2,-141,-145,-76,-79,-82,-75,-77,2,-81,-215,-214,-80,-216,-78,-127,2,-153,2,-151,-148,-157,-168,-69,-36,-35,2,2,2,-234,-233,2,-231,-217,-230,-81,-84,-218,-152,-150,-158,-170,-169,-31,-34,2,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'RETURN':([61,97,119,124,181,191,284,285,286,289,291,298,300,301,302,303,305,307,308,332,424,425,428,429,432,435,437,438,439,440,496,497,500,502,505,506,510,535,536,537,539,554,555,557,558,569,574,575,576,577,578,579,],[-71,-335,-87,-72,290,-336,-76,-79,-82,-75,-77,290,-81,-215,-214,-80,-216,290,-78,-69,-234,-233,-231,290,-217,-230,290,-84,-218,290,-229,-232,-221,290,-83,-219,-68,290,-220,290,290,-225,-224,-222,-84,290,290,-226,-223,290,-228,-227,]),'RSHIFTEQUAL':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,160,161,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-315,-289,-328,-316,-329,-320,-276,-323,-312,-336,368,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'_ALIGNAS':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,65,68,71,75,76,80,81,82,85,86,87,89,90,93,95,96,97,98,99,100,101,109,111,118,119,123,124,129,142,147,174,177,180,181,182,184,185,186,187,188,189,190,191,192,200,211,223,229,231,233,239,240,241,267,269,275,278,279,280,284,285,286,289,291,298,300,301,302,303,305,308,312,313,314,315,316,317,318,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,446,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[8,8,-113,-128,8,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,8,-120,-115,-65,-102,8,-131,-108,-238,-111,-122,-63,-129,-29,-121,-116,-62,-112,-70,-52,-123,-117,8,8,-119,8,-114,-130,8,-118,-71,-103,8,-131,-96,-98,8,-131,-95,-101,-97,8,-53,8,8,-88,8,8,-147,-335,-146,8,-167,-166,-100,-126,8,-87,-61,-72,8,-144,-142,8,8,-73,8,-89,8,8,8,-149,-159,-160,-156,-336,8,-30,8,-74,8,8,8,8,-174,-175,8,-143,-140,8,-141,-145,-76,-79,-82,-75,-77,8,-81,-215,-214,-80,-216,-78,-127,8,-153,8,-151,-148,-157,-168,-69,-36,-35,8,8,8,-234,-233,8,-231,-217,-230,-81,-84,-218,-152,-150,-158,-170,-169,-31,-34,8,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'RESTRICT':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,35,36,38,39,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,65,68,71,75,76,80,81,82,85,86,87,89,90,93,95,96,97,98,99,100,101,103,105,109,111,117,118,119,123,124,128,129,142,147,172,174,177,180,181,182,184,185,186,187,188,189,190,191,192,198,200,205,206,211,219,220,223,229,231,233,239,240,241,267,269,275,278,279,280,282,284,285,286,289,291,298,300,301,302,303,305,308,312,313,314,315,316,317,318,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,446,448,449,453,454,459,460,496,497,500,505,506,510,511,512,514,515,536,554,555,557,558,575,576,578,579,],[39,39,-113,-128,39,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,39,-120,-115,-65,-102,39,-131,-108,-238,-111,39,-122,-63,-129,-29,-121,-116,-62,-112,-70,-52,-123,-117,39,39,-119,39,-114,-130,39,-118,-71,-103,39,-131,-96,-98,39,-131,-95,-101,-97,39,-53,39,39,-88,39,39,-147,-335,-146,39,-167,-166,39,-182,-100,-126,39,39,-87,-61,-72,39,39,-144,-142,39,39,39,-73,39,-89,39,39,39,-149,-159,-160,-156,-336,39,-183,-30,39,39,39,39,39,-74,39,39,39,39,-174,-175,39,-143,-140,39,-141,-145,39,-76,-79,-82,-75,-77,39,-81,-215,-214,-80,-216,-78,-127,39,-153,39,-151,-148,-157,-168,-69,-36,-35,39,39,39,-234,-233,39,-231,-217,-230,-81,-84,-218,-152,-150,-158,-170,-169,-31,-34,39,39,-229,-232,-221,-83,-219,-68,-33,-32,39,39,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'STATIC':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,65,68,71,75,76,80,81,82,86,87,89,90,93,96,97,98,100,101,105,109,111,117,118,119,123,124,128,129,180,181,182,187,191,198,200,205,211,219,223,240,241,278,284,285,286,289,291,298,300,301,302,303,305,308,312,314,316,317,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,448,449,453,454,459,460,496,497,500,505,506,510,511,512,514,536,554,555,557,558,575,576,578,579,],[10,10,-113,-128,10,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,10,-120,-115,-65,-102,10,-131,-108,-238,-111,-122,-63,-129,-29,-121,-116,-62,-112,-70,-52,-123,-117,10,10,-119,10,-114,-130,10,-118,-71,-103,10,-131,-96,-98,10,-131,-95,-101,-97,-53,10,10,-88,10,-147,-335,-146,-167,-166,-182,-100,-126,206,10,-87,-61,-72,220,10,-73,10,-89,-149,-336,-183,-30,338,10,353,-74,-174,-175,10,-76,-79,-82,-75,-77,10,-81,-215,-214,-80,-216,-78,-127,-153,-151,-148,-168,-69,-36,-35,10,10,10,-234,-233,10,-231,-217,-230,-81,-84,-218,-152,-150,-170,-169,-31,-34,515,10,-229,-232,-221,-83,-219,-68,-33,-32,542,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'SIZEOF':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,146,149,150,151,165,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,146,-335,-28,-182,-27,146,-337,-87,-72,-337,146,-286,-285,146,146,-283,-287,-288,146,-284,146,146,146,-336,-183,146,146,-28,-337,146,-28,-337,-337,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,-337,-76,-79,-82,-75,146,-77,146,146,-81,-215,-214,-80,-216,146,-78,146,146,-69,-284,146,146,-284,146,146,-244,-247,-245,-241,-242,-246,-248,146,-250,-251,-243,-249,-12,146,146,-11,146,146,146,146,-234,-233,146,-231,146,146,-217,146,-230,146,-84,-218,146,146,146,-337,-337,-198,146,146,146,-337,-284,-229,-232,146,-221,146,-83,-219,-68,146,-28,-337,146,-11,146,146,-220,146,146,146,-284,146,146,146,-337,146,-225,-224,-222,-84,146,146,146,-226,-223,146,-228,-227,]),'UNSIGNED':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,40,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,71,75,76,80,81,82,85,86,87,89,90,91,93,94,95,96,97,98,99,100,101,105,109,111,118,119,120,121,122,123,124,129,142,147,172,174,177,180,181,182,184,185,186,187,188,189,190,191,192,198,200,211,214,223,229,231,233,239,240,241,267,269,275,278,279,280,284,285,286,289,291,298,300,301,302,303,305,308,312,313,314,315,316,317,318,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,446,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[22,-337,-113,-128,22,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,22,-120,-115,-65,-102,-126,-131,-108,-238,-111,-122,-63,-129,22,-29,-121,-116,-62,-112,-70,-52,-123,-117,-337,-337,-119,-337,-114,-130,22,-118,-71,-103,-337,-9,-131,-91,-10,-96,-98,22,-131,-95,-101,-97,22,-53,-126,22,-88,22,22,-93,22,-147,-335,-146,22,-167,-166,-182,-100,-126,22,-87,-90,-94,-92,-61,-72,22,-144,-142,22,22,22,-73,22,-89,22,22,22,-149,-159,-160,-156,-336,22,-183,-30,22,22,-74,22,22,22,22,-174,-175,22,-143,-140,22,-141,-145,-76,-79,-82,-75,-77,22,-81,-215,-214,-80,-216,-78,-127,22,-153,22,-151,-148,-157,-168,-69,-36,-35,22,22,22,-234,-233,22,-231,-217,-230,-81,-84,-218,-152,-150,-158,-170,-169,-31,-34,22,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'UNION':([0,1,3,7,10,11,13,14,16,17,19,20,21,25,26,27,29,30,38,39,40,42,45,47,48,52,53,55,58,59,61,62,63,64,65,66,67,75,85,86,87,90,91,93,94,95,97,99,105,118,119,120,121,122,123,124,129,172,174,180,181,182,184,185,186,188,189,190,191,198,200,214,223,229,231,233,239,240,241,267,278,284,285,286,289,291,298,300,301,302,303,305,308,312,313,315,318,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,446,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[28,-337,-128,-106,-104,-107,-105,-64,-60,-67,-66,-109,28,-65,-102,-337,-131,-108,-63,-129,28,-29,-62,-70,-52,-337,-337,-337,-130,28,-71,-103,-337,-9,-131,-91,-10,28,28,-53,-337,-88,28,28,-93,28,-335,28,-182,28,-87,-90,-94,-92,-61,-72,28,28,28,-73,28,-89,28,28,28,-159,-160,-156,-336,-183,-30,28,-74,28,28,28,28,-174,-175,28,28,-76,-79,-82,-75,-77,28,-81,-215,-214,-80,-216,-78,-127,28,28,-157,-69,-36,-35,28,28,28,-234,-233,28,-231,-217,-230,-81,-84,-218,-158,-31,-34,28,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'COLON':([2,3,5,6,12,22,23,33,34,36,39,42,43,44,46,48,49,50,54,56,58,60,73,74,76,77,86,96,98,100,101,111,127,132,133,134,136,138,139,140,141,142,143,144,145,147,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,178,179,187,191,192,200,216,224,225,230,232,234,235,236,237,238,240,241,261,263,268,269,272,273,275,279,280,295,310,312,314,316,317,324,328,340,341,355,356,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,407,411,431,442,443,445,448,449,453,454,464,465,468,476,478,480,482,483,486,487,511,512,518,519,524,547,551,565,],[-113,-128,-124,-110,-125,-120,-115,-238,-111,-122,-129,-29,-121,-116,-112,-52,-123,-117,-119,-114,-130,-118,-54,-179,-131,-37,-53,-147,-146,-167,-166,-126,-55,-317,-321,-318,-303,-324,-330,-313,-319,-144,-301,-274,-314,-142,-327,-325,-304,-322,-302,-255,-315,-289,-253,-328,-316,-329,-320,-276,-323,-312,-252,-178,-149,-336,319,-30,-38,-274,-239,-326,-280,-277,-334,-332,-331,-333,-174,-175,-298,-297,-279,-143,-235,-278,-140,-141,-145,429,440,-127,-153,-151,-148,447,-168,-36,-35,-44,-43,-261,-273,-262,-260,-264,-268,-263,-259,-266,-271,-257,-256,-265,-272,-267,-269,481,-270,-258,-296,-295,-294,-293,-292,-305,502,-152,-150,319,-170,-169,-31,-34,-39,-42,-240,-237,-281,-282,-290,-291,-236,-275,-33,-32,-41,-40,-254,-306,-299,-300,]),'$end':([0,9,14,16,17,19,25,38,45,47,57,59,61,119,123,124,180,191,223,332,439,510,],[-337,0,-64,-60,-67,-66,-65,-63,-62,-70,-59,-58,-71,-87,-61,-72,-73,-336,-74,-69,-218,-68,]),'WSTRING_LITERAL':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,139,146,148,149,150,151,153,163,165,166,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,235,236,237,238,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,148,-335,-28,-182,-27,148,-337,-87,-72,-337,148,-286,-285,-330,148,-327,148,-283,-287,237,-328,-288,-329,148,-284,148,148,148,-336,-183,148,148,-28,-337,148,-28,-337,-337,148,148,148,-334,-332,-331,-333,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,-337,-76,-79,-82,-75,148,-77,148,148,-81,-215,-214,-80,-216,148,-78,148,148,-69,-284,148,148,-284,148,148,-244,-247,-245,-241,-242,-246,-248,148,-250,-251,-243,-249,-12,148,148,-11,148,148,148,148,-234,-233,148,-231,148,148,-217,148,-230,148,-84,-218,148,148,148,-337,-337,-198,148,148,148,-337,-284,-229,-232,148,-221,148,-83,-219,-68,148,-28,-337,148,-11,148,148,-220,148,148,148,-284,148,148,148,-337,148,-225,-224,-222,-84,148,148,148,-226,-223,148,-228,-227,]),'DIVIDE':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-255,-315,-289,252,-328,-316,-329,-320,-276,-323,-312,-336,-274,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,252,252,252,252,252,252,252,252,252,252,-257,-256,252,252,252,252,252,-258,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'FOR':([61,97,119,124,181,191,284,285,286,289,291,298,300,301,302,303,305,307,308,332,424,425,428,429,432,435,437,438,439,440,496,497,500,502,505,506,510,535,536,537,539,554,555,557,558,569,574,575,576,577,578,579,],[-71,-335,-87,-72,292,-336,-76,-79,-82,-75,-77,292,-81,-215,-214,-80,-216,292,-78,-69,-234,-233,-231,292,-217,-230,292,-84,-218,292,-229,-232,-221,292,-83,-219,-68,292,-220,292,292,-225,-224,-222,-84,292,292,-226,-223,292,-228,-227,]),'PLUSPLUS':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,132,133,134,135,136,137,138,139,140,141,143,145,146,148,149,150,151,152,153,154,156,160,161,163,164,165,166,167,168,169,171,173,174,175,176,181,191,198,201,204,205,206,218,219,220,227,229,230,231,233,235,236,237,238,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,263,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,310,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,402,403,404,405,407,411,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,482,483,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,547,549,550,551,553,554,555,557,558,565,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,149,-335,-28,-182,-27,149,-337,-87,-72,-337,149,-317,-321,-318,-286,-303,-285,-324,-330,-313,-319,-301,-314,149,-327,149,-283,-287,-325,-304,-322,-302,-315,-289,-328,-316,-288,-329,-320,263,-323,149,-284,149,149,-312,149,-336,-183,149,149,-28,-337,149,-28,-337,-337,149,-326,149,149,-334,-332,-331,-333,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,-298,-297,149,149,-337,-76,-79,-82,-75,149,-77,149,149,-81,-215,-214,-80,-216,149,-78,-312,149,149,-69,-284,149,149,-284,149,149,-244,-247,-245,-241,-242,-246,-248,149,-250,-251,-243,-249,-12,149,149,-11,-296,-295,-294,-293,-292,-305,149,149,149,149,-234,-233,149,-231,149,149,-217,149,-230,149,-84,-218,149,149,149,-337,-337,-198,149,149,-290,-291,149,-337,-284,-229,-232,149,-221,149,-83,-219,-68,149,-28,-337,149,-11,149,149,-220,149,149,149,-284,149,149,-306,149,-337,-299,149,-225,-224,-222,-84,-300,149,149,149,-226,-223,149,-228,-227,]),'EQUALS':([42,48,73,74,75,77,78,86,110,127,132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,160,161,163,164,166,167,168,169,176,179,191,197,200,216,224,230,232,234,235,236,237,238,261,263,268,273,310,340,341,355,356,371,376,402,403,404,405,407,411,453,454,464,465,470,474,478,480,482,483,487,511,512,518,519,520,547,551,565,],[-29,-52,-54,-179,-178,-37,131,-53,201,-55,-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-315,-289,-328,-316,-329,-320,-276,-323,-312,-178,-336,329,-30,-38,360,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-36,-35,-44,-43,-199,475,-296,-295,-294,-293,-292,-305,-31,-34,-39,-42,-202,-200,-281,-282,-290,-291,-275,-33,-32,-41,-40,-201,-306,-299,-300,]),'ELSE':([61,124,191,284,285,286,289,291,300,303,308,332,424,425,428,435,437,438,439,496,497,500,505,506,510,536,554,555,557,558,575,576,578,579,],[-71,-72,-336,-76,-79,-82,-75,-77,-81,-80,-78,-69,-234,-233,-231,-230,-81,-84,-218,-229,-232,-221,-83,-219,-68,-220,-225,-224,-222,569,-226,-223,-228,-227,]),'ANDEQUAL':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,160,161,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-315,-289,-328,-316,-329,-320,-276,-323,-312,-336,365,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'EQ':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-255,-315,-289,256,-328,-316,-329,-320,-276,-323,-312,-336,-274,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-261,256,-262,-260,-264,-268,-263,-259,-266,256,-257,-256,-265,256,-267,256,256,-258,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'AND':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,132,133,134,135,136,137,138,139,140,141,143,144,145,146,148,149,150,151,152,153,154,156,158,160,161,162,163,164,165,166,167,168,169,171,173,174,175,176,181,191,198,201,204,205,206,218,219,220,224,227,229,230,231,232,233,234,235,236,237,238,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,263,265,266,268,273,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,310,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,478,480,481,482,483,484,487,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,547,549,550,551,553,554,555,557,558,565,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,150,-335,-28,-182,-27,150,-337,-87,-72,-337,150,-317,-321,-318,-286,-303,-285,-324,-330,-313,-319,-301,-274,-314,150,-327,150,-283,-287,-325,-304,-322,-302,-255,-315,-289,257,-328,-316,-288,-329,-320,-276,-323,150,-284,150,150,-312,150,-336,-183,150,150,-28,-337,150,-28,-337,-274,-337,150,-326,150,-280,150,-277,-334,-332,-331,-333,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,-298,-297,150,150,-279,-278,-337,-76,-79,-82,-75,150,-77,150,150,-81,-215,-214,-80,-216,150,-78,-312,150,150,-69,-284,150,150,-284,150,150,-244,-247,-245,-241,-242,-246,-248,150,-250,-251,-243,-249,-12,150,150,-11,-261,257,-262,-260,-264,-268,-263,-259,-266,257,-257,-256,-265,257,-267,-269,257,-258,-296,-295,-294,-293,-292,-305,150,150,150,150,-234,-233,150,-231,150,150,-217,150,-230,150,-84,-218,150,150,150,-337,-337,-198,150,-281,-282,150,-290,-291,150,-275,-337,-284,-229,-232,150,-221,150,-83,-219,-68,150,-28,-337,150,-11,150,150,-220,150,150,150,-284,150,150,-306,150,-337,-299,150,-225,-224,-222,-84,-300,150,150,150,-226,-223,150,-228,-227,]),'TYPEID':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,71,72,75,76,80,81,82,85,86,87,89,90,91,93,94,95,96,97,98,99,100,101,103,104,105,106,109,111,118,119,120,121,122,123,124,126,129,142,147,172,174,180,181,182,184,185,186,187,188,189,190,191,192,198,199,200,202,211,214,223,229,231,233,239,240,241,262,264,267,269,275,278,279,280,284,285,286,289,291,298,300,301,302,303,305,308,312,313,314,315,316,317,318,328,332,340,341,342,344,350,422,424,425,427,428,432,435,437,438,439,442,443,445,446,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[33,-337,-113,-128,77,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,33,-120,-115,-154,-65,-102,-126,-155,-131,-108,96,100,-238,-111,-337,-122,-63,-129,33,-29,-121,-116,-62,-112,-70,-52,-123,-117,-337,-337,-119,-337,-114,-130,33,-118,-71,-103,-337,-9,-131,-91,-10,-96,77,-98,77,33,-131,-95,-101,-97,33,-53,-126,77,-88,33,33,-93,33,-147,-335,-146,33,-167,-166,-28,-180,-182,-27,-100,-126,33,-87,-90,-94,-92,-61,-72,77,33,-144,-142,33,33,-73,33,-89,33,33,33,-149,-159,-160,-156,-336,77,-183,-181,-30,77,347,33,-74,33,33,33,33,-174,-175,402,404,33,-143,-140,33,-141,-145,-76,-79,-82,-75,-77,33,-81,-215,-214,-80,-216,-78,-127,33,-153,33,-151,-148,-157,-168,-69,-36,-35,33,347,33,33,-234,-233,33,-231,-217,-230,-81,-84,-218,-152,-150,77,-158,-170,-169,-31,-34,33,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'LBRACE':([21,24,28,31,32,42,48,61,75,86,88,90,92,93,96,97,98,100,101,119,124,130,131,181,182,191,200,201,227,229,284,285,286,289,291,298,300,301,302,303,305,307,308,332,340,341,369,375,377,413,424,425,428,429,432,435,437,438,439,440,453,454,472,475,477,478,479,488,496,497,500,502,505,506,510,511,512,521,522,535,536,537,539,550,554,555,557,558,569,574,575,576,577,578,579,],[-337,-154,-155,97,97,-29,-52,-71,-337,-53,-7,-88,97,-8,97,-335,97,97,97,-87,-72,97,97,97,-89,-336,-30,97,-337,97,-76,-79,-82,-75,-77,97,-81,-215,-214,-80,-216,97,-78,-69,-36,-35,-12,97,-11,97,-234,-233,-231,97,-217,-230,97,-84,-218,97,-31,-34,-337,-198,97,97,97,-337,-229,-232,-221,97,-83,-219,-68,-33,-32,97,-11,97,-220,97,97,-337,-225,-224,-222,-84,97,97,-226,-223,97,-228,-227,]),'PPHASH':([0,14,16,17,19,25,38,45,47,59,61,119,123,124,180,191,223,332,439,510,],[47,-64,-60,-67,-66,-65,-63,-62,-70,47,-71,-87,-61,-72,-73,-336,-74,-69,-218,-68,]),'INT':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,40,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,71,75,76,80,81,82,85,86,87,89,90,91,93,94,95,96,97,98,99,100,101,105,109,111,118,119,120,121,122,123,124,129,142,147,172,174,177,180,181,182,184,185,186,187,188,189,190,191,192,198,200,211,214,223,229,231,233,239,240,241,267,269,275,278,279,280,284,285,286,289,291,298,300,301,302,303,305,308,312,313,314,315,316,317,318,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,446,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[56,-337,-113,-128,56,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,56,-120,-115,-65,-102,-126,-131,-108,-238,-111,-122,-63,-129,56,-29,-121,-116,-62,-112,-70,-52,-123,-117,-337,-337,-119,-337,-114,-130,56,-118,-71,-103,-337,-9,-131,-91,-10,-96,-98,56,-131,-95,-101,-97,56,-53,-126,56,-88,56,56,-93,56,-147,-335,-146,56,-167,-166,-182,-100,-126,56,-87,-90,-94,-92,-61,-72,56,-144,-142,56,56,56,-73,56,-89,56,56,56,-149,-159,-160,-156,-336,56,-183,-30,56,56,-74,56,56,56,56,-174,-175,56,-143,-140,56,-141,-145,-76,-79,-82,-75,-77,56,-81,-215,-214,-80,-216,-78,-127,56,-153,56,-151,-148,-157,-168,-69,-36,-35,56,56,56,-234,-233,56,-231,-217,-230,-81,-84,-218,-152,-150,-158,-170,-169,-31,-34,56,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'SIGNED':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,40,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,71,75,76,80,81,82,85,86,87,89,90,91,93,94,95,96,97,98,99,100,101,105,109,111,118,119,120,121,122,123,124,129,142,147,172,174,177,180,181,182,184,185,186,187,188,189,190,191,192,198,200,211,214,223,229,231,233,239,240,241,267,269,275,278,279,280,284,285,286,289,291,298,300,301,302,303,305,308,312,313,314,315,316,317,318,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,446,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[54,-337,-113,-128,54,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,54,-120,-115,-65,-102,-126,-131,-108,-238,-111,-122,-63,-129,54,-29,-121,-116,-62,-112,-70,-52,-123,-117,-337,-337,-119,-337,-114,-130,54,-118,-71,-103,-337,-9,-131,-91,-10,-96,-98,54,-131,-95,-101,-97,54,-53,-126,54,-88,54,54,-93,54,-147,-335,-146,54,-167,-166,-182,-100,-126,54,-87,-90,-94,-92,-61,-72,54,-144,-142,54,54,54,-73,54,-89,54,54,54,-149,-159,-160,-156,-336,54,-183,-30,54,54,-74,54,54,54,54,-174,-175,54,-143,-140,54,-141,-145,-76,-79,-82,-75,-77,54,-81,-215,-214,-80,-216,-78,-127,54,-153,54,-151,-148,-157,-168,-69,-36,-35,54,54,54,-234,-233,54,-231,-217,-230,-81,-84,-218,-152,-150,-158,-170,-169,-31,-34,54,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'CONTINUE':([61,97,119,124,181,191,284,285,286,289,291,298,300,301,302,303,305,307,308,332,424,425,428,429,432,435,437,438,439,440,496,497,500,502,505,506,510,535,536,537,539,554,555,557,558,569,574,575,576,577,578,579,],[-71,-335,-87,-72,293,-336,-76,-79,-82,-75,-77,293,-81,-215,-214,-80,-216,293,-78,-69,-234,-233,-231,293,-217,-230,293,-84,-218,293,-229,-232,-221,293,-83,-219,-68,293,-220,293,293,-225,-224,-222,-84,293,293,-226,-223,293,-228,-227,]),'NOT':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,146,149,150,151,165,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,151,-335,-28,-182,-27,151,-337,-87,-72,-337,151,-286,-285,151,151,-283,-287,-288,151,-284,151,151,151,-336,-183,151,151,-28,-337,151,-28,-337,-337,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,-337,-76,-79,-82,-75,151,-77,151,151,-81,-215,-214,-80,-216,151,-78,151,151,-69,-284,151,151,-284,151,151,-244,-247,-245,-241,-242,-246,-248,151,-250,-251,-243,-249,-12,151,151,-11,151,151,151,151,-234,-233,151,-231,151,151,-217,151,-230,151,-84,-218,151,151,151,-337,-337,-198,151,151,151,-337,-284,-229,-232,151,-221,151,-83,-219,-68,151,-28,-337,151,-11,151,151,-220,151,151,151,-284,151,151,151,-337,151,-225,-224,-222,-84,151,151,151,-226,-223,151,-228,-227,]),'OREQUAL':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,160,161,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-315,-289,-328,-316,-329,-320,-276,-323,-312,-336,366,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'MOD':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-255,-315,-289,260,-328,-316,-329,-320,-276,-323,-312,-336,-274,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,260,260,260,260,260,260,260,260,260,260,-257,-256,260,260,260,260,260,-258,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'RSHIFT':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-255,-315,-289,242,-328,-316,-329,-320,-276,-323,-312,-336,-274,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-261,242,-262,-260,242,242,242,-259,242,242,-257,-256,242,242,242,242,242,-258,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'DEFAULT':([61,97,119,124,181,191,284,285,286,289,291,298,300,301,302,303,305,307,308,332,424,425,428,429,432,435,437,438,439,440,496,497,500,502,505,506,510,535,536,537,539,554,555,557,558,569,574,575,576,577,578,579,],[-71,-335,-87,-72,295,-336,-76,-79,-82,-75,-77,295,-81,-215,-214,-80,-216,295,-78,-69,-234,-233,-231,295,-217,-230,295,-84,-218,295,-229,-232,-221,295,-83,-219,-68,295,-220,295,295,-225,-224,-222,-84,295,295,-226,-223,295,-228,-227,]),'_NORETURN':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,65,68,71,75,76,80,81,82,86,87,89,90,93,96,97,98,100,101,109,111,118,119,123,124,129,180,181,182,187,191,200,211,223,240,241,278,284,285,286,289,291,298,300,301,302,303,305,308,312,314,316,317,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[20,20,-113,-128,20,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,20,-120,-115,-65,-102,20,-131,-108,-238,-111,-122,-63,-129,-29,-121,-116,-62,-112,-70,-52,-123,-117,20,20,-119,20,-114,-130,20,-118,-71,-103,20,-131,-96,-98,20,-131,-95,-101,-97,-53,20,20,-88,20,-147,-335,-146,-167,-166,-100,-126,20,-87,-61,-72,20,-73,20,-89,-149,-336,-30,20,-74,-174,-175,20,-76,-79,-82,-75,-77,20,-81,-215,-214,-80,-216,-78,-127,-153,-151,-148,-168,-69,-36,-35,20,20,20,-234,-233,20,-231,-217,-230,-81,-84,-218,-152,-150,-170,-169,-31,-34,20,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'__INT128':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,40,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,71,75,76,80,81,82,85,86,87,89,90,91,93,94,95,96,97,98,99,100,101,105,109,111,118,119,120,121,122,123,124,129,142,147,172,174,177,180,181,182,184,185,186,187,188,189,190,191,192,198,200,211,214,223,229,231,233,239,240,241,267,269,275,278,279,280,284,285,286,289,291,298,300,301,302,303,305,308,312,313,314,315,316,317,318,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,446,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[43,-337,-113,-128,43,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,43,-120,-115,-65,-102,-126,-131,-108,-238,-111,-122,-63,-129,43,-29,-121,-116,-62,-112,-70,-52,-123,-117,-337,-337,-119,-337,-114,-130,43,-118,-71,-103,-337,-9,-131,-91,-10,-96,-98,43,-131,-95,-101,-97,43,-53,-126,43,-88,43,43,-93,43,-147,-335,-146,43,-167,-166,-182,-100,-126,43,-87,-90,-94,-92,-61,-72,43,-144,-142,43,43,43,-73,43,-89,43,43,43,-149,-159,-160,-156,-336,43,-183,-30,43,43,-74,43,43,43,43,-174,-175,43,-143,-140,43,-141,-145,-76,-79,-82,-75,-77,43,-81,-215,-214,-80,-216,-78,-127,43,-153,43,-151,-148,-157,-168,-69,-36,-35,43,43,43,-234,-233,43,-231,-217,-230,-81,-84,-218,-152,-150,-158,-170,-169,-31,-34,43,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'WHILE':([61,97,119,124,181,191,284,285,286,289,291,298,300,301,302,303,305,307,308,332,424,425,428,429,432,435,436,437,438,439,440,496,497,500,502,505,506,510,535,536,537,539,554,555,557,558,569,574,575,576,577,578,579,],[-71,-335,-87,-72,296,-336,-76,-79,-82,-75,-77,296,-81,-215,-214,-80,-216,296,-78,-69,-234,-233,-231,296,-217,-230,504,296,-84,-218,296,-229,-232,-221,296,-83,-219,-68,296,-220,296,296,-225,-224,-222,-84,296,296,-226,-223,296,-228,-227,]),'U8CHAR_CONST':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,146,149,150,151,165,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,154,-335,-28,-182,-27,154,-337,-87,-72,-337,154,-286,-285,154,154,-283,-287,-288,154,-284,154,154,154,-336,-183,154,154,-28,-337,154,-28,-337,-337,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,-337,-76,-79,-82,-75,154,-77,154,154,-81,-215,-214,-80,-216,154,-78,154,154,-69,-284,154,154,-284,154,154,-244,-247,-245,-241,-242,-246,-248,154,-250,-251,-243,-249,-12,154,154,-11,154,154,154,154,-234,-233,154,-231,154,154,-217,154,-230,154,-84,-218,154,154,154,-337,-337,-198,154,154,154,-337,-284,-229,-232,154,-221,154,-83,-219,-68,154,-28,-337,154,-11,154,154,-220,154,154,154,-284,154,154,154,-337,154,-225,-224,-222,-84,154,154,154,-226,-223,154,-228,-227,]),'_ALIGNOF':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,146,149,150,151,165,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,155,-335,-28,-182,-27,155,-337,-87,-72,-337,155,-286,-285,155,155,-283,-287,-288,155,-284,155,155,155,-336,-183,155,155,-28,-337,155,-28,-337,-337,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,-337,-76,-79,-82,-75,155,-77,155,155,-81,-215,-214,-80,-216,155,-78,155,155,-69,-284,155,155,-284,155,155,-244,-247,-245,-241,-242,-246,-248,155,-250,-251,-243,-249,-12,155,155,-11,155,155,155,155,-234,-233,155,-231,155,155,-217,155,-230,155,-84,-218,155,155,155,-337,-337,-198,155,155,155,-337,-284,-229,-232,155,-221,155,-83,-219,-68,155,-28,-337,155,-11,155,155,-220,155,155,155,-284,155,155,155,-337,155,-225,-224,-222,-84,155,155,155,-226,-223,155,-228,-227,]),'EXTERN':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,65,68,71,75,76,80,81,82,86,87,89,90,93,96,97,98,100,101,109,111,118,119,123,124,129,180,181,182,187,191,200,211,223,240,241,278,284,285,286,289,291,298,300,301,302,303,305,308,312,314,316,317,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[13,13,-113,-128,13,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,13,-120,-115,-65,-102,13,-131,-108,-238,-111,-122,-63,-129,-29,-121,-116,-62,-112,-70,-52,-123,-117,13,13,-119,13,-114,-130,13,-118,-71,-103,13,-131,-96,-98,13,-131,-95,-101,-97,-53,13,13,-88,13,-147,-335,-146,-167,-166,-100,-126,13,-87,-61,-72,13,-73,13,-89,-149,-336,-30,13,-74,-174,-175,13,-76,-79,-82,-75,-77,13,-81,-215,-214,-80,-216,-78,-127,-153,-151,-148,-168,-69,-36,-35,13,13,13,-234,-233,13,-231,-217,-230,-81,-84,-218,-152,-150,-170,-169,-31,-34,13,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'CASE':([61,97,119,124,181,191,284,285,286,289,291,298,300,301,302,303,305,307,308,332,424,425,428,429,432,435,437,438,439,440,496,497,500,502,505,506,510,535,536,537,539,554,555,557,558,569,574,575,576,577,578,579,],[-71,-335,-87,-72,297,-336,-76,-79,-82,-75,-77,297,-81,-215,-214,-80,-216,297,-78,-69,-234,-233,-231,297,-217,-230,297,-84,-218,297,-229,-232,-221,297,-83,-219,-68,297,-220,297,297,-225,-224,-222,-84,297,297,-226,-223,297,-228,-227,]),'LAND':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-255,-315,-289,255,-328,-316,-329,-320,-276,-323,-312,-336,-274,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-261,255,-262,-260,-264,-268,-263,-259,-266,-271,-257,-256,-265,-272,-267,-269,-270,-258,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'REGISTER':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,65,68,71,75,76,80,81,82,86,87,89,90,93,96,97,98,100,101,109,111,118,119,123,124,129,180,181,182,187,191,200,211,223,240,241,278,284,285,286,289,291,298,300,301,302,303,305,308,312,314,316,317,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[62,62,-113,-128,62,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,62,-120,-115,-65,-102,62,-131,-108,-238,-111,-122,-63,-129,-29,-121,-116,-62,-112,-70,-52,-123,-117,62,62,-119,62,-114,-130,62,-118,-71,-103,62,-131,-96,-98,62,-131,-95,-101,-97,-53,62,62,-88,62,-147,-335,-146,-167,-166,-100,-126,62,-87,-61,-72,62,-73,62,-89,-149,-336,-30,62,-74,-174,-175,62,-76,-79,-82,-75,-77,62,-81,-215,-214,-80,-216,-78,-127,-153,-151,-148,-168,-69,-36,-35,62,62,62,-234,-233,62,-231,-217,-230,-81,-84,-218,-152,-150,-170,-169,-31,-34,62,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'MODEQUAL':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,160,161,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-315,-289,-328,-316,-329,-320,-276,-323,-312,-336,359,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'NE':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-255,-315,-289,247,-328,-316,-329,-320,-276,-323,-312,-336,-274,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-261,247,-262,-260,-264,-268,-263,-259,-266,247,-257,-256,-265,247,-267,247,247,-258,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'SWITCH':([61,97,119,124,181,191,284,285,286,289,291,298,300,301,302,303,305,307,308,332,424,425,428,429,432,435,437,438,439,440,496,497,500,502,505,506,510,535,536,537,539,554,555,557,558,569,574,575,576,577,578,579,],[-71,-335,-87,-72,299,-336,-76,-79,-82,-75,-77,299,-81,-215,-214,-80,-216,299,-78,-69,-234,-233,-231,299,-217,-230,299,-84,-218,299,-229,-232,-221,299,-83,-219,-68,299,-220,299,299,-225,-224,-222,-84,299,299,-226,-223,299,-228,-227,]),'INT_CONST_HEX':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,146,149,150,151,165,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,160,-335,-28,-182,-27,160,-337,-87,-72,-337,160,-286,-285,160,160,-283,-287,-288,160,-284,160,160,160,-336,-183,160,160,-28,-337,160,-28,-337,-337,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,-337,-76,-79,-82,-75,160,-77,160,160,-81,-215,-214,-80,-216,160,-78,160,160,-69,-284,160,160,-284,160,160,-244,-247,-245,-241,-242,-246,-248,160,-250,-251,-243,-249,-12,160,160,-11,160,160,160,160,-234,-233,160,-231,160,160,-217,160,-230,160,-84,-218,160,160,160,-337,-337,-198,160,160,160,-337,-284,-229,-232,160,-221,160,-83,-219,-68,160,-28,-337,160,-11,160,160,-220,160,160,160,-284,160,160,160,-337,160,-225,-224,-222,-84,160,160,160,-226,-223,160,-228,-227,]),'_COMPLEX':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,40,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,71,75,76,80,81,82,85,86,87,89,90,91,93,94,95,96,97,98,99,100,101,105,109,111,118,119,120,121,122,123,124,129,142,147,172,174,177,180,181,182,184,185,186,187,188,189,190,191,192,198,200,211,214,223,229,231,233,239,240,241,267,269,275,278,279,280,284,285,286,289,291,298,300,301,302,303,305,308,312,313,314,315,316,317,318,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,446,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[60,-337,-113,-128,60,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,60,-120,-115,-65,-102,-126,-131,-108,-238,-111,-122,-63,-129,60,-29,-121,-116,-62,-112,-70,-52,-123,-117,-337,-337,-119,-337,-114,-130,60,-118,-71,-103,-337,-9,-131,-91,-10,-96,-98,60,-131,-95,-101,-97,60,-53,-126,60,-88,60,60,-93,60,-147,-335,-146,60,-167,-166,-182,-100,-126,60,-87,-90,-94,-92,-61,-72,60,-144,-142,60,60,60,-73,60,-89,60,60,60,-149,-159,-160,-156,-336,60,-183,-30,60,60,-74,60,60,60,60,-174,-175,60,-143,-140,60,-141,-145,-76,-79,-82,-75,-77,60,-81,-215,-214,-80,-216,-78,-127,60,-153,60,-151,-148,-157,-168,-69,-36,-35,60,60,60,-234,-233,60,-231,-217,-230,-81,-84,-218,-152,-150,-158,-170,-169,-31,-34,60,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'PPPRAGMASTR':([61,],[124,]),'PLUSEQUAL':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,160,161,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-315,-289,-328,-316,-329,-320,-276,-323,-312,-336,362,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'U32CHAR_CONST':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,146,149,150,151,165,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,138,-335,-28,-182,-27,138,-337,-87,-72,-337,138,-286,-285,138,138,-283,-287,-288,138,-284,138,138,138,-336,-183,138,138,-28,-337,138,-28,-337,-337,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,-337,-76,-79,-82,-75,138,-77,138,138,-81,-215,-214,-80,-216,138,-78,138,138,-69,-284,138,138,-284,138,138,-244,-247,-245,-241,-242,-246,-248,138,-250,-251,-243,-249,-12,138,138,-11,138,138,138,138,-234,-233,138,-231,138,138,-217,138,-230,138,-84,-218,138,138,138,-337,-337,-198,138,138,138,-337,-284,-229,-232,138,-221,138,-83,-219,-68,138,-28,-337,138,-11,138,138,-220,138,138,138,-284,138,138,138,-337,138,-225,-224,-222,-84,138,138,138,-226,-223,138,-228,-227,]),'CONDOP':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-255,-315,-289,258,-328,-316,-329,-320,-276,-323,-312,-336,-274,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-261,-273,-262,-260,-264,-268,-263,-259,-266,-271,-257,-256,-265,-272,-267,-269,-270,-258,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'U8STRING_LITERAL':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,139,146,148,149,150,151,153,163,165,166,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,235,236,237,238,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,163,-335,-28,-182,-27,163,-337,-87,-72,-337,163,-286,-285,-330,163,-327,163,-283,-287,236,-328,-288,-329,163,-284,163,163,163,-336,-183,163,163,-28,-337,163,-28,-337,-337,163,163,163,-334,-332,-331,-333,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-337,-76,-79,-82,-75,163,-77,163,163,-81,-215,-214,-80,-216,163,-78,163,163,-69,-284,163,163,-284,163,163,-244,-247,-245,-241,-242,-246,-248,163,-250,-251,-243,-249,-12,163,163,-11,163,163,163,163,-234,-233,163,-231,163,163,-217,163,-230,163,-84,-218,163,163,163,-337,-337,-198,163,163,163,-337,-284,-229,-232,163,-221,163,-83,-219,-68,163,-28,-337,163,-11,163,163,-220,163,163,163,-284,163,163,163,-337,163,-225,-224,-222,-84,163,163,163,-226,-223,163,-228,-227,]),'BREAK':([61,97,119,124,181,191,284,285,286,289,291,298,300,301,302,303,305,307,308,332,424,425,428,429,432,435,437,438,439,440,496,497,500,502,505,506,510,535,536,537,539,554,555,557,558,569,574,575,576,577,578,579,],[-71,-335,-87,-72,304,-336,-76,-79,-82,-75,-77,304,-81,-215,-214,-80,-216,304,-78,-69,-234,-233,-231,304,-217,-230,304,-84,-218,304,-229,-232,-221,304,-83,-219,-68,304,-220,304,304,-225,-224,-222,-84,304,304,-226,-223,304,-228,-227,]),'VOLATILE':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,35,36,38,39,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,65,68,71,75,76,80,81,82,85,86,87,89,90,93,95,96,97,98,99,100,101,103,105,109,111,117,118,119,123,124,128,129,142,147,172,174,177,180,181,182,184,185,186,187,188,189,190,191,192,198,200,205,206,211,219,220,223,229,231,233,239,240,241,267,269,275,278,279,280,282,284,285,286,289,291,298,300,301,302,303,305,308,312,313,314,315,316,317,318,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,446,448,449,453,454,459,460,496,497,500,505,506,510,511,512,514,515,536,554,555,557,558,575,576,578,579,],[58,58,-113,-128,58,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,58,-120,-115,-65,-102,58,-131,-108,-238,-111,58,-122,-63,-129,-29,-121,-116,-62,-112,-70,-52,-123,-117,58,58,-119,58,-114,-130,58,-118,-71,-103,58,-131,-96,-98,58,-131,-95,-101,-97,58,-53,58,58,-88,58,58,-147,-335,-146,58,-167,-166,58,-182,-100,-126,58,58,-87,-61,-72,58,58,-144,-142,58,58,58,-73,58,-89,58,58,58,-149,-159,-160,-156,-336,58,-183,-30,58,58,58,58,58,-74,58,58,58,58,-174,-175,58,-143,-140,58,-141,-145,58,-76,-79,-82,-75,-77,58,-81,-215,-214,-80,-216,-78,-127,58,-153,58,-151,-148,-157,-168,-69,-36,-35,58,58,58,-234,-233,58,-231,-217,-230,-81,-84,-218,-152,-150,-158,-170,-169,-31,-34,58,58,-229,-232,-221,-83,-219,-68,-33,-32,58,58,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'PPPRAGMA':([0,14,16,17,19,25,38,45,47,59,61,97,99,119,123,124,180,181,184,185,186,188,189,190,191,223,284,285,286,289,291,298,300,301,302,303,305,307,308,313,315,318,332,424,425,428,429,432,435,437,438,439,440,446,496,497,500,502,505,506,510,535,536,537,539,554,555,557,558,569,574,575,576,577,578,579,],[61,-64,-60,-67,-66,-65,-63,-62,-70,61,-71,-335,61,-87,-61,-72,-73,61,61,61,61,-159,-160,-156,-336,-74,-76,-79,-82,-75,-77,61,-81,-215,-214,-80,-216,61,-78,61,61,-157,-69,-234,-233,-231,61,-217,-230,61,-84,-218,61,-158,-229,-232,-221,61,-83,-219,-68,61,-220,61,61,-225,-224,-222,-84,61,61,-226,-223,61,-228,-227,]),'INLINE':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,65,68,71,75,76,80,81,82,86,87,89,90,93,96,97,98,100,101,109,111,118,119,123,124,129,180,181,182,187,191,200,211,223,240,241,278,284,285,286,289,291,298,300,301,302,303,305,308,312,314,316,317,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[30,30,-113,-128,30,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,30,-120,-115,-65,-102,30,-131,-108,-238,-111,-122,-63,-129,-29,-121,-116,-62,-112,-70,-52,-123,-117,30,30,-119,30,-114,-130,30,-118,-71,-103,30,-131,-96,-98,30,-131,-95,-101,-97,-53,30,30,-88,30,-147,-335,-146,-167,-166,-100,-126,30,-87,-61,-72,30,-73,30,-89,-149,-336,-30,30,-74,-174,-175,30,-76,-79,-82,-75,-77,30,-81,-215,-214,-80,-216,-78,-127,-153,-151,-148,-168,-69,-36,-35,30,30,30,-234,-233,30,-231,-217,-230,-81,-84,-218,-152,-150,-170,-169,-31,-34,30,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'INT_CONST_BIN':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,146,149,150,151,165,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,164,-335,-28,-182,-27,164,-337,-87,-72,-337,164,-286,-285,164,164,-283,-287,-288,164,-284,164,164,164,-336,-183,164,164,-28,-337,164,-28,-337,-337,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,-337,-76,-79,-82,-75,164,-77,164,164,-81,-215,-214,-80,-216,164,-78,164,164,-69,-284,164,164,-284,164,164,-244,-247,-245,-241,-242,-246,-248,164,-250,-251,-243,-249,-12,164,164,-11,164,164,164,164,-234,-233,164,-231,164,164,-217,164,-230,164,-84,-218,164,164,164,-337,-337,-198,164,164,164,-337,-284,-229,-232,164,-221,164,-83,-219,-68,164,-28,-337,164,-11,164,164,-220,164,164,164,-284,164,164,164,-337,164,-225,-224,-222,-84,164,164,164,-226,-223,164,-228,-227,]),'DO':([61,97,119,124,181,191,284,285,286,289,291,298,300,301,302,303,305,307,308,332,424,425,428,429,432,435,437,438,439,440,496,497,500,502,505,506,510,535,536,537,539,554,555,557,558,569,574,575,576,577,578,579,],[-71,-335,-87,-72,307,-336,-76,-79,-82,-75,-77,307,-81,-215,-214,-80,-216,307,-78,-69,-234,-233,-231,307,-217,-230,307,-84,-218,307,-229,-232,-221,307,-83,-219,-68,307,-220,307,307,-225,-224,-222,-84,307,307,-226,-223,307,-228,-227,]),'LNOT':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,146,149,150,151,165,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,165,-335,-28,-182,-27,165,-337,-87,-72,-337,165,-286,-285,165,165,-283,-287,-288,165,-284,165,165,165,-336,-183,165,165,-28,-337,165,-28,-337,-337,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,-337,-76,-79,-82,-75,165,-77,165,165,-81,-215,-214,-80,-216,165,-78,165,165,-69,-284,165,165,-284,165,165,-244,-247,-245,-241,-242,-246,-248,165,-250,-251,-243,-249,-12,165,165,-11,165,165,165,165,-234,-233,165,-231,165,165,-217,165,-230,165,-84,-218,165,165,165,-337,-337,-198,165,165,165,-337,-284,-229,-232,165,-221,165,-83,-219,-68,165,-28,-337,165,-11,165,165,-220,165,165,165,-284,165,165,165,-337,165,-225,-224,-222,-84,165,165,165,-226,-223,165,-228,-227,]),'CONST':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,35,36,38,39,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,65,68,71,75,76,80,81,82,85,86,87,89,90,93,95,96,97,98,99,100,101,103,105,109,111,117,118,119,123,124,128,129,142,147,172,174,177,180,181,182,184,185,186,187,188,189,190,191,192,198,200,205,206,211,219,220,223,229,231,233,239,240,241,267,269,275,278,279,280,282,284,285,286,289,291,298,300,301,302,303,305,308,312,313,314,315,316,317,318,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,446,448,449,453,454,459,460,496,497,500,505,506,510,511,512,514,515,536,554,555,557,558,575,576,578,579,],[3,3,-113,-128,3,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,3,-120,-115,-65,-102,3,-131,-108,-238,-111,3,-122,-63,-129,-29,-121,-116,-62,-112,-70,-52,-123,-117,3,3,-119,3,-114,-130,3,-118,-71,-103,3,-131,-96,-98,3,-131,-95,-101,-97,3,-53,3,3,-88,3,3,-147,-335,-146,3,-167,-166,3,-182,-100,-126,3,3,-87,-61,-72,3,3,-144,-142,3,3,3,-73,3,-89,3,3,3,-149,-159,-160,-156,-336,3,-183,-30,3,3,3,3,3,-74,3,3,3,3,-174,-175,3,-143,-140,3,-141,-145,3,-76,-79,-82,-75,-77,3,-81,-215,-214,-80,-216,-78,-127,3,-153,3,-151,-148,-157,-168,-69,-36,-35,3,3,3,-234,-233,3,-231,-217,-230,-81,-84,-218,-152,-150,-158,-170,-169,-31,-34,3,3,-229,-232,-221,-83,-219,-68,-33,-32,3,3,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'LSHIFT':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-255,-315,-289,244,-328,-316,-329,-320,-276,-323,-312,-336,-274,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-261,244,-262,-260,244,244,244,-259,244,244,-257,-256,244,244,244,244,244,-258,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'LOR':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-255,-315,-289,243,-328,-316,-329,-320,-276,-323,-312,-336,-274,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-261,-273,-262,-260,-264,-268,-263,-259,-266,-271,-257,-256,-265,-272,-267,-269,-270,-258,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'CHAR_CONST':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,146,149,150,151,165,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,167,-335,-28,-182,-27,167,-337,-87,-72,-337,167,-286,-285,167,167,-283,-287,-288,167,-284,167,167,167,-336,-183,167,167,-28,-337,167,-28,-337,-337,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,-337,-76,-79,-82,-75,167,-77,167,167,-81,-215,-214,-80,-216,167,-78,167,167,-69,-284,167,167,-284,167,167,-244,-247,-245,-241,-242,-246,-248,167,-250,-251,-243,-249,-12,167,167,-11,167,167,167,167,-234,-233,167,-231,167,167,-217,167,-230,167,-84,-218,167,167,167,-337,-337,-198,167,167,167,-337,-284,-229,-232,167,-221,167,-83,-219,-68,167,-28,-337,167,-11,167,167,-220,167,167,167,-284,167,167,167,-337,167,-225,-224,-222,-84,167,167,167,-226,-223,167,-228,-227,]),'U16STRING_LITERAL':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,139,146,148,149,150,151,153,163,165,166,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,235,236,237,238,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,166,-335,-28,-182,-27,166,-337,-87,-72,-337,166,-286,-285,-330,166,-327,166,-283,-287,238,-328,-288,-329,166,-284,166,166,166,-336,-183,166,166,-28,-337,166,-28,-337,-337,166,166,166,-334,-332,-331,-333,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,-337,-76,-79,-82,-75,166,-77,166,166,-81,-215,-214,-80,-216,166,-78,166,166,-69,-284,166,166,-284,166,166,-244,-247,-245,-241,-242,-246,-248,166,-250,-251,-243,-249,-12,166,166,-11,166,166,166,166,-234,-233,166,-231,166,166,-217,166,-230,166,-84,-218,166,166,166,-337,-337,-198,166,166,166,-337,-284,-229,-232,166,-221,166,-83,-219,-68,166,-28,-337,166,-11,166,166,-220,166,166,166,-284,166,166,166,-337,166,-225,-224,-222,-84,166,166,166,-226,-223,166,-228,-227,]),'RBRACE':([61,97,99,119,124,132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,178,181,184,185,186,188,189,190,191,195,196,197,224,225,227,228,230,232,234,235,236,237,238,261,263,268,273,284,285,286,289,291,298,300,301,302,303,305,306,308,309,313,315,318,325,326,327,332,370,374,377,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,424,425,428,432,435,437,438,439,446,450,451,468,469,472,473,476,478,480,482,483,487,496,497,500,505,506,510,523,524,528,536,546,547,550,551,554,555,557,558,565,575,576,578,579,],[-71,-335,191,-87,-72,-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-255,-315,-289,-253,-328,-316,-329,-320,-276,-323,-312,-252,-337,191,191,191,-159,-160,-156,-336,-171,191,-176,-274,-239,-337,-193,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-76,-79,-82,-75,-77,-6,-81,-215,-214,-80,-216,-5,-78,191,191,191,-157,191,191,-172,-69,191,-22,-21,-261,-273,-262,-260,-264,-268,-263,-259,-266,-271,-257,-256,-265,-272,-267,-269,-270,-258,-296,-295,-294,-293,-292,-305,-234,-233,-231,-217,-230,-81,-84,-218,-158,-173,-177,-240,-194,191,-196,-237,-281,-282,-290,-291,-275,-229,-232,-221,-83,-219,-68,-195,-254,191,-220,-197,-306,191,-299,-225,-224,-222,-84,-300,-226,-223,-228,-227,]),'_BOOL':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,40,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,71,75,76,80,81,82,85,86,87,89,90,91,93,94,95,96,97,98,99,100,101,105,109,111,118,119,120,121,122,123,124,129,142,147,172,174,177,180,181,182,184,185,186,187,188,189,190,191,192,198,200,211,214,223,229,231,233,239,240,241,267,269,275,278,279,280,284,285,286,289,291,298,300,301,302,303,305,308,312,313,314,315,316,317,318,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,446,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[34,-337,-113,-128,34,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,34,-120,-115,-65,-102,-126,-131,-108,-238,-111,-122,-63,-129,34,-29,-121,-116,-62,-112,-70,-52,-123,-117,-337,-337,-119,-337,-114,-130,34,-118,-71,-103,-337,-9,-131,-91,-10,-96,-98,34,-131,-95,-101,-97,34,-53,-126,34,-88,34,34,-93,34,-147,-335,-146,34,-167,-166,-182,-100,-126,34,-87,-90,-94,-92,-61,-72,34,-144,-142,34,34,34,-73,34,-89,34,34,34,-149,-159,-160,-156,-336,34,-183,-30,34,34,-74,34,34,34,34,-174,-175,34,-143,-140,34,-141,-145,-76,-79,-82,-75,-77,34,-81,-215,-214,-80,-216,-78,-127,34,-153,34,-151,-148,-157,-168,-69,-36,-35,34,34,34,-234,-233,34,-231,-217,-230,-81,-84,-218,-152,-150,-158,-170,-169,-31,-34,34,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'LE':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-255,-315,-289,246,-328,-316,-329,-320,-276,-323,-312,-336,-274,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-261,246,-262,-260,-264,246,-263,-259,-266,246,-257,-256,-265,246,246,246,246,-258,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'SEMI':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,22,23,25,26,27,29,30,33,34,36,38,39,40,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,70,71,73,74,75,76,77,78,79,80,81,82,83,84,86,87,89,91,94,96,97,98,99,100,101,108,109,110,111,113,114,115,119,120,121,122,123,124,127,132,133,134,136,138,139,140,141,142,143,144,145,147,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,178,179,180,181,184,185,186,187,188,189,190,191,192,200,216,217,223,224,225,226,228,230,232,234,235,236,237,238,240,241,261,263,268,269,272,273,275,279,280,284,285,286,288,289,290,291,293,294,298,300,301,302,303,304,305,306,307,308,310,312,313,314,315,316,317,318,320,321,322,323,324,328,330,331,332,340,341,355,356,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,423,424,425,426,427,428,429,432,433,435,437,438,439,440,442,443,444,446,448,449,453,454,464,465,468,469,476,478,480,482,483,486,487,496,497,498,499,500,502,505,506,508,509,510,511,512,518,519,523,524,533,534,535,536,537,539,547,551,552,554,555,557,558,565,568,569,574,575,576,577,578,579,],[19,-337,-113,-128,-337,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,-120,-115,-65,-102,-126,-131,-108,-238,-111,-122,-63,-129,-337,-29,-121,-116,-62,-112,-70,-52,-123,-117,119,-337,-337,-119,-337,-114,-130,19,-118,-71,-103,-337,-9,-131,-91,-10,-96,-20,-98,-54,-179,-178,-131,-37,-134,-85,-95,-101,-97,-19,-132,-53,-126,-337,-337,-93,-147,-335,-146,188,-167,-166,-136,-100,-138,-126,-16,-86,-15,-87,-90,-94,-92,-61,-72,-55,-317,-321,-318,-303,-324,-330,-313,-319,-144,-301,-274,-314,-142,-327,-325,-304,-322,-302,-255,-315,-289,-253,-328,-316,-329,-320,-276,-323,-312,-252,-178,-73,-337,188,188,188,-149,-159,-160,-156,-336,-337,-30,-38,-133,-74,-274,-239,-135,-193,-326,-280,-277,-334,-332,-331,-333,-174,-175,-298,-297,-279,-143,-235,-278,-140,-141,-145,-76,-79,-82,424,-75,425,-77,428,-14,-337,-81,-215,-214,-80,435,-216,-13,-337,-78,-312,-127,188,-153,188,-151,-148,-157,-26,-25,446,-161,-163,-168,-139,-137,-69,-36,-35,-44,-43,-261,-273,-262,-260,-264,-268,-263,-259,-266,-271,-257,-256,-265,-272,-267,-269,-270,-258,-296,-295,-294,-293,-292,-305,496,-234,-233,497,-337,-231,-337,-217,-13,-230,-81,-84,-218,-337,-152,-150,-165,-158,-170,-169,-31,-34,-39,-42,-240,-194,-237,-281,-282,-290,-291,-236,-275,-229,-232,533,-337,-221,-337,-83,-219,-162,-164,-68,-33,-32,-41,-40,-195,-254,-337,553,-337,-220,-337,-337,-306,-299,566,-225,-224,-222,-84,-300,575,-337,-337,-226,-223,-337,-228,-227,]),'_THREAD_LOCAL':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,65,68,71,75,76,80,81,82,86,87,89,90,93,96,97,98,100,101,109,111,118,119,123,124,129,180,181,182,187,191,200,211,223,240,241,278,284,285,286,289,291,298,300,301,302,303,305,308,312,314,316,317,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[11,11,-113,-128,11,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,11,-120,-115,-65,-102,11,-131,-108,-238,-111,-122,-63,-129,-29,-121,-116,-62,-112,-70,-52,-123,-117,11,11,-119,11,-114,-130,11,-118,-71,-103,11,-131,-96,-98,11,-131,-95,-101,-97,-53,11,11,-88,11,-147,-335,-146,-167,-166,-100,-126,11,-87,-61,-72,11,-73,11,-89,-149,-336,-30,11,-74,-174,-175,11,-76,-79,-82,-75,-77,11,-81,-215,-214,-80,-216,-78,-127,-153,-151,-148,-168,-69,-36,-35,11,11,11,-234,-233,11,-231,-217,-230,-81,-84,-218,-152,-150,-170,-169,-31,-34,11,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'LT':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-255,-315,-289,248,-328,-316,-329,-320,-276,-323,-312,-336,-274,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-261,248,-262,-260,-264,248,-263,-259,-266,248,-257,-256,-265,248,248,248,248,-258,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'COMMA':([2,3,5,6,7,10,11,12,13,18,20,22,23,26,27,30,33,34,35,36,39,42,43,44,46,48,49,50,54,56,58,60,62,68,70,71,73,74,75,76,77,78,80,81,82,84,86,96,98,100,101,103,104,105,106,108,109,110,111,113,127,132,133,134,136,138,139,140,141,142,143,144,145,147,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,177,178,179,187,191,195,196,197,198,199,200,203,210,211,212,213,215,216,217,224,225,226,228,230,232,234,235,236,237,238,240,241,261,263,268,269,270,272,273,274,275,276,277,279,280,281,283,294,310,312,314,316,317,320,323,324,325,326,327,328,330,331,340,341,343,344,345,346,347,348,355,356,374,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,414,426,442,443,444,448,449,450,451,453,454,458,461,463,464,465,468,469,473,476,478,480,482,483,486,487,489,490,492,501,503,507,508,509,511,512,518,519,523,524,525,528,529,530,531,532,544,545,546,547,551,556,559,560,564,565,570,571,],[-113,-128,-124,-110,-106,-104,-107,-125,-105,-99,-109,-120,-115,-102,-126,-108,-238,-111,-337,-122,-129,-29,-121,-116,-112,-52,-123,-117,-119,-114,-130,-118,-103,-96,126,-98,-54,-179,-178,-131,-37,-134,-95,-101,-97,-132,-53,-147,-146,-167,-166,-28,-180,-182,-27,-136,-100,-138,-126,202,-55,-317,-321,-318,-303,-324,-330,-313,-319,-144,-301,-274,-314,-142,-327,-325,-304,-322,-302,-255,-315,-289,-253,-328,-316,-329,-320,-276,-323,-312,-337,-252,-178,-149,-336,-171,327,-176,-183,-181,-30,333,-186,-337,349,350,-191,-38,-133,-274,-239,-135,-193,-326,-280,-277,-334,-332,-331,-333,-174,-175,-298,-297,-279,-143,412,-235,-278,-203,-140,-204,-1,-141,-145,-2,-206,412,-312,-127,-153,-151,-148,445,-161,-163,327,327,-172,-168,-139,-137,-36,-35,-190,-204,-56,-188,-45,-189,-44,-43,472,-261,-273,-262,-260,-264,-268,-263,-259,-266,-271,-257,-256,-265,-272,-267,-269,412,-270,-258,-296,-295,-294,-293,412,-292,-310,484,485,-305,-205,412,-152,-150,-165,-170,-169,-173,-177,-31,-34,-57,-192,-187,-39,-42,-240,-194,-196,-237,-281,-282,-290,-291,-236,-275,-213,-207,-211,412,412,412,-162,-164,-33,-32,-41,-40,-195,-254,-311,550,-209,-208,-210,-212,-51,-50,-197,-306,-299,412,-46,-49,412,-300,-48,-47,]),'U16CHAR_CONST':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,146,149,150,151,165,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,169,-335,-28,-182,-27,169,-337,-87,-72,-337,169,-286,-285,169,169,-283,-287,-288,169,-284,169,169,169,-336,-183,169,169,-28,-337,169,-28,-337,-337,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,-337,-76,-79,-82,-75,169,-77,169,169,-81,-215,-214,-80,-216,169,-78,169,169,-69,-284,169,169,-284,169,169,-244,-247,-245,-241,-242,-246,-248,169,-250,-251,-243,-249,-12,169,169,-11,169,169,169,169,-234,-233,169,-231,169,169,-217,169,-230,169,-84,-218,169,169,169,-337,-337,-198,169,169,169,-337,-284,-229,-232,169,-221,169,-83,-219,-68,169,-28,-337,169,-11,169,169,-220,169,169,169,-284,169,169,169,-337,169,-225,-224,-222,-84,169,169,169,-226,-223,169,-228,-227,]),'OFFSETOF':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,137,146,149,150,151,165,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,170,-335,-28,-182,-27,170,-337,-87,-72,-337,170,-286,-285,170,170,-283,-287,-288,170,-284,170,170,170,-336,-183,170,170,-28,-337,170,-28,-337,-337,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,-337,-76,-79,-82,-75,170,-77,170,170,-81,-215,-214,-80,-216,170,-78,170,170,-69,-284,170,170,-284,170,170,-244,-247,-245,-241,-242,-246,-248,170,-250,-251,-243,-249,-12,170,170,-11,170,170,170,170,-234,-233,170,-231,170,170,-217,170,-230,170,-84,-218,170,170,170,-337,-337,-198,170,170,170,-337,-284,-229,-232,170,-221,170,-83,-219,-68,170,-28,-337,170,-11,170,170,-220,170,170,170,-284,170,170,170,-337,170,-225,-224,-222,-84,170,170,170,-226,-223,170,-228,-227,]),'_ATOMIC':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,35,36,38,39,40,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,71,75,76,80,81,82,85,86,87,89,90,91,93,94,95,96,97,98,99,100,101,103,105,109,111,117,118,119,120,121,122,123,124,128,129,142,147,172,174,177,180,181,182,184,185,186,187,188,189,190,191,192,198,200,205,206,211,214,219,220,223,229,231,233,239,240,241,267,269,275,278,279,280,282,284,285,286,289,291,298,300,301,302,303,305,308,312,313,314,315,316,317,318,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,446,448,449,453,454,459,460,496,497,500,505,506,510,511,512,514,515,536,554,555,557,558,575,576,578,579,],[29,65,-113,-128,76,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,65,-120,-115,-65,-102,65,-131,-108,-238,-111,76,-122,-63,-129,112,-29,-121,-116,-62,-112,-70,-52,-123,-117,65,65,-119,65,-114,-130,29,-118,-71,-103,65,-9,-131,-91,-10,-96,-98,65,-131,-95,-101,-97,29,-53,65,76,-88,112,65,-93,29,-147,-335,-146,29,-167,-166,76,-182,-100,-126,76,29,-87,-90,-94,-92,-61,-72,76,29,-144,-142,65,29,76,-73,65,-89,29,29,29,-149,-159,-160,-156,-336,76,-183,-30,76,76,76,112,76,76,-74,29,29,29,29,-174,-175,29,-143,-140,29,-141,-145,76,-76,-79,-82,-75,-77,65,-81,-215,-214,-80,-216,-78,-127,29,-153,29,-151,-148,-157,-168,-69,-36,-35,29,29,29,-234,-233,65,-231,-217,-230,-81,-84,-218,-152,-150,-158,-170,-169,-31,-34,76,29,-229,-232,-221,-83,-219,-68,-33,-32,76,76,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'TYPEDEF':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,65,68,71,75,76,80,81,82,86,87,89,90,93,96,97,98,100,101,109,111,118,119,123,124,129,180,181,182,187,191,200,211,223,240,241,278,284,285,286,289,291,298,300,301,302,303,305,308,312,314,316,317,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[7,7,-113,-128,7,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,7,-120,-115,-65,-102,7,-131,-108,-238,-111,-122,-63,-129,-29,-121,-116,-62,-112,-70,-52,-123,-117,7,7,-119,7,-114,-130,7,-118,-71,-103,7,-131,-96,-98,7,-131,-95,-101,-97,-53,7,7,-88,7,-147,-335,-146,-167,-166,-100,-126,7,-87,-61,-72,7,-73,7,-89,-149,-336,-30,7,-74,-174,-175,7,-76,-79,-82,-75,-77,7,-81,-215,-214,-80,-216,-78,-127,-153,-151,-148,-168,-69,-36,-35,7,7,7,-234,-233,7,-231,-217,-230,-81,-84,-218,-152,-150,-170,-169,-31,-34,7,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'XOR':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-255,-315,-289,251,-328,-316,-329,-320,-276,-323,-312,-336,-274,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-261,251,-262,-260,-264,-268,-263,-259,-266,-271,-257,-256,-265,251,-267,-269,251,-258,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'AUTO':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,65,68,71,75,76,80,81,82,86,87,89,90,93,96,97,98,100,101,109,111,118,119,123,124,129,180,181,182,187,191,200,211,223,240,241,278,284,285,286,289,291,298,300,301,302,303,305,308,312,314,316,317,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[26,26,-113,-128,26,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,26,-120,-115,-65,-102,26,-131,-108,-238,-111,-122,-63,-129,-29,-121,-116,-62,-112,-70,-52,-123,-117,26,26,-119,26,-114,-130,26,-118,-71,-103,26,-131,-96,-98,26,-131,-95,-101,-97,-53,26,26,-88,26,-147,-335,-146,-167,-166,-100,-126,26,-87,-61,-72,26,-73,26,-89,-149,-336,-30,26,-74,-174,-175,26,-76,-79,-82,-75,-77,26,-81,-215,-214,-80,-216,-78,-127,-153,-151,-148,-168,-69,-36,-35,26,26,26,-234,-233,26,-231,-217,-230,-81,-84,-218,-152,-150,-170,-169,-31,-34,26,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'DIVEQUAL':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,160,161,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-315,-289,-328,-316,-329,-320,-276,-323,-312,-336,357,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'TIMES':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,22,23,25,26,27,29,30,33,34,35,36,37,38,39,40,43,44,45,46,47,49,50,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,71,76,80,81,82,85,87,89,91,94,96,97,98,100,101,103,104,105,106,109,111,116,117,119,120,121,122,123,124,126,128,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,156,158,160,161,162,163,164,165,166,167,168,169,171,173,174,175,176,177,180,181,187,191,192,198,201,202,204,205,206,211,218,219,220,223,224,227,229,230,231,232,233,234,235,236,237,238,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,263,265,266,268,269,273,275,278,279,280,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,310,312,314,316,317,319,328,329,332,336,338,339,342,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,407,411,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,442,443,445,447,448,449,459,472,475,477,478,480,481,482,483,484,487,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,547,549,550,551,553,554,555,557,558,565,566,569,574,575,576,577,578,579,],[35,-337,-113,-128,35,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,-120,-115,-65,-102,-126,-131,-108,-238,-111,-337,-122,35,-63,-129,35,-121,-116,-62,-112,-70,-123,-117,-337,-337,-119,-337,-114,-130,35,-118,-71,-103,-337,-9,-131,-91,-10,-96,35,-98,-131,-95,-101,-97,173,-126,35,35,-93,-147,-335,-146,-167,-166,-28,35,-182,-27,-100,-126,173,-337,-87,-90,-94,-92,-61,-72,35,-337,173,-317,-321,-318,-286,-303,-285,-324,-330,-313,-319,-144,-301,-274,-314,173,-142,-327,173,-283,-287,-325,-304,-322,-302,-255,-315,-289,253,-328,-316,-288,-329,-320,-276,-323,173,-284,173,173,-312,35,-73,173,-149,-336,35,-183,173,35,336,-28,-337,35,352,-28,-337,-74,-274,-337,173,-326,173,-280,173,-277,-334,-332,-331,-333,-174,-175,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,-298,-297,173,173,-279,-143,-278,-140,35,-141,-145,420,-76,-79,-82,-75,173,-77,173,173,-81,-215,-214,-80,-216,173,-78,-312,-127,-153,-151,-148,173,-168,173,-69,-284,173,173,35,-284,173,173,-244,-247,-245,-241,-242,-246,-248,173,-250,-251,-243,-249,-12,173,173,-11,253,253,253,253,253,253,253,253,253,253,-257,-256,253,253,253,253,253,-258,-296,-295,-294,-293,-292,-305,173,173,173,494,-234,-233,173,-231,173,173,-217,173,-230,173,-84,-218,173,173,-152,-150,35,173,-170,-169,-337,-337,-198,173,-281,-282,173,-290,-291,173,-275,-337,-284,-229,-232,173,-221,173,-83,-219,-68,541,-28,-337,173,-11,173,173,-220,173,173,173,-284,173,173,-306,173,-337,-299,173,-225,-224,-222,-84,-300,173,173,173,-226,-223,173,-228,-227,]),'LPAREN':([0,1,2,3,4,5,6,7,8,10,11,12,13,14,15,16,17,18,19,20,22,23,25,26,27,29,30,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,71,72,73,76,77,80,81,82,85,86,87,89,91,94,96,97,98,100,101,103,104,105,106,109,111,112,116,117,119,120,121,122,123,124,126,127,128,131,132,133,134,135,136,137,138,139,140,141,142,143,145,146,147,148,149,150,151,152,153,154,155,156,160,161,163,164,165,166,167,168,169,170,171,173,174,175,176,177,180,181,187,191,192,198,199,200,201,202,204,205,206,211,216,218,219,220,223,227,229,230,231,233,235,236,237,238,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,263,265,266,269,275,276,278,279,280,282,283,284,285,286,289,290,291,292,296,297,298,299,300,301,302,303,305,307,308,310,311,312,314,316,317,319,328,329,332,336,338,339,340,341,342,344,345,347,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,402,403,404,405,407,411,412,413,414,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,442,443,445,447,448,449,453,454,457,458,459,464,465,472,475,477,481,482,483,484,488,489,490,492,494,496,497,499,500,502,504,505,506,510,511,512,513,514,515,518,519,521,522,529,530,531,532,533,535,536,537,538,539,541,542,543,544,545,547,549,550,551,553,554,555,557,558,559,560,565,566,569,570,571,574,575,576,577,578,579,],[37,-337,-113,-128,69,-124,-110,-106,85,-104,-107,-125,-105,-64,37,-60,-67,-99,-66,-109,-120,-115,-65,-102,-126,95,-108,-238,-111,-337,-122,37,-63,-129,37,116,-29,-121,-116,-62,-112,-70,118,-123,-117,-337,-337,-119,-337,-114,-130,37,-118,-71,-103,-337,-9,95,-91,-10,-96,69,-98,69,129,-131,-37,-95,-101,-97,174,118,-126,69,37,-93,-147,-335,-146,-167,-166,-28,-180,-182,-27,-100,-126,95,174,-337,-87,-90,-94,-92,-61,-72,69,129,-337,229,-317,-321,-318,-286,-303,-285,-324,-330,-313,-319,-144,-301,-314,231,-142,-327,233,-283,-287,-325,-304,-322,239,-302,-315,-289,-328,-316,-288,-329,-320,266,-323,267,174,-284,229,233,-312,278,-73,229,-149,-336,69,-183,-181,-30,229,69,229,-28,-337,342,-38,229,-28,-337,-74,-337,229,-326,229,229,-334,-332,-331,-333,-174,-175,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,229,174,174,-298,-297,229,229,-143,-140,278,278,-141,-145,-337,422,-76,-79,-82,-75,229,-77,427,430,174,229,434,-81,-215,-214,-80,-216,229,-78,-312,441,-127,-153,-151,-148,174,-168,174,-69,-284,229,229,-36,-35,342,342,460,-45,-284,229,229,-44,-43,-244,-247,-245,-241,-242,-246,-248,229,-250,-251,-243,-249,-12,174,229,-11,-296,-295,-294,-293,-292,-305,229,174,422,229,229,-234,-233,229,-231,229,229,-217,229,-230,229,-84,-218,229,229,-152,-150,69,174,-170,-169,-31,-34,342,460,-337,-39,-42,-337,-198,174,174,-290,-291,229,-337,-213,-207,-211,-284,-229,-232,229,-221,229,538,-83,-219,-68,-33,-32,229,-28,-337,-41,-40,229,-11,-209,-208,-210,-212,229,229,-220,229,229,229,-284,229,229,-51,-50,-306,229,-337,-299,229,-225,-224,-222,-84,-46,-49,-300,229,229,-48,-47,229,-226,-223,229,-228,-227,]),'MINUSMINUS':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,132,133,134,135,136,137,138,139,140,141,143,145,146,148,149,150,151,152,153,154,156,160,161,163,164,165,166,167,168,169,171,173,174,175,176,181,191,198,201,204,205,206,218,219,220,227,229,230,231,233,235,236,237,238,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,263,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,310,319,329,332,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,402,403,404,405,407,411,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,459,472,475,477,481,482,483,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,547,549,550,551,553,554,555,557,558,565,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,175,-335,-28,-182,-27,175,-337,-87,-72,-337,175,-317,-321,-318,-286,-303,-285,-324,-330,-313,-319,-301,-314,175,-327,175,-283,-287,-325,-304,-322,-302,-315,-289,-328,-316,-288,-329,-320,261,-323,175,-284,175,175,-312,175,-336,-183,175,175,-28,-337,175,-28,-337,-337,175,-326,175,175,-334,-332,-331,-333,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,-298,-297,175,175,-337,-76,-79,-82,-75,175,-77,175,175,-81,-215,-214,-80,-216,175,-78,-312,175,175,-69,-284,175,175,-284,175,175,-244,-247,-245,-241,-242,-246,-248,175,-250,-251,-243,-249,-12,175,175,-11,-296,-295,-294,-293,-292,-305,175,175,175,175,-234,-233,175,-231,175,175,-217,175,-230,175,-84,-218,175,175,175,-337,-337,-198,175,175,-290,-291,175,-337,-284,-229,-232,175,-221,175,-83,-219,-68,175,-28,-337,175,-11,175,175,-220,175,175,175,-284,175,175,-306,175,-337,-299,175,-225,-224,-222,-84,-300,175,175,175,-226,-223,175,-228,-227,]),'ID':([0,1,2,3,4,5,6,7,10,11,12,13,14,15,16,17,18,19,20,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,43,44,45,46,47,49,50,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,71,72,76,80,81,82,85,87,89,91,94,96,97,98,100,101,102,103,104,105,106,109,111,116,117,118,119,120,121,122,123,124,126,128,129,131,135,137,142,146,147,149,150,151,165,171,173,174,175,180,181,187,191,192,193,194,198,199,201,202,204,205,206,211,218,219,220,223,227,229,231,233,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,262,264,265,266,269,275,279,280,282,284,285,286,287,289,290,291,297,298,300,301,302,303,305,307,308,312,314,316,317,319,327,328,329,332,336,338,339,342,344,349,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,372,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,442,443,445,447,448,449,457,459,460,472,475,477,481,484,485,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,548,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[42,-337,-113,-128,42,-124,-110,-106,-104,-107,-125,-105,-64,42,-60,-67,-99,-66,-109,-120,-115,-154,-65,-102,-126,-155,-131,-108,98,101,-238,-111,-337,-122,42,-63,-129,42,-121,-116,-62,-112,-70,-123,-117,-337,-337,-119,-337,-114,-130,42,-118,-71,-103,-337,-9,-131,-91,-10,-96,42,-98,42,-131,-95,-101,-97,176,-126,42,42,-93,-147,-335,-146,-167,-166,197,-28,-180,-182,-27,-100,-126,176,-337,176,-87,-90,-94,-92,-61,-72,42,-337,176,176,-286,-285,-144,176,-142,176,-283,-287,-288,176,-284,176,176,-73,310,-149,-336,42,197,197,-183,-181,176,42,176,-28,-337,42,176,-28,-337,-74,-337,176,176,176,-174,-175,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,403,405,176,176,-143,-140,-141,-145,-337,-76,-79,-82,423,-75,176,-77,176,310,-81,-215,-214,-80,-216,310,-78,-127,-153,-151,-148,176,197,-168,176,-69,-284,176,176,42,42,176,-284,176,176,-244,-247,-245,-241,-242,-246,-248,176,-250,-251,-243,-249,-12,176,176,176,-11,176,176,176,176,-234,-233,176,-231,310,176,-217,176,-230,310,-84,-218,310,176,-152,-150,42,176,-170,-169,42,-337,176,-337,-198,176,176,176,176,-337,-284,-229,-232,176,-221,310,-83,-219,-68,176,-28,-337,176,-11,176,310,-220,310,176,310,-284,176,176,176,176,-337,176,-225,-224,-222,-84,176,310,310,-226,-223,310,-228,-227,]),'IF':([61,97,119,124,181,191,284,285,286,289,291,298,300,301,302,303,305,307,308,332,424,425,428,429,432,435,437,438,439,440,496,497,500,502,505,506,510,535,536,537,539,554,555,557,558,569,574,575,576,577,578,579,],[-71,-335,-87,-72,311,-336,-76,-79,-82,-75,-77,311,-81,-215,-214,-80,-216,311,-78,-69,-234,-233,-231,311,-217,-230,311,-84,-218,311,-229,-232,-221,311,-83,-219,-68,311,-220,311,311,-225,-224,-222,-84,311,311,-226,-223,311,-228,-227,]),'STRING_LITERAL':([3,39,58,61,76,85,97,103,105,106,116,117,119,124,128,131,135,136,137,146,149,150,151,152,165,171,173,174,175,181,191,198,201,204,205,206,218,219,220,227,229,230,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,282,284,285,286,289,290,291,297,298,300,301,302,303,305,307,308,319,329,332,333,336,338,339,352,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,373,375,377,412,413,419,421,424,425,427,428,429,430,432,434,435,437,438,439,440,441,447,452,459,472,475,477,481,484,488,494,496,497,499,500,502,505,506,510,513,514,515,521,522,533,535,536,537,538,539,541,542,543,549,550,553,554,555,557,558,566,569,574,575,576,577,578,579,],[-128,-129,-130,-71,-131,152,-335,-28,-182,-27,152,-337,-87,-72,-337,152,-286,230,-285,152,152,-283,-287,-325,-288,152,-284,152,152,152,-336,-183,152,152,-28,-337,152,-28,-337,-337,152,-326,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,-337,-76,-79,-82,-75,152,-77,152,152,-81,-215,-214,-80,-216,152,-78,152,152,-69,152,-284,152,152,-284,152,152,-244,-247,-245,-241,-242,-246,-248,152,-250,-251,-243,-249,-12,152,152,-11,152,152,152,152,-234,-233,152,-231,152,152,-217,152,-230,152,-84,-218,152,152,152,230,-337,-337,-198,152,152,152,-337,-284,-229,-232,152,-221,152,-83,-219,-68,152,-28,-337,152,-11,152,152,-220,152,152,152,-284,152,152,152,-337,152,-225,-224,-222,-84,152,152,152,-226,-223,152,-228,-227,]),'FLOAT':([0,1,2,3,4,5,6,7,10,11,12,13,14,16,17,18,19,20,21,22,23,25,26,27,29,30,33,34,36,38,39,40,42,43,44,45,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,71,75,76,80,81,82,85,86,87,89,90,91,93,94,95,96,97,98,99,100,101,105,109,111,118,119,120,121,122,123,124,129,142,147,172,174,177,180,181,182,184,185,186,187,188,189,190,191,192,198,200,211,214,223,229,231,233,239,240,241,267,269,275,278,279,280,284,285,286,289,291,298,300,301,302,303,305,308,312,313,314,315,316,317,318,328,332,340,341,342,350,422,424,425,427,428,432,435,437,438,439,442,443,446,448,449,453,454,460,496,497,500,505,506,510,511,512,536,554,555,557,558,575,576,578,579,],[44,-337,-113,-128,44,-124,-110,-106,-104,-107,-125,-105,-64,-60,-67,-99,-66,-109,44,-120,-115,-65,-102,-126,-131,-108,-238,-111,-122,-63,-129,44,-29,-121,-116,-62,-112,-70,-52,-123,-117,-337,-337,-119,-337,-114,-130,44,-118,-71,-103,-337,-9,-131,-91,-10,-96,-98,44,-131,-95,-101,-97,44,-53,-126,44,-88,44,44,-93,44,-147,-335,-146,44,-167,-166,-182,-100,-126,44,-87,-90,-94,-92,-61,-72,44,-144,-142,44,44,44,-73,44,-89,44,44,44,-149,-159,-160,-156,-336,44,-183,-30,44,44,-74,44,44,44,44,-174,-175,44,-143,-140,44,-141,-145,-76,-79,-82,-75,-77,44,-81,-215,-214,-80,-216,-78,-127,44,-153,44,-151,-148,-157,-168,-69,-36,-35,44,44,44,-234,-233,44,-231,-217,-230,-81,-84,-218,-152,-150,-158,-170,-169,-31,-34,44,-229,-232,-221,-83,-219,-68,-33,-32,-220,-225,-224,-222,-84,-226,-223,-228,-227,]),'XOREQUAL':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,160,161,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-315,-289,-328,-316,-329,-320,-276,-323,-312,-336,361,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'LSHIFTEQUAL':([132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,160,161,163,164,166,167,168,169,176,191,224,230,232,234,235,236,237,238,261,263,268,273,310,402,403,404,405,407,411,478,480,482,483,487,547,551,565,],[-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-315,-289,-328,-316,-329,-320,-276,-323,-312,-336,363,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-278,-312,-296,-295,-294,-293,-292,-305,-281,-282,-290,-291,-275,-306,-299,-300,]),'RBRACKET':([3,39,58,76,103,105,106,117,128,132,133,134,136,138,139,140,141,143,144,145,148,152,153,154,156,158,160,161,162,163,164,166,167,168,169,176,178,191,198,204,205,218,219,224,225,230,232,234,235,236,237,238,261,263,268,272,273,282,334,335,336,337,351,352,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,406,407,411,419,420,421,455,456,459,466,467,468,471,476,478,480,482,483,486,487,491,493,494,513,514,524,540,541,547,551,561,562,564,565,],[-128,-129,-130,-131,-28,-182,-27,-337,-337,-317,-321,-318,-303,-324,-330,-313,-319,-301,-274,-314,-327,-325,-304,-322,-302,-255,-315,-289,-253,-328,-316,-329,-320,-276,-323,-312,-252,-336,-183,-337,-28,-337,-28,-274,-239,-326,-280,-277,-334,-332,-331,-333,-298,-297,-279,-235,-278,-337,453,-4,454,-3,464,465,-261,-273,-262,-260,-264,-268,-263,-259,-266,-271,-257,-256,-265,-272,-267,-269,-270,-258,-296,-295,-294,-293,482,-292,-305,-337,492,-337,511,512,-337,518,519,-240,520,-237,-281,-282,-290,-291,-236,-275,529,530,531,-337,-28,-254,559,560,-306,-299,570,571,572,-300,]),} + +_lr_action = {} +for _k, _v in _lr_action_items.items(): + for _x,_y in zip(_v[0],_v[1]): + if not _x in _lr_action: _lr_action[_x] = {} + _lr_action[_x][_k] = _y +del _lr_action_items + +_lr_goto_items = {'expression_statement':([181,298,307,429,437,440,502,535,537,539,569,574,577,],[284,284,284,284,284,284,284,284,284,284,284,284,284,]),'struct_or_union_specifier':([0,21,40,59,75,85,91,93,95,99,118,129,172,174,181,184,185,186,214,229,231,233,239,267,278,298,313,315,342,350,422,427,460,],[5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,]),'init_declarator_list':([4,89,],[70,70,]),'init_declarator_list_opt':([4,89,],[79,79,]),'iteration_statement':([181,298,307,429,437,440,502,535,537,539,569,574,577,],[285,285,285,285,285,285,285,285,285,285,285,285,285,]),'static_assert':([0,59,181,298,307,429,437,440,502,535,537,539,569,574,577,],[17,17,286,286,286,286,286,286,286,286,286,286,286,286,286,]),'unified_string_literal':([85,116,131,146,149,171,174,175,181,201,204,218,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,290,297,298,307,319,329,333,338,339,353,354,364,373,375,412,413,419,421,427,429,430,434,437,440,441,447,477,481,484,499,502,513,521,533,535,537,538,539,542,543,549,553,566,569,574,577,],[136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,452,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,]),'assignment_expression_opt':([204,218,419,421,513,],[334,351,491,493,540,]),'brace_open':([31,32,92,96,98,100,101,130,131,181,201,229,298,307,375,413,429,437,440,477,478,479,502,521,535,537,539,569,574,577,],[99,102,181,184,185,193,194,181,227,181,227,181,181,181,227,488,181,181,181,488,488,488,181,227,181,181,181,181,181,181,]),'enumerator':([102,193,194,327,],[195,195,195,450,]),'typeid_noparen_declarator':([211,],[348,]),'type_qualifier_list_opt':([35,117,128,206,220,282,459,515,],[104,204,218,339,354,419,513,543,]),'declaration_specifiers_no_type_opt':([1,27,52,53,55,63,87,],[66,94,120,121,122,94,94,]),'expression_opt':([181,298,307,427,429,437,440,499,502,533,535,537,539,553,566,569,574,577,],[288,288,288,498,288,288,288,534,288,552,288,288,288,567,573,288,288,288,]),'designation':([227,472,488,550,],[369,369,369,369,]),'parameter_list':([118,129,278,342,422,460,],[213,213,213,213,213,213,]),'alignment_specifier':([0,1,4,21,27,52,53,55,59,63,75,85,87,89,93,95,99,118,129,174,177,181,184,185,186,192,211,229,231,233,239,267,278,298,313,315,342,350,422,427,460,],[53,53,81,53,53,53,53,53,53,53,53,142,53,81,53,142,142,53,53,142,280,53,142,142,142,280,81,142,142,142,142,142,53,53,142,142,53,53,53,53,53,]),'labeled_statement':([181,298,307,429,437,440,502,535,537,539,569,574,577,],[289,289,289,289,289,289,289,289,289,289,289,289,289,]),'abstract_declarator':([177,211,278,342,],[281,281,418,418,]),'translation_unit':([0,],[59,]),'init_declarator':([4,89,126,202,],[84,84,217,331,]),'direct_abstract_declarator':([177,211,276,278,342,344,457,],[283,283,414,283,283,414,414,]),'designator_list':([227,472,488,550,],[376,376,376,376,]),'identifier':([85,116,118,129,131,146,149,171,174,175,181,201,204,218,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,290,297,298,307,319,329,338,339,349,353,354,364,372,373,375,412,413,419,421,427,429,430,434,437,440,441,447,460,477,481,484,485,499,502,513,521,533,535,537,538,539,542,543,548,549,553,566,569,574,577,],[143,143,215,215,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,461,143,143,143,470,143,143,143,143,143,143,143,143,143,143,143,143,143,143,215,143,143,143,527,143,143,143,143,143,143,143,143,143,143,143,563,143,143,143,143,143,143,]),'offsetof_member_designator':([485,],[526,]),'unary_expression':([85,116,131,146,149,171,174,175,181,201,204,218,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,290,297,298,307,319,329,338,339,353,354,364,373,375,412,413,419,421,427,429,430,434,437,440,441,447,477,481,484,499,502,513,521,533,535,537,538,539,542,543,549,553,566,569,574,577,],[144,144,224,232,234,144,224,273,224,224,224,224,224,224,224,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,224,144,144,224,224,224,144,224,224,144,144,224,224,224,224,224,144,224,224,144,224,224,224,224,224,224,224,224,224,144,144,144,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,]),'abstract_declarator_opt':([177,211,],[274,343,]),'initializer':([131,201,375,521,],[226,330,473,546,]),'direct_id_declarator':([0,4,15,37,40,59,69,72,89,91,126,192,202,211,342,344,445,457,],[48,48,86,48,48,48,48,86,48,48,48,48,48,48,48,86,48,86,]),'struct_declaration_list':([99,184,185,],[186,313,315,]),'pp_directive':([0,59,],[14,14,]),'declaration_list':([21,75,],[93,93,]),'id_init_declarator':([40,91,],[108,108,]),'type_specifier':([0,21,40,59,75,85,91,93,95,99,118,129,172,174,181,184,185,186,214,229,231,233,239,267,278,298,313,315,342,350,422,427,460,],[18,18,109,18,18,147,109,18,147,147,18,18,269,147,18,147,147,147,109,147,147,147,147,147,18,18,147,147,18,18,18,18,18,]),'compound_statement':([92,130,181,229,298,307,429,437,440,502,535,537,539,569,574,577,],[180,223,291,378,291,291,291,291,291,291,291,291,291,291,291,291,]),'pointer':([0,4,37,40,59,69,89,91,104,126,177,192,202,211,278,342,445,],[15,72,15,15,15,72,72,15,199,72,276,72,72,344,276,457,72,]),'typeid_declarator':([4,69,89,126,192,202,445,],[74,125,74,74,74,74,74,]),'id_init_declarator_list':([40,91,],[113,113,]),'declarator':([4,89,126,192,202,445,],[78,78,78,324,78,324,]),'argument_expression_list':([266,],[409,]),'struct_declarator_list_opt':([192,],[322,]),'block_item_list':([181,],[298,]),'parameter_type_list_opt':([278,342,422,],[417,417,495,]),'struct_declarator':([192,445,],[323,508,]),'type_qualifier':([0,1,4,21,27,35,52,53,55,59,63,75,85,87,89,93,95,99,103,117,118,128,129,172,174,177,181,184,185,186,192,205,206,211,219,220,229,231,233,239,267,278,282,298,313,315,342,350,422,427,459,460,514,515,],[52,52,80,52,52,105,52,52,52,52,52,52,105,52,80,52,105,105,198,105,52,105,52,198,105,279,52,105,105,105,279,198,105,80,198,105,105,105,105,105,105,52,105,52,105,105,52,52,52,52,105,52,198,105,]),'assignment_operator':([224,],[364,]),'expression':([174,181,229,231,233,258,265,290,298,307,427,429,430,434,437,440,441,499,502,533,535,537,538,539,549,553,566,569,574,577,],[270,294,270,270,270,399,406,426,294,294,294,294,501,503,294,294,507,294,294,294,294,294,556,294,564,294,294,294,294,294,]),'storage_class_specifier':([0,1,4,21,27,52,53,55,59,63,75,87,89,93,118,129,181,211,278,298,342,350,422,427,460,],[1,1,68,1,1,1,1,1,1,1,1,1,68,1,1,1,1,68,1,1,1,1,1,1,1,]),'unified_wstring_literal':([85,116,131,146,149,171,174,175,181,201,204,218,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,290,297,298,307,319,329,338,339,353,354,364,373,375,412,413,419,421,427,429,430,434,437,440,441,447,477,481,484,499,502,513,521,533,535,537,538,539,542,543,549,553,566,569,574,577,],[153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,]),'translation_unit_or_empty':([0,],[9,]),'initializer_list_opt':([227,],[370,]),'brace_close':([99,184,185,186,196,309,313,315,325,326,370,472,528,550,],[187,314,316,317,328,439,442,443,448,449,469,523,551,565,]),'direct_typeid_declarator':([4,69,72,89,126,192,202,445,],[73,73,127,73,73,73,73,73,]),'external_declaration':([0,59,],[16,123,]),'pragmacomp_or_statement':([307,429,440,502,535,537,539,569,574,577,],[436,500,506,536,554,555,557,576,578,579,]),'type_name':([85,95,174,229,231,233,239,267,],[157,183,271,379,380,381,382,410,]),'typedef_name':([0,21,40,59,75,85,91,93,95,99,118,129,172,174,181,184,185,186,214,229,231,233,239,267,278,298,313,315,342,350,422,427,460,],[36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,]),'pppragma_directive':([0,59,99,181,184,185,186,298,307,313,315,429,437,440,502,535,537,539,569,574,577,],[25,25,189,300,189,189,189,300,437,189,189,437,300,437,437,437,437,437,437,437,437,]),'statement':([181,298,307,429,437,440,502,535,537,539,569,574,577,],[301,301,438,438,505,438,438,438,438,558,438,438,438,]),'cast_expression':([85,116,131,171,174,181,201,204,218,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,290,297,298,307,319,329,338,339,353,354,364,373,375,412,413,419,421,427,429,430,434,437,440,441,447,477,481,484,499,502,513,521,533,535,537,538,539,542,543,549,553,566,569,574,577,],[158,158,158,268,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,487,158,158,158,158,158,158,158,158,158,158,487,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,]),'atomic_specifier':([0,1,21,27,40,52,53,55,59,63,75,85,87,91,93,95,99,118,129,172,174,181,184,185,186,214,229,231,233,239,267,278,298,313,315,342,350,422,427,460,],[27,63,87,63,111,63,63,63,27,63,87,111,63,111,87,111,111,27,27,111,111,87,111,111,111,111,111,111,111,111,111,27,87,111,111,27,27,27,87,27,]),'struct_declarator_list':([192,],[320,]),'empty':([0,1,4,21,27,35,40,52,53,55,63,75,87,89,91,117,118,128,129,177,181,192,204,206,211,218,220,227,278,282,298,307,342,419,421,422,427,429,437,440,459,460,472,488,499,502,513,515,533,535,537,539,550,553,566,569,574,577,],[57,64,83,88,64,106,115,64,64,64,64,88,64,83,115,106,208,106,208,277,306,321,337,106,277,337,106,377,415,106,433,433,415,337,337,415,433,433,433,433,106,208,522,522,433,433,337,106,433,433,433,433,522,433,433,433,433,433,]),'parameter_declaration':([118,129,278,342,350,422,460,],[210,210,210,210,463,210,210,]),'primary_expression':([85,116,131,146,149,171,174,175,181,201,204,218,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,290,297,298,307,319,329,338,339,353,354,364,373,375,412,413,419,421,427,429,430,434,437,440,441,447,477,481,484,499,502,513,521,533,535,537,538,539,542,543,549,553,566,569,574,577,],[161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,]),'declaration':([0,21,59,75,93,181,298,427,],[38,90,38,90,182,302,302,499,]),'declaration_specifiers_no_type':([0,1,21,27,52,53,55,59,63,75,87,93,118,129,181,278,298,342,350,422,427,460,],[40,67,91,67,67,67,67,40,67,91,67,91,214,214,91,214,91,214,214,214,91,214,]),'jump_statement':([181,298,307,429,437,440,502,535,537,539,569,574,577,],[303,303,303,303,303,303,303,303,303,303,303,303,303,]),'enumerator_list':([102,193,194,],[196,325,326,]),'block_item':([181,298,],[305,432,]),'constant_expression':([85,116,297,319,329,373,447,],[159,203,431,444,451,471,509,]),'identifier_list_opt':([118,129,460,],[207,221,516,]),'constant':([85,116,131,146,149,171,174,175,181,201,204,218,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,290,297,298,307,319,329,338,339,353,354,364,373,375,412,413,419,421,427,429,430,434,437,440,441,447,477,481,484,499,502,513,521,533,535,537,538,539,542,543,549,553,566,569,574,577,],[156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,]),'type_specifier_no_typeid':([0,4,21,40,59,75,85,89,91,93,95,99,118,129,172,174,177,181,184,185,186,192,211,214,229,231,233,239,267,278,298,313,315,342,350,422,427,460,],[12,71,12,12,12,12,12,71,12,12,12,12,12,12,12,12,275,12,12,12,12,275,71,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,]),'struct_declaration':([99,184,185,186,313,315,],[190,190,190,318,318,318,]),'direct_typeid_noparen_declarator':([211,344,],[345,458,]),'id_declarator':([0,4,37,40,59,69,89,91,126,192,202,211,342,445,],[21,75,107,110,21,107,179,110,179,179,179,346,107,179,]),'selection_statement':([181,298,307,429,437,440,502,535,537,539,569,574,577,],[308,308,308,308,308,308,308,308,308,308,308,308,308,]),'postfix_expression':([85,116,131,146,149,171,174,175,181,201,204,218,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,290,297,298,307,319,329,338,339,353,354,364,373,375,412,413,419,421,427,429,430,434,437,440,441,447,477,481,484,499,502,513,521,533,535,537,538,539,542,543,549,553,566,569,574,577,],[168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,]),'initializer_list':([227,488,],[374,528,]),'unary_operator':([85,116,131,146,149,171,174,175,181,201,204,218,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,290,297,298,307,319,329,338,339,353,354,364,373,375,412,413,419,421,427,429,430,434,437,440,441,447,477,481,484,499,502,513,521,533,535,537,538,539,542,543,549,553,566,569,574,577,],[171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,]),'struct_or_union':([0,21,40,59,75,85,91,93,95,99,118,129,172,174,181,184,185,186,214,229,231,233,239,267,278,298,313,315,342,350,422,427,460,],[31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,]),'block_item_list_opt':([181,],[309,]),'assignment_expression':([131,174,181,201,204,218,229,231,233,258,265,266,290,298,307,338,339,353,354,364,375,412,419,421,427,429,430,434,437,440,441,484,499,502,513,521,533,535,537,538,539,542,543,549,553,566,569,574,577,],[228,272,272,228,335,335,272,272,272,272,272,408,272,272,272,455,456,466,467,468,228,486,335,335,272,272,272,272,272,272,272,525,272,272,335,228,272,272,272,272,272,561,562,272,272,272,272,272,272,]),'designation_opt':([227,472,488,550,],[375,521,375,521,]),'parameter_type_list':([118,129,278,342,422,460,],[209,222,416,416,416,517,]),'type_qualifier_list':([35,85,95,99,117,128,174,184,185,186,206,220,229,231,233,239,267,282,313,315,459,515,],[103,172,172,172,205,219,172,172,172,172,103,103,172,172,172,172,172,103,172,172,514,103,]),'designator':([227,376,472,488,550,],[371,474,371,371,371,]),'id_init_declarator_list_opt':([40,91,],[114,114,]),'declaration_specifiers':([0,21,59,75,93,118,129,181,278,298,342,350,422,427,460,],[4,89,4,89,89,211,211,89,211,89,211,211,211,89,211,]),'identifier_list':([118,129,460,],[212,212,212,]),'declaration_list_opt':([21,75,],[92,130,]),'function_definition':([0,59,],[45,45,]),'binary_expression':([85,116,131,174,181,201,204,218,229,231,233,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,265,266,290,297,298,307,319,329,338,339,353,354,364,373,375,412,419,421,427,429,430,434,437,440,441,447,481,484,499,502,513,521,533,535,537,538,539,542,543,549,553,566,569,574,577,],[162,162,162,162,162,162,162,162,162,162,162,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,162,400,401,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,]),'enum_specifier':([0,21,40,59,75,85,91,93,95,99,118,129,172,174,181,184,185,186,214,229,231,233,239,267,278,298,313,315,342,350,422,427,460,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'decl_body':([0,21,59,75,93,181,298,427,],[51,51,51,51,51,51,51,51,]),'function_specifier':([0,1,4,21,27,52,53,55,59,63,75,87,89,93,118,129,181,211,278,298,342,350,422,427,460,],[55,55,82,55,55,55,55,55,55,55,55,55,82,55,55,55,55,82,55,55,55,55,55,55,55,]),'specifier_qualifier_list':([85,95,99,174,184,185,186,229,231,233,239,267,313,315,],[177,177,192,177,192,192,192,177,177,177,177,177,192,192,]),'conditional_expression':([85,116,131,174,181,201,204,218,229,231,233,258,265,266,290,297,298,307,319,329,338,339,353,354,364,373,375,412,419,421,427,429,430,434,437,440,441,447,481,484,499,502,513,521,533,535,537,538,539,542,543,549,553,566,569,574,577,],[178,178,225,225,225,225,225,225,225,225,225,225,225,225,225,178,225,225,178,178,225,225,225,225,225,178,225,225,225,225,225,225,225,225,225,225,225,178,524,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,]),} + +_lr_goto = {} +for _k, _v in _lr_goto_items.items(): + for _x, _y in zip(_v[0], _v[1]): + if not _x in _lr_goto: _lr_goto[_x] = {} + _lr_goto[_x][_k] = _y +del _lr_goto_items +_lr_productions = [ + ("S' -> translation_unit_or_empty","S'",1,None,None,None), + ('abstract_declarator_opt -> empty','abstract_declarator_opt',1,'p_abstract_declarator_opt','plyparser.py',43), + ('abstract_declarator_opt -> abstract_declarator','abstract_declarator_opt',1,'p_abstract_declarator_opt','plyparser.py',44), + ('assignment_expression_opt -> empty','assignment_expression_opt',1,'p_assignment_expression_opt','plyparser.py',43), + ('assignment_expression_opt -> assignment_expression','assignment_expression_opt',1,'p_assignment_expression_opt','plyparser.py',44), + ('block_item_list_opt -> empty','block_item_list_opt',1,'p_block_item_list_opt','plyparser.py',43), + ('block_item_list_opt -> block_item_list','block_item_list_opt',1,'p_block_item_list_opt','plyparser.py',44), + ('declaration_list_opt -> empty','declaration_list_opt',1,'p_declaration_list_opt','plyparser.py',43), + ('declaration_list_opt -> declaration_list','declaration_list_opt',1,'p_declaration_list_opt','plyparser.py',44), + ('declaration_specifiers_no_type_opt -> empty','declaration_specifiers_no_type_opt',1,'p_declaration_specifiers_no_type_opt','plyparser.py',43), + ('declaration_specifiers_no_type_opt -> declaration_specifiers_no_type','declaration_specifiers_no_type_opt',1,'p_declaration_specifiers_no_type_opt','plyparser.py',44), + ('designation_opt -> empty','designation_opt',1,'p_designation_opt','plyparser.py',43), + ('designation_opt -> designation','designation_opt',1,'p_designation_opt','plyparser.py',44), + ('expression_opt -> empty','expression_opt',1,'p_expression_opt','plyparser.py',43), + ('expression_opt -> expression','expression_opt',1,'p_expression_opt','plyparser.py',44), + ('id_init_declarator_list_opt -> empty','id_init_declarator_list_opt',1,'p_id_init_declarator_list_opt','plyparser.py',43), + ('id_init_declarator_list_opt -> id_init_declarator_list','id_init_declarator_list_opt',1,'p_id_init_declarator_list_opt','plyparser.py',44), + ('identifier_list_opt -> empty','identifier_list_opt',1,'p_identifier_list_opt','plyparser.py',43), + ('identifier_list_opt -> identifier_list','identifier_list_opt',1,'p_identifier_list_opt','plyparser.py',44), + ('init_declarator_list_opt -> empty','init_declarator_list_opt',1,'p_init_declarator_list_opt','plyparser.py',43), + ('init_declarator_list_opt -> init_declarator_list','init_declarator_list_opt',1,'p_init_declarator_list_opt','plyparser.py',44), + ('initializer_list_opt -> empty','initializer_list_opt',1,'p_initializer_list_opt','plyparser.py',43), + ('initializer_list_opt -> initializer_list','initializer_list_opt',1,'p_initializer_list_opt','plyparser.py',44), + ('parameter_type_list_opt -> empty','parameter_type_list_opt',1,'p_parameter_type_list_opt','plyparser.py',43), + ('parameter_type_list_opt -> parameter_type_list','parameter_type_list_opt',1,'p_parameter_type_list_opt','plyparser.py',44), + ('struct_declarator_list_opt -> empty','struct_declarator_list_opt',1,'p_struct_declarator_list_opt','plyparser.py',43), + ('struct_declarator_list_opt -> struct_declarator_list','struct_declarator_list_opt',1,'p_struct_declarator_list_opt','plyparser.py',44), + ('type_qualifier_list_opt -> empty','type_qualifier_list_opt',1,'p_type_qualifier_list_opt','plyparser.py',43), + ('type_qualifier_list_opt -> type_qualifier_list','type_qualifier_list_opt',1,'p_type_qualifier_list_opt','plyparser.py',44), + ('direct_id_declarator -> ID','direct_id_declarator',1,'p_direct_id_declarator_1','plyparser.py',126), + ('direct_id_declarator -> LPAREN id_declarator RPAREN','direct_id_declarator',3,'p_direct_id_declarator_2','plyparser.py',126), + ('direct_id_declarator -> direct_id_declarator LBRACKET type_qualifier_list_opt assignment_expression_opt RBRACKET','direct_id_declarator',5,'p_direct_id_declarator_3','plyparser.py',126), + ('direct_id_declarator -> direct_id_declarator LBRACKET STATIC type_qualifier_list_opt assignment_expression RBRACKET','direct_id_declarator',6,'p_direct_id_declarator_4','plyparser.py',126), + ('direct_id_declarator -> direct_id_declarator LBRACKET type_qualifier_list STATIC assignment_expression RBRACKET','direct_id_declarator',6,'p_direct_id_declarator_4','plyparser.py',127), + ('direct_id_declarator -> direct_id_declarator LBRACKET type_qualifier_list_opt TIMES RBRACKET','direct_id_declarator',5,'p_direct_id_declarator_5','plyparser.py',126), + ('direct_id_declarator -> direct_id_declarator LPAREN parameter_type_list RPAREN','direct_id_declarator',4,'p_direct_id_declarator_6','plyparser.py',126), + ('direct_id_declarator -> direct_id_declarator LPAREN identifier_list_opt RPAREN','direct_id_declarator',4,'p_direct_id_declarator_6','plyparser.py',127), + ('direct_typeid_declarator -> TYPEID','direct_typeid_declarator',1,'p_direct_typeid_declarator_1','plyparser.py',126), + ('direct_typeid_declarator -> LPAREN typeid_declarator RPAREN','direct_typeid_declarator',3,'p_direct_typeid_declarator_2','plyparser.py',126), + ('direct_typeid_declarator -> direct_typeid_declarator LBRACKET type_qualifier_list_opt assignment_expression_opt RBRACKET','direct_typeid_declarator',5,'p_direct_typeid_declarator_3','plyparser.py',126), + ('direct_typeid_declarator -> direct_typeid_declarator LBRACKET STATIC type_qualifier_list_opt assignment_expression RBRACKET','direct_typeid_declarator',6,'p_direct_typeid_declarator_4','plyparser.py',126), + ('direct_typeid_declarator -> direct_typeid_declarator LBRACKET type_qualifier_list STATIC assignment_expression RBRACKET','direct_typeid_declarator',6,'p_direct_typeid_declarator_4','plyparser.py',127), + ('direct_typeid_declarator -> direct_typeid_declarator LBRACKET type_qualifier_list_opt TIMES RBRACKET','direct_typeid_declarator',5,'p_direct_typeid_declarator_5','plyparser.py',126), + ('direct_typeid_declarator -> direct_typeid_declarator LPAREN parameter_type_list RPAREN','direct_typeid_declarator',4,'p_direct_typeid_declarator_6','plyparser.py',126), + ('direct_typeid_declarator -> direct_typeid_declarator LPAREN identifier_list_opt RPAREN','direct_typeid_declarator',4,'p_direct_typeid_declarator_6','plyparser.py',127), + ('direct_typeid_noparen_declarator -> TYPEID','direct_typeid_noparen_declarator',1,'p_direct_typeid_noparen_declarator_1','plyparser.py',126), + ('direct_typeid_noparen_declarator -> direct_typeid_noparen_declarator LBRACKET type_qualifier_list_opt assignment_expression_opt RBRACKET','direct_typeid_noparen_declarator',5,'p_direct_typeid_noparen_declarator_3','plyparser.py',126), + ('direct_typeid_noparen_declarator -> direct_typeid_noparen_declarator LBRACKET STATIC type_qualifier_list_opt assignment_expression RBRACKET','direct_typeid_noparen_declarator',6,'p_direct_typeid_noparen_declarator_4','plyparser.py',126), + ('direct_typeid_noparen_declarator -> direct_typeid_noparen_declarator LBRACKET type_qualifier_list STATIC assignment_expression RBRACKET','direct_typeid_noparen_declarator',6,'p_direct_typeid_noparen_declarator_4','plyparser.py',127), + ('direct_typeid_noparen_declarator -> direct_typeid_noparen_declarator LBRACKET type_qualifier_list_opt TIMES RBRACKET','direct_typeid_noparen_declarator',5,'p_direct_typeid_noparen_declarator_5','plyparser.py',126), + ('direct_typeid_noparen_declarator -> direct_typeid_noparen_declarator LPAREN parameter_type_list RPAREN','direct_typeid_noparen_declarator',4,'p_direct_typeid_noparen_declarator_6','plyparser.py',126), + ('direct_typeid_noparen_declarator -> direct_typeid_noparen_declarator LPAREN identifier_list_opt RPAREN','direct_typeid_noparen_declarator',4,'p_direct_typeid_noparen_declarator_6','plyparser.py',127), + ('id_declarator -> direct_id_declarator','id_declarator',1,'p_id_declarator_1','plyparser.py',126), + ('id_declarator -> pointer direct_id_declarator','id_declarator',2,'p_id_declarator_2','plyparser.py',126), + ('typeid_declarator -> direct_typeid_declarator','typeid_declarator',1,'p_typeid_declarator_1','plyparser.py',126), + ('typeid_declarator -> pointer direct_typeid_declarator','typeid_declarator',2,'p_typeid_declarator_2','plyparser.py',126), + ('typeid_noparen_declarator -> direct_typeid_noparen_declarator','typeid_noparen_declarator',1,'p_typeid_noparen_declarator_1','plyparser.py',126), + ('typeid_noparen_declarator -> pointer direct_typeid_noparen_declarator','typeid_noparen_declarator',2,'p_typeid_noparen_declarator_2','plyparser.py',126), + ('translation_unit_or_empty -> translation_unit','translation_unit_or_empty',1,'p_translation_unit_or_empty','c_parser.py',509), + ('translation_unit_or_empty -> empty','translation_unit_or_empty',1,'p_translation_unit_or_empty','c_parser.py',510), + ('translation_unit -> external_declaration','translation_unit',1,'p_translation_unit_1','c_parser.py',518), + ('translation_unit -> translation_unit external_declaration','translation_unit',2,'p_translation_unit_2','c_parser.py',524), + ('external_declaration -> function_definition','external_declaration',1,'p_external_declaration_1','c_parser.py',534), + ('external_declaration -> declaration','external_declaration',1,'p_external_declaration_2','c_parser.py',539), + ('external_declaration -> pp_directive','external_declaration',1,'p_external_declaration_3','c_parser.py',544), + ('external_declaration -> pppragma_directive','external_declaration',1,'p_external_declaration_3','c_parser.py',545), + ('external_declaration -> SEMI','external_declaration',1,'p_external_declaration_4','c_parser.py',550), + ('external_declaration -> static_assert','external_declaration',1,'p_external_declaration_5','c_parser.py',555), + ('static_assert -> _STATIC_ASSERT LPAREN constant_expression COMMA unified_string_literal RPAREN','static_assert',6,'p_static_assert_declaration','c_parser.py',560), + ('static_assert -> _STATIC_ASSERT LPAREN constant_expression RPAREN','static_assert',4,'p_static_assert_declaration','c_parser.py',561), + ('pp_directive -> PPHASH','pp_directive',1,'p_pp_directive','c_parser.py',569), + ('pppragma_directive -> PPPRAGMA','pppragma_directive',1,'p_pppragma_directive','c_parser.py',575), + ('pppragma_directive -> PPPRAGMA PPPRAGMASTR','pppragma_directive',2,'p_pppragma_directive','c_parser.py',576), + ('function_definition -> id_declarator declaration_list_opt compound_statement','function_definition',3,'p_function_definition_1','c_parser.py',586), + ('function_definition -> declaration_specifiers id_declarator declaration_list_opt compound_statement','function_definition',4,'p_function_definition_2','c_parser.py',604), + ('statement -> labeled_statement','statement',1,'p_statement','c_parser.py',619), + ('statement -> expression_statement','statement',1,'p_statement','c_parser.py',620), + ('statement -> compound_statement','statement',1,'p_statement','c_parser.py',621), + ('statement -> selection_statement','statement',1,'p_statement','c_parser.py',622), + ('statement -> iteration_statement','statement',1,'p_statement','c_parser.py',623), + ('statement -> jump_statement','statement',1,'p_statement','c_parser.py',624), + ('statement -> pppragma_directive','statement',1,'p_statement','c_parser.py',625), + ('statement -> static_assert','statement',1,'p_statement','c_parser.py',626), + ('pragmacomp_or_statement -> pppragma_directive statement','pragmacomp_or_statement',2,'p_pragmacomp_or_statement','c_parser.py',674), + ('pragmacomp_or_statement -> statement','pragmacomp_or_statement',1,'p_pragmacomp_or_statement','c_parser.py',675), + ('decl_body -> declaration_specifiers init_declarator_list_opt','decl_body',2,'p_decl_body','c_parser.py',694), + ('decl_body -> declaration_specifiers_no_type id_init_declarator_list_opt','decl_body',2,'p_decl_body','c_parser.py',695), + ('declaration -> decl_body SEMI','declaration',2,'p_declaration','c_parser.py',755), + ('declaration_list -> declaration','declaration_list',1,'p_declaration_list','c_parser.py',764), + ('declaration_list -> declaration_list declaration','declaration_list',2,'p_declaration_list','c_parser.py',765), + ('declaration_specifiers_no_type -> type_qualifier declaration_specifiers_no_type_opt','declaration_specifiers_no_type',2,'p_declaration_specifiers_no_type_1','c_parser.py',775), + ('declaration_specifiers_no_type -> storage_class_specifier declaration_specifiers_no_type_opt','declaration_specifiers_no_type',2,'p_declaration_specifiers_no_type_2','c_parser.py',780), + ('declaration_specifiers_no_type -> function_specifier declaration_specifiers_no_type_opt','declaration_specifiers_no_type',2,'p_declaration_specifiers_no_type_3','c_parser.py',785), + ('declaration_specifiers_no_type -> atomic_specifier declaration_specifiers_no_type_opt','declaration_specifiers_no_type',2,'p_declaration_specifiers_no_type_4','c_parser.py',792), + ('declaration_specifiers_no_type -> alignment_specifier declaration_specifiers_no_type_opt','declaration_specifiers_no_type',2,'p_declaration_specifiers_no_type_5','c_parser.py',797), + ('declaration_specifiers -> declaration_specifiers type_qualifier','declaration_specifiers',2,'p_declaration_specifiers_1','c_parser.py',802), + ('declaration_specifiers -> declaration_specifiers storage_class_specifier','declaration_specifiers',2,'p_declaration_specifiers_2','c_parser.py',807), + ('declaration_specifiers -> declaration_specifiers function_specifier','declaration_specifiers',2,'p_declaration_specifiers_3','c_parser.py',812), + ('declaration_specifiers -> declaration_specifiers type_specifier_no_typeid','declaration_specifiers',2,'p_declaration_specifiers_4','c_parser.py',817), + ('declaration_specifiers -> type_specifier','declaration_specifiers',1,'p_declaration_specifiers_5','c_parser.py',822), + ('declaration_specifiers -> declaration_specifiers_no_type type_specifier','declaration_specifiers',2,'p_declaration_specifiers_6','c_parser.py',827), + ('declaration_specifiers -> declaration_specifiers alignment_specifier','declaration_specifiers',2,'p_declaration_specifiers_7','c_parser.py',832), + ('storage_class_specifier -> AUTO','storage_class_specifier',1,'p_storage_class_specifier','c_parser.py',837), + ('storage_class_specifier -> REGISTER','storage_class_specifier',1,'p_storage_class_specifier','c_parser.py',838), + ('storage_class_specifier -> STATIC','storage_class_specifier',1,'p_storage_class_specifier','c_parser.py',839), + ('storage_class_specifier -> EXTERN','storage_class_specifier',1,'p_storage_class_specifier','c_parser.py',840), + ('storage_class_specifier -> TYPEDEF','storage_class_specifier',1,'p_storage_class_specifier','c_parser.py',841), + ('storage_class_specifier -> _THREAD_LOCAL','storage_class_specifier',1,'p_storage_class_specifier','c_parser.py',842), + ('function_specifier -> INLINE','function_specifier',1,'p_function_specifier','c_parser.py',847), + ('function_specifier -> _NORETURN','function_specifier',1,'p_function_specifier','c_parser.py',848), + ('type_specifier_no_typeid -> VOID','type_specifier_no_typeid',1,'p_type_specifier_no_typeid','c_parser.py',853), + ('type_specifier_no_typeid -> _BOOL','type_specifier_no_typeid',1,'p_type_specifier_no_typeid','c_parser.py',854), + ('type_specifier_no_typeid -> CHAR','type_specifier_no_typeid',1,'p_type_specifier_no_typeid','c_parser.py',855), + ('type_specifier_no_typeid -> SHORT','type_specifier_no_typeid',1,'p_type_specifier_no_typeid','c_parser.py',856), + ('type_specifier_no_typeid -> INT','type_specifier_no_typeid',1,'p_type_specifier_no_typeid','c_parser.py',857), + ('type_specifier_no_typeid -> LONG','type_specifier_no_typeid',1,'p_type_specifier_no_typeid','c_parser.py',858), + ('type_specifier_no_typeid -> FLOAT','type_specifier_no_typeid',1,'p_type_specifier_no_typeid','c_parser.py',859), + ('type_specifier_no_typeid -> DOUBLE','type_specifier_no_typeid',1,'p_type_specifier_no_typeid','c_parser.py',860), + ('type_specifier_no_typeid -> _COMPLEX','type_specifier_no_typeid',1,'p_type_specifier_no_typeid','c_parser.py',861), + ('type_specifier_no_typeid -> SIGNED','type_specifier_no_typeid',1,'p_type_specifier_no_typeid','c_parser.py',862), + ('type_specifier_no_typeid -> UNSIGNED','type_specifier_no_typeid',1,'p_type_specifier_no_typeid','c_parser.py',863), + ('type_specifier_no_typeid -> __INT128','type_specifier_no_typeid',1,'p_type_specifier_no_typeid','c_parser.py',864), + ('type_specifier -> typedef_name','type_specifier',1,'p_type_specifier','c_parser.py',869), + ('type_specifier -> enum_specifier','type_specifier',1,'p_type_specifier','c_parser.py',870), + ('type_specifier -> struct_or_union_specifier','type_specifier',1,'p_type_specifier','c_parser.py',871), + ('type_specifier -> type_specifier_no_typeid','type_specifier',1,'p_type_specifier','c_parser.py',872), + ('type_specifier -> atomic_specifier','type_specifier',1,'p_type_specifier','c_parser.py',873), + ('atomic_specifier -> _ATOMIC LPAREN type_name RPAREN','atomic_specifier',4,'p_atomic_specifier','c_parser.py',879), + ('type_qualifier -> CONST','type_qualifier',1,'p_type_qualifier','c_parser.py',886), + ('type_qualifier -> RESTRICT','type_qualifier',1,'p_type_qualifier','c_parser.py',887), + ('type_qualifier -> VOLATILE','type_qualifier',1,'p_type_qualifier','c_parser.py',888), + ('type_qualifier -> _ATOMIC','type_qualifier',1,'p_type_qualifier','c_parser.py',889), + ('init_declarator_list -> init_declarator','init_declarator_list',1,'p_init_declarator_list','c_parser.py',894), + ('init_declarator_list -> init_declarator_list COMMA init_declarator','init_declarator_list',3,'p_init_declarator_list','c_parser.py',895), + ('init_declarator -> declarator','init_declarator',1,'p_init_declarator','c_parser.py',903), + ('init_declarator -> declarator EQUALS initializer','init_declarator',3,'p_init_declarator','c_parser.py',904), + ('id_init_declarator_list -> id_init_declarator','id_init_declarator_list',1,'p_id_init_declarator_list','c_parser.py',909), + ('id_init_declarator_list -> id_init_declarator_list COMMA init_declarator','id_init_declarator_list',3,'p_id_init_declarator_list','c_parser.py',910), + ('id_init_declarator -> id_declarator','id_init_declarator',1,'p_id_init_declarator','c_parser.py',915), + ('id_init_declarator -> id_declarator EQUALS initializer','id_init_declarator',3,'p_id_init_declarator','c_parser.py',916), + ('specifier_qualifier_list -> specifier_qualifier_list type_specifier_no_typeid','specifier_qualifier_list',2,'p_specifier_qualifier_list_1','c_parser.py',923), + ('specifier_qualifier_list -> specifier_qualifier_list type_qualifier','specifier_qualifier_list',2,'p_specifier_qualifier_list_2','c_parser.py',928), + ('specifier_qualifier_list -> type_specifier','specifier_qualifier_list',1,'p_specifier_qualifier_list_3','c_parser.py',933), + ('specifier_qualifier_list -> type_qualifier_list type_specifier','specifier_qualifier_list',2,'p_specifier_qualifier_list_4','c_parser.py',938), + ('specifier_qualifier_list -> alignment_specifier','specifier_qualifier_list',1,'p_specifier_qualifier_list_5','c_parser.py',943), + ('specifier_qualifier_list -> specifier_qualifier_list alignment_specifier','specifier_qualifier_list',2,'p_specifier_qualifier_list_6','c_parser.py',948), + ('struct_or_union_specifier -> struct_or_union ID','struct_or_union_specifier',2,'p_struct_or_union_specifier_1','c_parser.py',956), + ('struct_or_union_specifier -> struct_or_union TYPEID','struct_or_union_specifier',2,'p_struct_or_union_specifier_1','c_parser.py',957), + ('struct_or_union_specifier -> struct_or_union brace_open struct_declaration_list brace_close','struct_or_union_specifier',4,'p_struct_or_union_specifier_2','c_parser.py',967), + ('struct_or_union_specifier -> struct_or_union brace_open brace_close','struct_or_union_specifier',3,'p_struct_or_union_specifier_2','c_parser.py',968), + ('struct_or_union_specifier -> struct_or_union ID brace_open struct_declaration_list brace_close','struct_or_union_specifier',5,'p_struct_or_union_specifier_3','c_parser.py',985), + ('struct_or_union_specifier -> struct_or_union ID brace_open brace_close','struct_or_union_specifier',4,'p_struct_or_union_specifier_3','c_parser.py',986), + ('struct_or_union_specifier -> struct_or_union TYPEID brace_open struct_declaration_list brace_close','struct_or_union_specifier',5,'p_struct_or_union_specifier_3','c_parser.py',987), + ('struct_or_union_specifier -> struct_or_union TYPEID brace_open brace_close','struct_or_union_specifier',4,'p_struct_or_union_specifier_3','c_parser.py',988), + ('struct_or_union -> STRUCT','struct_or_union',1,'p_struct_or_union','c_parser.py',1004), + ('struct_or_union -> UNION','struct_or_union',1,'p_struct_or_union','c_parser.py',1005), + ('struct_declaration_list -> struct_declaration','struct_declaration_list',1,'p_struct_declaration_list','c_parser.py',1012), + ('struct_declaration_list -> struct_declaration_list struct_declaration','struct_declaration_list',2,'p_struct_declaration_list','c_parser.py',1013), + ('struct_declaration -> specifier_qualifier_list struct_declarator_list_opt SEMI','struct_declaration',3,'p_struct_declaration_1','c_parser.py',1021), + ('struct_declaration -> SEMI','struct_declaration',1,'p_struct_declaration_2','c_parser.py',1059), + ('struct_declaration -> pppragma_directive','struct_declaration',1,'p_struct_declaration_3','c_parser.py',1064), + ('struct_declarator_list -> struct_declarator','struct_declarator_list',1,'p_struct_declarator_list','c_parser.py',1069), + ('struct_declarator_list -> struct_declarator_list COMMA struct_declarator','struct_declarator_list',3,'p_struct_declarator_list','c_parser.py',1070), + ('struct_declarator -> declarator','struct_declarator',1,'p_struct_declarator_1','c_parser.py',1078), + ('struct_declarator -> declarator COLON constant_expression','struct_declarator',3,'p_struct_declarator_2','c_parser.py',1083), + ('struct_declarator -> COLON constant_expression','struct_declarator',2,'p_struct_declarator_2','c_parser.py',1084), + ('enum_specifier -> ENUM ID','enum_specifier',2,'p_enum_specifier_1','c_parser.py',1092), + ('enum_specifier -> ENUM TYPEID','enum_specifier',2,'p_enum_specifier_1','c_parser.py',1093), + ('enum_specifier -> ENUM brace_open enumerator_list brace_close','enum_specifier',4,'p_enum_specifier_2','c_parser.py',1098), + ('enum_specifier -> ENUM ID brace_open enumerator_list brace_close','enum_specifier',5,'p_enum_specifier_3','c_parser.py',1103), + ('enum_specifier -> ENUM TYPEID brace_open enumerator_list brace_close','enum_specifier',5,'p_enum_specifier_3','c_parser.py',1104), + ('enumerator_list -> enumerator','enumerator_list',1,'p_enumerator_list','c_parser.py',1109), + ('enumerator_list -> enumerator_list COMMA','enumerator_list',2,'p_enumerator_list','c_parser.py',1110), + ('enumerator_list -> enumerator_list COMMA enumerator','enumerator_list',3,'p_enumerator_list','c_parser.py',1111), + ('alignment_specifier -> _ALIGNAS LPAREN type_name RPAREN','alignment_specifier',4,'p_alignment_specifier','c_parser.py',1122), + ('alignment_specifier -> _ALIGNAS LPAREN constant_expression RPAREN','alignment_specifier',4,'p_alignment_specifier','c_parser.py',1123), + ('enumerator -> ID','enumerator',1,'p_enumerator','c_parser.py',1128), + ('enumerator -> ID EQUALS constant_expression','enumerator',3,'p_enumerator','c_parser.py',1129), + ('declarator -> id_declarator','declarator',1,'p_declarator','c_parser.py',1144), + ('declarator -> typeid_declarator','declarator',1,'p_declarator','c_parser.py',1145), + ('pointer -> TIMES type_qualifier_list_opt','pointer',2,'p_pointer','c_parser.py',1257), + ('pointer -> TIMES type_qualifier_list_opt pointer','pointer',3,'p_pointer','c_parser.py',1258), + ('type_qualifier_list -> type_qualifier','type_qualifier_list',1,'p_type_qualifier_list','c_parser.py',1287), + ('type_qualifier_list -> type_qualifier_list type_qualifier','type_qualifier_list',2,'p_type_qualifier_list','c_parser.py',1288), + ('parameter_type_list -> parameter_list','parameter_type_list',1,'p_parameter_type_list','c_parser.py',1293), + ('parameter_type_list -> parameter_list COMMA ELLIPSIS','parameter_type_list',3,'p_parameter_type_list','c_parser.py',1294), + ('parameter_list -> parameter_declaration','parameter_list',1,'p_parameter_list','c_parser.py',1302), + ('parameter_list -> parameter_list COMMA parameter_declaration','parameter_list',3,'p_parameter_list','c_parser.py',1303), + ('parameter_declaration -> declaration_specifiers id_declarator','parameter_declaration',2,'p_parameter_declaration_1','c_parser.py',1322), + ('parameter_declaration -> declaration_specifiers typeid_noparen_declarator','parameter_declaration',2,'p_parameter_declaration_1','c_parser.py',1323), + ('parameter_declaration -> declaration_specifiers abstract_declarator_opt','parameter_declaration',2,'p_parameter_declaration_2','c_parser.py',1334), + ('identifier_list -> identifier','identifier_list',1,'p_identifier_list','c_parser.py',1366), + ('identifier_list -> identifier_list COMMA identifier','identifier_list',3,'p_identifier_list','c_parser.py',1367), + ('initializer -> assignment_expression','initializer',1,'p_initializer_1','c_parser.py',1376), + ('initializer -> brace_open initializer_list_opt brace_close','initializer',3,'p_initializer_2','c_parser.py',1381), + ('initializer -> brace_open initializer_list COMMA brace_close','initializer',4,'p_initializer_2','c_parser.py',1382), + ('initializer_list -> designation_opt initializer','initializer_list',2,'p_initializer_list','c_parser.py',1390), + ('initializer_list -> initializer_list COMMA designation_opt initializer','initializer_list',4,'p_initializer_list','c_parser.py',1391), + ('designation -> designator_list EQUALS','designation',2,'p_designation','c_parser.py',1402), + ('designator_list -> designator','designator_list',1,'p_designator_list','c_parser.py',1410), + ('designator_list -> designator_list designator','designator_list',2,'p_designator_list','c_parser.py',1411), + ('designator -> LBRACKET constant_expression RBRACKET','designator',3,'p_designator','c_parser.py',1416), + ('designator -> PERIOD identifier','designator',2,'p_designator','c_parser.py',1417), + ('type_name -> specifier_qualifier_list abstract_declarator_opt','type_name',2,'p_type_name','c_parser.py',1422), + ('abstract_declarator -> pointer','abstract_declarator',1,'p_abstract_declarator_1','c_parser.py',1434), + ('abstract_declarator -> pointer direct_abstract_declarator','abstract_declarator',2,'p_abstract_declarator_2','c_parser.py',1442), + ('abstract_declarator -> direct_abstract_declarator','abstract_declarator',1,'p_abstract_declarator_3','c_parser.py',1447), + ('direct_abstract_declarator -> LPAREN abstract_declarator RPAREN','direct_abstract_declarator',3,'p_direct_abstract_declarator_1','c_parser.py',1457), + ('direct_abstract_declarator -> direct_abstract_declarator LBRACKET assignment_expression_opt RBRACKET','direct_abstract_declarator',4,'p_direct_abstract_declarator_2','c_parser.py',1461), + ('direct_abstract_declarator -> LBRACKET type_qualifier_list_opt assignment_expression_opt RBRACKET','direct_abstract_declarator',4,'p_direct_abstract_declarator_3','c_parser.py',1472), + ('direct_abstract_declarator -> direct_abstract_declarator LBRACKET TIMES RBRACKET','direct_abstract_declarator',4,'p_direct_abstract_declarator_4','c_parser.py',1482), + ('direct_abstract_declarator -> LBRACKET TIMES RBRACKET','direct_abstract_declarator',3,'p_direct_abstract_declarator_5','c_parser.py',1493), + ('direct_abstract_declarator -> direct_abstract_declarator LPAREN parameter_type_list_opt RPAREN','direct_abstract_declarator',4,'p_direct_abstract_declarator_6','c_parser.py',1502), + ('direct_abstract_declarator -> LPAREN parameter_type_list_opt RPAREN','direct_abstract_declarator',3,'p_direct_abstract_declarator_7','c_parser.py',1512), + ('block_item -> declaration','block_item',1,'p_block_item','c_parser.py',1523), + ('block_item -> statement','block_item',1,'p_block_item','c_parser.py',1524), + ('block_item_list -> block_item','block_item_list',1,'p_block_item_list','c_parser.py',1531), + ('block_item_list -> block_item_list block_item','block_item_list',2,'p_block_item_list','c_parser.py',1532), + ('compound_statement -> brace_open block_item_list_opt brace_close','compound_statement',3,'p_compound_statement_1','c_parser.py',1538), + ('labeled_statement -> ID COLON pragmacomp_or_statement','labeled_statement',3,'p_labeled_statement_1','c_parser.py',1544), + ('labeled_statement -> CASE constant_expression COLON pragmacomp_or_statement','labeled_statement',4,'p_labeled_statement_2','c_parser.py',1548), + ('labeled_statement -> DEFAULT COLON pragmacomp_or_statement','labeled_statement',3,'p_labeled_statement_3','c_parser.py',1552), + ('selection_statement -> IF LPAREN expression RPAREN pragmacomp_or_statement','selection_statement',5,'p_selection_statement_1','c_parser.py',1556), + ('selection_statement -> IF LPAREN expression RPAREN statement ELSE pragmacomp_or_statement','selection_statement',7,'p_selection_statement_2','c_parser.py',1560), + ('selection_statement -> SWITCH LPAREN expression RPAREN pragmacomp_or_statement','selection_statement',5,'p_selection_statement_3','c_parser.py',1564), + ('iteration_statement -> WHILE LPAREN expression RPAREN pragmacomp_or_statement','iteration_statement',5,'p_iteration_statement_1','c_parser.py',1569), + ('iteration_statement -> DO pragmacomp_or_statement WHILE LPAREN expression RPAREN SEMI','iteration_statement',7,'p_iteration_statement_2','c_parser.py',1573), + ('iteration_statement -> FOR LPAREN expression_opt SEMI expression_opt SEMI expression_opt RPAREN pragmacomp_or_statement','iteration_statement',9,'p_iteration_statement_3','c_parser.py',1577), + ('iteration_statement -> FOR LPAREN declaration expression_opt SEMI expression_opt RPAREN pragmacomp_or_statement','iteration_statement',8,'p_iteration_statement_4','c_parser.py',1581), + ('jump_statement -> GOTO ID SEMI','jump_statement',3,'p_jump_statement_1','c_parser.py',1586), + ('jump_statement -> BREAK SEMI','jump_statement',2,'p_jump_statement_2','c_parser.py',1590), + ('jump_statement -> CONTINUE SEMI','jump_statement',2,'p_jump_statement_3','c_parser.py',1594), + ('jump_statement -> RETURN expression SEMI','jump_statement',3,'p_jump_statement_4','c_parser.py',1598), + ('jump_statement -> RETURN SEMI','jump_statement',2,'p_jump_statement_4','c_parser.py',1599), + ('expression_statement -> expression_opt SEMI','expression_statement',2,'p_expression_statement','c_parser.py',1604), + ('expression -> assignment_expression','expression',1,'p_expression','c_parser.py',1611), + ('expression -> expression COMMA assignment_expression','expression',3,'p_expression','c_parser.py',1612), + ('assignment_expression -> LPAREN compound_statement RPAREN','assignment_expression',3,'p_parenthesized_compound_expression','c_parser.py',1624), + ('typedef_name -> TYPEID','typedef_name',1,'p_typedef_name','c_parser.py',1628), + ('assignment_expression -> conditional_expression','assignment_expression',1,'p_assignment_expression','c_parser.py',1632), + ('assignment_expression -> unary_expression assignment_operator assignment_expression','assignment_expression',3,'p_assignment_expression','c_parser.py',1633), + ('assignment_operator -> EQUALS','assignment_operator',1,'p_assignment_operator','c_parser.py',1646), + ('assignment_operator -> XOREQUAL','assignment_operator',1,'p_assignment_operator','c_parser.py',1647), + ('assignment_operator -> TIMESEQUAL','assignment_operator',1,'p_assignment_operator','c_parser.py',1648), + ('assignment_operator -> DIVEQUAL','assignment_operator',1,'p_assignment_operator','c_parser.py',1649), + ('assignment_operator -> MODEQUAL','assignment_operator',1,'p_assignment_operator','c_parser.py',1650), + ('assignment_operator -> PLUSEQUAL','assignment_operator',1,'p_assignment_operator','c_parser.py',1651), + ('assignment_operator -> MINUSEQUAL','assignment_operator',1,'p_assignment_operator','c_parser.py',1652), + ('assignment_operator -> LSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','c_parser.py',1653), + ('assignment_operator -> RSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','c_parser.py',1654), + ('assignment_operator -> ANDEQUAL','assignment_operator',1,'p_assignment_operator','c_parser.py',1655), + ('assignment_operator -> OREQUAL','assignment_operator',1,'p_assignment_operator','c_parser.py',1656), + ('constant_expression -> conditional_expression','constant_expression',1,'p_constant_expression','c_parser.py',1661), + ('conditional_expression -> binary_expression','conditional_expression',1,'p_conditional_expression','c_parser.py',1665), + ('conditional_expression -> binary_expression CONDOP expression COLON conditional_expression','conditional_expression',5,'p_conditional_expression','c_parser.py',1666), + ('binary_expression -> cast_expression','binary_expression',1,'p_binary_expression','c_parser.py',1674), + ('binary_expression -> binary_expression TIMES binary_expression','binary_expression',3,'p_binary_expression','c_parser.py',1675), + ('binary_expression -> binary_expression DIVIDE binary_expression','binary_expression',3,'p_binary_expression','c_parser.py',1676), + ('binary_expression -> binary_expression MOD binary_expression','binary_expression',3,'p_binary_expression','c_parser.py',1677), + ('binary_expression -> binary_expression PLUS binary_expression','binary_expression',3,'p_binary_expression','c_parser.py',1678), + ('binary_expression -> binary_expression MINUS binary_expression','binary_expression',3,'p_binary_expression','c_parser.py',1679), + ('binary_expression -> binary_expression RSHIFT binary_expression','binary_expression',3,'p_binary_expression','c_parser.py',1680), + ('binary_expression -> binary_expression LSHIFT binary_expression','binary_expression',3,'p_binary_expression','c_parser.py',1681), + ('binary_expression -> binary_expression LT binary_expression','binary_expression',3,'p_binary_expression','c_parser.py',1682), + ('binary_expression -> binary_expression LE binary_expression','binary_expression',3,'p_binary_expression','c_parser.py',1683), + ('binary_expression -> binary_expression GE binary_expression','binary_expression',3,'p_binary_expression','c_parser.py',1684), + ('binary_expression -> binary_expression GT binary_expression','binary_expression',3,'p_binary_expression','c_parser.py',1685), + ('binary_expression -> binary_expression EQ binary_expression','binary_expression',3,'p_binary_expression','c_parser.py',1686), + ('binary_expression -> binary_expression NE binary_expression','binary_expression',3,'p_binary_expression','c_parser.py',1687), + ('binary_expression -> binary_expression AND binary_expression','binary_expression',3,'p_binary_expression','c_parser.py',1688), + ('binary_expression -> binary_expression OR binary_expression','binary_expression',3,'p_binary_expression','c_parser.py',1689), + ('binary_expression -> binary_expression XOR binary_expression','binary_expression',3,'p_binary_expression','c_parser.py',1690), + ('binary_expression -> binary_expression LAND binary_expression','binary_expression',3,'p_binary_expression','c_parser.py',1691), + ('binary_expression -> binary_expression LOR binary_expression','binary_expression',3,'p_binary_expression','c_parser.py',1692), + ('cast_expression -> unary_expression','cast_expression',1,'p_cast_expression_1','c_parser.py',1700), + ('cast_expression -> LPAREN type_name RPAREN cast_expression','cast_expression',4,'p_cast_expression_2','c_parser.py',1704), + ('unary_expression -> postfix_expression','unary_expression',1,'p_unary_expression_1','c_parser.py',1708), + ('unary_expression -> PLUSPLUS unary_expression','unary_expression',2,'p_unary_expression_2','c_parser.py',1712), + ('unary_expression -> MINUSMINUS unary_expression','unary_expression',2,'p_unary_expression_2','c_parser.py',1713), + ('unary_expression -> unary_operator cast_expression','unary_expression',2,'p_unary_expression_2','c_parser.py',1714), + ('unary_expression -> SIZEOF unary_expression','unary_expression',2,'p_unary_expression_3','c_parser.py',1719), + ('unary_expression -> SIZEOF LPAREN type_name RPAREN','unary_expression',4,'p_unary_expression_3','c_parser.py',1720), + ('unary_expression -> _ALIGNOF LPAREN type_name RPAREN','unary_expression',4,'p_unary_expression_3','c_parser.py',1721), + ('unary_operator -> AND','unary_operator',1,'p_unary_operator','c_parser.py',1729), + ('unary_operator -> TIMES','unary_operator',1,'p_unary_operator','c_parser.py',1730), + ('unary_operator -> PLUS','unary_operator',1,'p_unary_operator','c_parser.py',1731), + ('unary_operator -> MINUS','unary_operator',1,'p_unary_operator','c_parser.py',1732), + ('unary_operator -> NOT','unary_operator',1,'p_unary_operator','c_parser.py',1733), + ('unary_operator -> LNOT','unary_operator',1,'p_unary_operator','c_parser.py',1734), + ('postfix_expression -> primary_expression','postfix_expression',1,'p_postfix_expression_1','c_parser.py',1739), + ('postfix_expression -> postfix_expression LBRACKET expression RBRACKET','postfix_expression',4,'p_postfix_expression_2','c_parser.py',1743), + ('postfix_expression -> postfix_expression LPAREN argument_expression_list RPAREN','postfix_expression',4,'p_postfix_expression_3','c_parser.py',1747), + ('postfix_expression -> postfix_expression LPAREN RPAREN','postfix_expression',3,'p_postfix_expression_3','c_parser.py',1748), + ('postfix_expression -> postfix_expression PERIOD ID','postfix_expression',3,'p_postfix_expression_4','c_parser.py',1753), + ('postfix_expression -> postfix_expression PERIOD TYPEID','postfix_expression',3,'p_postfix_expression_4','c_parser.py',1754), + ('postfix_expression -> postfix_expression ARROW ID','postfix_expression',3,'p_postfix_expression_4','c_parser.py',1755), + ('postfix_expression -> postfix_expression ARROW TYPEID','postfix_expression',3,'p_postfix_expression_4','c_parser.py',1756), + ('postfix_expression -> postfix_expression PLUSPLUS','postfix_expression',2,'p_postfix_expression_5','c_parser.py',1762), + ('postfix_expression -> postfix_expression MINUSMINUS','postfix_expression',2,'p_postfix_expression_5','c_parser.py',1763), + ('postfix_expression -> LPAREN type_name RPAREN brace_open initializer_list brace_close','postfix_expression',6,'p_postfix_expression_6','c_parser.py',1768), + ('postfix_expression -> LPAREN type_name RPAREN brace_open initializer_list COMMA brace_close','postfix_expression',7,'p_postfix_expression_6','c_parser.py',1769), + ('primary_expression -> identifier','primary_expression',1,'p_primary_expression_1','c_parser.py',1774), + ('primary_expression -> constant','primary_expression',1,'p_primary_expression_2','c_parser.py',1778), + ('primary_expression -> unified_string_literal','primary_expression',1,'p_primary_expression_3','c_parser.py',1782), + ('primary_expression -> unified_wstring_literal','primary_expression',1,'p_primary_expression_3','c_parser.py',1783), + ('primary_expression -> LPAREN expression RPAREN','primary_expression',3,'p_primary_expression_4','c_parser.py',1788), + ('primary_expression -> OFFSETOF LPAREN type_name COMMA offsetof_member_designator RPAREN','primary_expression',6,'p_primary_expression_5','c_parser.py',1792), + ('offsetof_member_designator -> identifier','offsetof_member_designator',1,'p_offsetof_member_designator','c_parser.py',1800), + ('offsetof_member_designator -> offsetof_member_designator PERIOD identifier','offsetof_member_designator',3,'p_offsetof_member_designator','c_parser.py',1801), + ('offsetof_member_designator -> offsetof_member_designator LBRACKET expression RBRACKET','offsetof_member_designator',4,'p_offsetof_member_designator','c_parser.py',1802), + ('argument_expression_list -> assignment_expression','argument_expression_list',1,'p_argument_expression_list','c_parser.py',1814), + ('argument_expression_list -> argument_expression_list COMMA assignment_expression','argument_expression_list',3,'p_argument_expression_list','c_parser.py',1815), + ('identifier -> ID','identifier',1,'p_identifier','c_parser.py',1824), + ('constant -> INT_CONST_DEC','constant',1,'p_constant_1','c_parser.py',1828), + ('constant -> INT_CONST_OCT','constant',1,'p_constant_1','c_parser.py',1829), + ('constant -> INT_CONST_HEX','constant',1,'p_constant_1','c_parser.py',1830), + ('constant -> INT_CONST_BIN','constant',1,'p_constant_1','c_parser.py',1831), + ('constant -> INT_CONST_CHAR','constant',1,'p_constant_1','c_parser.py',1832), + ('constant -> FLOAT_CONST','constant',1,'p_constant_2','c_parser.py',1851), + ('constant -> HEX_FLOAT_CONST','constant',1,'p_constant_2','c_parser.py',1852), + ('constant -> CHAR_CONST','constant',1,'p_constant_3','c_parser.py',1868), + ('constant -> WCHAR_CONST','constant',1,'p_constant_3','c_parser.py',1869), + ('constant -> U8CHAR_CONST','constant',1,'p_constant_3','c_parser.py',1870), + ('constant -> U16CHAR_CONST','constant',1,'p_constant_3','c_parser.py',1871), + ('constant -> U32CHAR_CONST','constant',1,'p_constant_3','c_parser.py',1872), + ('unified_string_literal -> STRING_LITERAL','unified_string_literal',1,'p_unified_string_literal','c_parser.py',1883), + ('unified_string_literal -> unified_string_literal STRING_LITERAL','unified_string_literal',2,'p_unified_string_literal','c_parser.py',1884), + ('unified_wstring_literal -> WSTRING_LITERAL','unified_wstring_literal',1,'p_unified_wstring_literal','c_parser.py',1894), + ('unified_wstring_literal -> U8STRING_LITERAL','unified_wstring_literal',1,'p_unified_wstring_literal','c_parser.py',1895), + ('unified_wstring_literal -> U16STRING_LITERAL','unified_wstring_literal',1,'p_unified_wstring_literal','c_parser.py',1896), + ('unified_wstring_literal -> U32STRING_LITERAL','unified_wstring_literal',1,'p_unified_wstring_literal','c_parser.py',1897), + ('unified_wstring_literal -> unified_wstring_literal WSTRING_LITERAL','unified_wstring_literal',2,'p_unified_wstring_literal','c_parser.py',1898), + ('unified_wstring_literal -> unified_wstring_literal U8STRING_LITERAL','unified_wstring_literal',2,'p_unified_wstring_literal','c_parser.py',1899), + ('unified_wstring_literal -> unified_wstring_literal U16STRING_LITERAL','unified_wstring_literal',2,'p_unified_wstring_literal','c_parser.py',1900), + ('unified_wstring_literal -> unified_wstring_literal U32STRING_LITERAL','unified_wstring_literal',2,'p_unified_wstring_literal','c_parser.py',1901), + ('brace_open -> LBRACE','brace_open',1,'p_brace_open','c_parser.py',1911), + ('brace_close -> RBRACE','brace_close',1,'p_brace_close','c_parser.py',1917), + ('empty -> ','empty',0,'p_empty','c_parser.py',1923), +] diff --git a/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/INSTALLER b/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/LICENSE b/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/LICENSE new file mode 100644 index 00000000..3a971190 --- /dev/null +++ b/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2014, Saurabh Kumar (python-dotenv), 2013, Ted Tieken (django-dotenv-rw), 2013, Jacob Kaplan-Moss (django-dotenv) + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +- Neither the name of django-dotenv nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/METADATA b/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/METADATA new file mode 100644 index 00000000..b9af7fe6 --- /dev/null +++ b/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/METADATA @@ -0,0 +1,692 @@ +Metadata-Version: 2.1 +Name: python-dotenv +Version: 1.0.1 +Summary: Read key-value pairs from a .env file and set them as environment variables +Home-page: https://github.com/theskumar/python-dotenv +Author: Saurabh Kumar +Author-email: me+github@saurabh-kumar.com +License: BSD-3-Clause +Keywords: environment variables,deployments,settings,env,dotenv,configurations,python +Classifier: Development Status :: 5 - Production/Stable +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: Programming Language :: Python :: Implementation :: PyPy +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: System Administrators +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Topic :: System :: Systems Administration +Classifier: Topic :: Utilities +Classifier: Environment :: Web Environment +Requires-Python: >=3.8 +Description-Content-Type: text/markdown +License-File: LICENSE +Provides-Extra: cli +Requires-Dist: click >=5.0 ; extra == 'cli' + +# python-dotenv + +[![Build Status][build_status_badge]][build_status_link] +[![PyPI version][pypi_badge]][pypi_link] + +Python-dotenv reads key-value pairs from a `.env` file and can set them as environment +variables. It helps in the development of applications following the +[12-factor](https://12factor.net/) principles. + +- [Getting Started](#getting-started) +- [Other Use Cases](#other-use-cases) + * [Load configuration without altering the environment](#load-configuration-without-altering-the-environment) + * [Parse configuration as a stream](#parse-configuration-as-a-stream) + * [Load .env files in IPython](#load-env-files-in-ipython) +- [Command-line Interface](#command-line-interface) +- [File format](#file-format) + * [Multiline values](#multiline-values) + * [Variable expansion](#variable-expansion) +- [Related Projects](#related-projects) +- [Acknowledgements](#acknowledgements) + +## Getting Started + +```shell +pip install python-dotenv +``` + +If your application takes its configuration from environment variables, like a 12-factor +application, launching it in development is not very practical because you have to set +those environment variables yourself. + +To help you with that, you can add Python-dotenv to your application to make it load the +configuration from a `.env` file when it is present (e.g. in development) while remaining +configurable via the environment: + +```python +from dotenv import load_dotenv + +load_dotenv() # take environment variables from .env. + +# Code of your application, which uses environment variables (e.g. from `os.environ` or +# `os.getenv`) as if they came from the actual environment. +``` + +By default, `load_dotenv` doesn't override existing environment variables. + +To configure the development environment, add a `.env` in the root directory of your +project: + +``` +. +├── .env +└── foo.py +``` + +The syntax of `.env` files supported by python-dotenv is similar to that of Bash: + +```bash +# Development settings +DOMAIN=example.org +ADMIN_EMAIL=admin@${DOMAIN} +ROOT_URL=${DOMAIN}/app +``` + +If you use variables in values, ensure they are surrounded with `{` and `}`, like +`${DOMAIN}`, as bare variables such as `$DOMAIN` are not expanded. + +You will probably want to add `.env` to your `.gitignore`, especially if it contains +secrets like a password. + +See the section "File format" below for more information about what you can write in a +`.env` file. + +## Other Use Cases + +### Load configuration without altering the environment + +The function `dotenv_values` works more or less the same way as `load_dotenv`, except it +doesn't touch the environment, it just returns a `dict` with the values parsed from the +`.env` file. + +```python +from dotenv import dotenv_values + +config = dotenv_values(".env") # config = {"USER": "foo", "EMAIL": "foo@example.org"} +``` + +This notably enables advanced configuration management: + +```python +import os +from dotenv import dotenv_values + +config = { + **dotenv_values(".env.shared"), # load shared development variables + **dotenv_values(".env.secret"), # load sensitive variables + **os.environ, # override loaded values with environment variables +} +``` + +### Parse configuration as a stream + +`load_dotenv` and `dotenv_values` accept [streams][python_streams] via their `stream` +argument. It is thus possible to load the variables from sources other than the +filesystem (e.g. the network). + +```python +from io import StringIO + +from dotenv import load_dotenv + +config = StringIO("USER=foo\nEMAIL=foo@example.org") +load_dotenv(stream=config) +``` + +### Load .env files in IPython + +You can use dotenv in IPython. By default, it will use `find_dotenv` to search for a +`.env` file: + +```python +%load_ext dotenv +%dotenv +``` + +You can also specify a path: + +```python +%dotenv relative/or/absolute/path/to/.env +``` + +Optional flags: + +- `-o` to override existing variables. +- `-v` for increased verbosity. + +## Command-line Interface + +A CLI interface `dotenv` is also included, which helps you manipulate the `.env` file +without manually opening it. + +```shell +$ pip install "python-dotenv[cli]" +$ dotenv set USER foo +$ dotenv set EMAIL foo@example.org +$ dotenv list +USER=foo +EMAIL=foo@example.org +$ dotenv list --format=json +{ + "USER": "foo", + "EMAIL": "foo@example.org" +} +$ dotenv run -- python foo.py +``` + +Run `dotenv --help` for more information about the options and subcommands. + +## File format + +The format is not formally specified and still improves over time. That being said, +`.env` files should mostly look like Bash files. + +Keys can be unquoted or single-quoted. Values can be unquoted, single- or double-quoted. +Spaces before and after keys, equal signs, and values are ignored. Values can be followed +by a comment. Lines can start with the `export` directive, which does not affect their +interpretation. + +Allowed escape sequences: + +- in single-quoted values: `\\`, `\'` +- in double-quoted values: `\\`, `\'`, `\"`, `\a`, `\b`, `\f`, `\n`, `\r`, `\t`, `\v` + +### Multiline values + +It is possible for single- or double-quoted values to span multiple lines. The following +examples are equivalent: + +```bash +FOO="first line +second line" +``` + +```bash +FOO="first line\nsecond line" +``` + +### Variable without a value + +A variable can have no value: + +```bash +FOO +``` + +It results in `dotenv_values` associating that variable name with the value `None` (e.g. +`{"FOO": None}`. `load_dotenv`, on the other hand, simply ignores such variables. + +This shouldn't be confused with `FOO=`, in which case the variable is associated with the +empty string. + +### Variable expansion + +Python-dotenv can interpolate variables using POSIX variable expansion. + +With `load_dotenv(override=True)` or `dotenv_values()`, the value of a variable is the +first of the values defined in the following list: + +- Value of that variable in the `.env` file. +- Value of that variable in the environment. +- Default value, if provided. +- Empty string. + +With `load_dotenv(override=False)`, the value of a variable is the first of the values +defined in the following list: + +- Value of that variable in the environment. +- Value of that variable in the `.env` file. +- Default value, if provided. +- Empty string. + +## Related Projects + +- [Honcho](https://github.com/nickstenning/honcho) - For managing + Procfile-based applications. +- [django-dotenv](https://github.com/jpadilla/django-dotenv) +- [django-environ](https://github.com/joke2k/django-environ) +- [django-environ-2](https://github.com/sergeyklay/django-environ-2) +- [django-configuration](https://github.com/jezdez/django-configurations) +- [dump-env](https://github.com/sobolevn/dump-env) +- [environs](https://github.com/sloria/environs) +- [dynaconf](https://github.com/rochacbruno/dynaconf) +- [parse_it](https://github.com/naorlivne/parse_it) +- [python-decouple](https://github.com/HBNetwork/python-decouple) + +## Acknowledgements + +This project is currently maintained by [Saurabh Kumar](https://saurabh-kumar.com) and +[Bertrand Bonnefoy-Claudet](https://github.com/bbc2) and would not have been possible +without the support of these [awesome +people](https://github.com/theskumar/python-dotenv/graphs/contributors). + +[build_status_badge]: https://github.com/theskumar/python-dotenv/actions/workflows/test.yml/badge.svg +[build_status_link]: https://github.com/theskumar/python-dotenv/actions/workflows/test.yml +[pypi_badge]: https://badge.fury.io/py/python-dotenv.svg +[pypi_link]: https://badge.fury.io/py/python-dotenv +[python_streams]: https://docs.python.org/3/library/io.html + +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this +project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.0.1] - 2024-01-23 + +**Fixed** + +* Gracefully handle code which has been imported from a zipfile ([#456] by [@samwyma]) +* Allow modules using load_dotenv to be reloaded when launched in a separate thread ([#497] by [@freddyaboulton]) +* Fix file not closed after deletion, handle error in the rewrite function ([#469] by [@Qwerty-133]) + +**Misc** +* Use pathlib.Path in tests ([#466] by [@eumiro]) +* Fix year in release date in changelog.md ([#454] by [@jankislinger]) +* Use https in README links ([#474] by [@Nicals]) + +## [1.0.0] - 2023-02-24 + +**Fixed** + +* Drop support for python 3.7, add python 3.12-dev (#449 by [@theskumar]) +* Handle situations where the cwd does not exist. (#446 by [@jctanner]) + +## [0.21.1] - 2023-01-21 + +**Added** + +* Use Python 3.11 non-beta in CI (#438 by [@bbc2]) +* Modernize variables code (#434 by [@Nougat-Waffle]) +* Modernize main.py and parser.py code (#435 by [@Nougat-Waffle]) +* Improve conciseness of cli.py and __init__.py (#439 by [@Nougat-Waffle]) +* Improve error message for `get` and `list` commands when env file can't be opened (#441 by [@bbc2]) +* Updated License to align with BSD OSI template (#433 by [@lsmith77]) + + +**Fixed** + +* Fix Out-of-scope error when "dest" variable is undefined (#413 by [@theGOTOguy]) +* Fix IPython test warning about deprecated `magic` (#440 by [@bbc2]) +* Fix type hint for dotenv_path var, add StrPath alias (#432 by [@eaf]) + +## [0.21.0] - 2022-09-03 + +**Added** + +* CLI: add support for invocations via 'python -m'. (#395 by [@theskumar]) +* `load_dotenv` function now returns `False`. (#388 by [@larsks]) +* CLI: add --format= option to list command. (#407 by [@sammck]) + +**Fixed** + +* Drop Python 3.5 and 3.6 and upgrade GA (#393 by [@eggplants]) +* Use `open` instead of `io.open`. (#389 by [@rabinadk1]) +* Improve documentation for variables without a value (#390 by [@bbc2]) +* Add `parse_it` to Related Projects (#410 by [@naorlivne]) +* Update README.md (#415 by [@harveer07]) +* Improve documentation with direct use of MkDocs (#398 by [@bbc2]) + +## [0.20.0] - 2022-03-24 + +**Added** + +- Add `encoding` (`Optional[str]`) parameter to `get_key`, `set_key` and `unset_key`. + (#379 by [@bbc2]) + +**Fixed** + +- Use dict to specify the `entry_points` parameter of `setuptools.setup` (#376 by + [@mgorny]). +- Don't build universal wheels (#387 by [@bbc2]). + +## [0.19.2] - 2021-11-11 + +**Fixed** + +- In `set_key`, add missing newline character before new entry if necessary. (#361 by + [@bbc2]) + +## [0.19.1] - 2021-08-09 + +**Added** + +- Add support for Python 3.10. (#359 by [@theskumar]) + +## [0.19.0] - 2021-07-24 + +**Changed** + +- Require Python 3.5 or a later version. Python 2 and 3.4 are no longer supported. (#341 + by [@bbc2]). + +**Added** + +- The `dotenv_path` argument of `set_key` and `unset_key` now has a type of `Union[str, + os.PathLike]` instead of just `os.PathLike` (#347 by [@bbc2]). +- The `stream` argument of `load_dotenv` and `dotenv_values` can now be a text stream + (`IO[str]`), which includes values like `io.StringIO("foo")` and `open("file.env", + "r")` (#348 by [@bbc2]). + +## [0.18.0] - 2021-06-20 + +**Changed** + +- Raise `ValueError` if `quote_mode` isn't one of `always`, `auto` or `never` in + `set_key` (#330 by [@bbc2]). +- When writing a value to a .env file with `set_key` or `dotenv set ` (#330 + by [@bbc2]): + - Use single quotes instead of double quotes. + - Don't strip surrounding quotes. + - In `auto` mode, don't add quotes if the value is only made of alphanumeric characters + (as determined by `string.isalnum`). + +## [0.17.1] - 2021-04-29 + +**Fixed** + +- Fixed tests for build environments relying on `PYTHONPATH` (#318 by [@befeleme]). + +## [0.17.0] - 2021-04-02 + +**Changed** + +- Make `dotenv get ` only show the value, not `key=value` (#313 by [@bbc2]). + +**Added** + +- Add `--override`/`--no-override` option to `dotenv run` (#312 by [@zueve] and [@bbc2]). + +## [0.16.0] - 2021-03-27 + +**Changed** + +- The default value of the `encoding` parameter for `load_dotenv` and `dotenv_values` is + now `"utf-8"` instead of `None` (#306 by [@bbc2]). +- Fix resolution order in variable expansion with `override=False` (#287 by [@bbc2]). + +## [0.15.0] - 2020-10-28 + +**Added** + +- Add `--export` option to `set` to make it prepend the binding with `export` (#270 by + [@jadutter]). + +**Changed** + +- Make `set` command create the `.env` file in the current directory if no `.env` file was + found (#270 by [@jadutter]). + +**Fixed** + +- Fix potentially empty expanded value for duplicate key (#260 by [@bbc2]). +- Fix import error on Python 3.5.0 and 3.5.1 (#267 by [@gongqingkui]). +- Fix parsing of unquoted values containing several adjacent space or tab characters + (#277 by [@bbc2], review by [@x-yuri]). + +## [0.14.0] - 2020-07-03 + +**Changed** + +- Privilege definition in file over the environment in variable expansion (#256 by + [@elbehery95]). + +**Fixed** + +- Improve error message for when file isn't found (#245 by [@snobu]). +- Use HTTPS URL in package meta data (#251 by [@ekohl]). + +## [0.13.0] - 2020-04-16 + +**Added** + +- Add support for a Bash-like default value in variable expansion (#248 by [@bbc2]). + +## [0.12.0] - 2020-02-28 + +**Changed** + +- Use current working directory to find `.env` when bundled by PyInstaller (#213 by + [@gergelyk]). + +**Fixed** + +- Fix escaping of quoted values written by `set_key` (#236 by [@bbc2]). +- Fix `dotenv run` crashing on environment variables without values (#237 by [@yannham]). +- Remove warning when last line is empty (#238 by [@bbc2]). + +## [0.11.0] - 2020-02-07 + +**Added** + +- Add `interpolate` argument to `load_dotenv` and `dotenv_values` to disable interpolation + (#232 by [@ulyssessouza]). + +**Changed** + +- Use logging instead of warnings (#231 by [@bbc2]). + +**Fixed** + +- Fix installation in non-UTF-8 environments (#225 by [@altendky]). +- Fix PyPI classifiers (#228 by [@bbc2]). + +## [0.10.5] - 2020-01-19 + +**Fixed** + +- Fix handling of malformed lines and lines without a value (#222 by [@bbc2]): + - Don't print warning when key has no value. + - Reject more malformed lines (e.g. "A: B", "a='b',c"). +- Fix handling of lines with just a comment (#224 by [@bbc2]). + +## [0.10.4] - 2020-01-17 + +**Added** + +- Make typing optional (#179 by [@techalchemy]). +- Print a warning on malformed line (#211 by [@bbc2]). +- Support keys without a value (#220 by [@ulyssessouza]). + +## 0.10.3 + +- Improve interactive mode detection ([@andrewsmith])([#183]). +- Refactor parser to fix parsing inconsistencies ([@bbc2])([#170]). + - Interpret escapes as control characters only in double-quoted strings. + - Interpret `#` as start of comment only if preceded by whitespace. + +## 0.10.2 + +- Add type hints and expose them to users ([@qnighy])([#172]) +- `load_dotenv` and `dotenv_values` now accept an `encoding` parameter, defaults to `None` + ([@theskumar])([@earlbread])([#161]) +- Fix `str`/`unicode` inconsistency in Python 2: values are always `str` now. ([@bbc2])([#121]) +- Fix Unicode error in Python 2, introduced in 0.10.0. ([@bbc2])([#176]) + +## 0.10.1 +- Fix parsing of variable without a value ([@asyncee])([@bbc2])([#158]) + +## 0.10.0 + +- Add support for UTF-8 in unquoted values ([@bbc2])([#148]) +- Add support for trailing comments ([@bbc2])([#148]) +- Add backslashes support in values ([@bbc2])([#148]) +- Add support for newlines in values ([@bbc2])([#148]) +- Force environment variables to str with Python2 on Windows ([@greyli]) +- Drop Python 3.3 support ([@greyli]) +- Fix stderr/-out/-in redirection ([@venthur]) + + +## 0.9.0 + +- Add `--version` parameter to cli ([@venthur]) +- Enable loading from current directory ([@cjauvin]) +- Add 'dotenv run' command for calling arbitrary shell script with .env ([@venthur]) + +## 0.8.1 + +- Add tests for docs ([@Flimm]) +- Make 'cli' support optional. Use `pip install python-dotenv[cli]`. ([@theskumar]) + +## 0.8.0 + +- `set_key` and `unset_key` only modified the affected file instead of + parsing and re-writing file, this causes comments and other file + entact as it is. +- Add support for `export` prefix in the line. +- Internal refractoring ([@theskumar]) +- Allow `load_dotenv` and `dotenv_values` to work with `StringIO())` ([@alanjds])([@theskumar])([#78]) + +## 0.7.1 + +- Remove hard dependency on iPython ([@theskumar]) + +## 0.7.0 + +- Add support to override system environment variable via .env. + ([@milonimrod](https://github.com/milonimrod)) + ([\#63](https://github.com/theskumar/python-dotenv/issues/63)) +- Disable ".env not found" warning by default + ([@maxkoryukov](https://github.com/maxkoryukov)) + ([\#57](https://github.com/theskumar/python-dotenv/issues/57)) + +## 0.6.5 + +- Add support for special characters `\`. + ([@pjona](https://github.com/pjona)) + ([\#60](https://github.com/theskumar/python-dotenv/issues/60)) + +## 0.6.4 + +- Fix issue with single quotes ([@Flimm]) + ([\#52](https://github.com/theskumar/python-dotenv/issues/52)) + +## 0.6.3 + +- Handle unicode exception in setup.py + ([\#46](https://github.com/theskumar/python-dotenv/issues/46)) + +## 0.6.2 + +- Fix dotenv list command ([@ticosax](https://github.com/ticosax)) +- Add iPython Support + ([@tillahoffmann](https://github.com/tillahoffmann)) + +## 0.6.0 + +- Drop support for Python 2.6 +- Handle escaped characters and newlines in quoted values. (Thanks + [@iameugenejo](https://github.com/iameugenejo)) +- Remove any spaces around unquoted key/value. (Thanks + [@paulochf](https://github.com/paulochf)) +- Added POSIX variable expansion. (Thanks + [@hugochinchilla](https://github.com/hugochinchilla)) + +## 0.5.1 + +- Fix find\_dotenv - it now start search from the file where this + function is called from. + +## 0.5.0 + +- Add `find_dotenv` method that will try to find a `.env` file. + (Thanks [@isms](https://github.com/isms)) + +## 0.4.0 + +- cli: Added `-q/--quote` option to control the behaviour of quotes + around values in `.env`. (Thanks + [@hugochinchilla](https://github.com/hugochinchilla)). +- Improved test coverage. + +[#78]: https://github.com/theskumar/python-dotenv/issues/78 +[#121]: https://github.com/theskumar/python-dotenv/issues/121 +[#148]: https://github.com/theskumar/python-dotenv/issues/148 +[#158]: https://github.com/theskumar/python-dotenv/issues/158 +[#170]: https://github.com/theskumar/python-dotenv/issues/170 +[#172]: https://github.com/theskumar/python-dotenv/issues/172 +[#176]: https://github.com/theskumar/python-dotenv/issues/176 +[#183]: https://github.com/theskumar/python-dotenv/issues/183 +[#359]: https://github.com/theskumar/python-dotenv/issues/359 +[#469]: https://github.com/theskumar/python-dotenv/issues/469 +[#456]: https://github.com/theskumar/python-dotenv/issues/456 +[#466]: https://github.com/theskumar/python-dotenv/issues/466 +[#454]: https://github.com/theskumar/python-dotenv/issues/454 +[#474]: https://github.com/theskumar/python-dotenv/issues/474 + +[@alanjds]: https://github.com/alanjds +[@altendky]: https://github.com/altendky +[@andrewsmith]: https://github.com/andrewsmith +[@asyncee]: https://github.com/asyncee +[@bbc2]: https://github.com/bbc2 +[@befeleme]: https://github.com/befeleme +[@cjauvin]: https://github.com/cjauvin +[@eaf]: https://github.com/eaf +[@earlbread]: https://github.com/earlbread +[@eggplants]: https://github.com/@eggplants +[@ekohl]: https://github.com/ekohl +[@elbehery95]: https://github.com/elbehery95 +[@eumiro]: https://github.com/eumiro +[@Flimm]: https://github.com/Flimm +[@freddyaboulton]: https://github.com/freddyaboulton +[@gergelyk]: https://github.com/gergelyk +[@gongqingkui]: https://github.com/gongqingkui +[@greyli]: https://github.com/greyli +[@harveer07]: https://github.com/@harveer07 +[@jadutter]: https://github.com/jadutter +[@jankislinger]: https://github.com/jankislinger +[@jctanner]: https://github.com/jctanner +[@larsks]: https://github.com/@larsks +[@lsmith77]: https://github.com/lsmith77 +[@mgorny]: https://github.com/mgorny +[@naorlivne]: https://github.com/@naorlivne +[@Nicals]: https://github.com/Nicals +[@Nougat-Waffle]: https://github.com/Nougat-Waffle +[@qnighy]: https://github.com/qnighy +[@Qwerty-133]: https://github.com/Qwerty-133 +[@rabinadk1]: https://github.com/@rabinadk1 +[@sammck]: https://github.com/@sammck +[@samwyma]: https://github.com/samwyma +[@snobu]: https://github.com/snobu +[@techalchemy]: https://github.com/techalchemy +[@theGOTOguy]: https://github.com/theGOTOguy +[@theskumar]: https://github.com/theskumar +[@ulyssessouza]: https://github.com/ulyssessouza +[@venthur]: https://github.com/venthur +[@x-yuri]: https://github.com/x-yuri +[@yannham]: https://github.com/yannham +[@zueve]: https://github.com/zueve + + +[Unreleased]: https://github.com/theskumar/python-dotenv/compare/v1.0.1...HEAD +[1.0.1]: https://github.com/theskumar/python-dotenv/compare/v1.0.0...v1.0.1 +[1.0.0]: https://github.com/theskumar/python-dotenv/compare/v0.21.0...v1.0.0 +[0.21.1]: https://github.com/theskumar/python-dotenv/compare/v0.21.0...v0.21.1 +[0.21.0]: https://github.com/theskumar/python-dotenv/compare/v0.20.0...v0.21.0 +[0.20.0]: https://github.com/theskumar/python-dotenv/compare/v0.19.2...v0.20.0 +[0.19.2]: https://github.com/theskumar/python-dotenv/compare/v0.19.1...v0.19.2 +[0.19.1]: https://github.com/theskumar/python-dotenv/compare/v0.19.0...v0.19.1 +[0.19.0]: https://github.com/theskumar/python-dotenv/compare/v0.18.0...v0.19.0 +[0.18.0]: https://github.com/theskumar/python-dotenv/compare/v0.17.1...v0.18.0 +[0.17.1]: https://github.com/theskumar/python-dotenv/compare/v0.17.0...v0.17.1 +[0.17.0]: https://github.com/theskumar/python-dotenv/compare/v0.16.0...v0.17.0 +[0.16.0]: https://github.com/theskumar/python-dotenv/compare/v0.15.0...v0.16.0 +[0.15.0]: https://github.com/theskumar/python-dotenv/compare/v0.14.0...v0.15.0 +[0.14.0]: https://github.com/theskumar/python-dotenv/compare/v0.13.0...v0.14.0 +[0.13.0]: https://github.com/theskumar/python-dotenv/compare/v0.12.0...v0.13.0 +[0.12.0]: https://github.com/theskumar/python-dotenv/compare/v0.11.0...v0.12.0 +[0.11.0]: https://github.com/theskumar/python-dotenv/compare/v0.10.5...v0.11.0 +[0.10.5]: https://github.com/theskumar/python-dotenv/compare/v0.10.4...v0.10.5 +[0.10.4]: https://github.com/theskumar/python-dotenv/compare/v0.10.3...v0.10.4 diff --git a/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/RECORD b/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/RECORD new file mode 100644 index 00000000..a63bcb9d --- /dev/null +++ b/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/RECORD @@ -0,0 +1,26 @@ +../../Scripts/dotenv.exe,sha256=YRCcm6xHhO6_Iiv70DTSA7aqz5sdqV3_qn_5sRFlj30,108410 +dotenv/__init__.py,sha256=WBU5SfSiKAhS3hzu17ykNuuwbuwyDCX91Szv4vUeOuM,1292 +dotenv/__main__.py,sha256=N0RhLG7nHIqtlJHwwepIo-zbJPNx9sewCCRGY528h_4,129 +dotenv/__pycache__/__init__.cpython-311.pyc,, +dotenv/__pycache__/__main__.cpython-311.pyc,, +dotenv/__pycache__/cli.cpython-311.pyc,, +dotenv/__pycache__/ipython.cpython-311.pyc,, +dotenv/__pycache__/main.cpython-311.pyc,, +dotenv/__pycache__/parser.cpython-311.pyc,, +dotenv/__pycache__/variables.cpython-311.pyc,, +dotenv/__pycache__/version.cpython-311.pyc,, +dotenv/cli.py,sha256=_ttQuR9Yl4k1PT53ByISkDjJ3kO_N_LzIDZzZ95uXEk,5809 +dotenv/ipython.py,sha256=avI6aez_RxnBptYgchIquF2TSgKI-GOhY3ppiu3VuWE,1303 +dotenv/main.py,sha256=GV7Ki6JYPDa-xy2ZXHKqER-bRvKa7qqh0G0OwffYJr8,12098 +dotenv/parser.py,sha256=QgU5HwMwM2wMqt0vz6dHTJ4nzPmwqRqvi4MSyeVifgU,5186 +dotenv/py.typed,sha256=8PjyZ1aVoQpRVvt71muvuq5qE-jTFZkK-GLHkhdebmc,26 +dotenv/variables.py,sha256=CD0qXOvvpB3q5RpBQMD9qX6vHX7SyW-SuiwGMFSlt08,2348 +dotenv/version.py,sha256=d4QHYmS_30j0hPN8NmNPnQ_Z0TphDRbu4MtQj9cT9e8,22 +python_dotenv-1.0.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +python_dotenv-1.0.1.dist-info/LICENSE,sha256=gGGbcEnwjIFoOtDgHwjyV6hAZS3XHugxRtNmWMfSwrk,1556 +python_dotenv-1.0.1.dist-info/METADATA,sha256=fCkcTEUG3zknbuN1BK8e0PPCIgvPBLk-LneK0mRDM_s,23170 +python_dotenv-1.0.1.dist-info/RECORD,, +python_dotenv-1.0.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +python_dotenv-1.0.1.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92 +python_dotenv-1.0.1.dist-info/entry_points.txt,sha256=yRl1rCbswb1nQTQ_gZRlCw5QfabztUGnfGWLhlXFNdI,47 +python_dotenv-1.0.1.dist-info/top_level.txt,sha256=eyqUH4SHJNr6ahOYlxIunTr4XinE8Z5ajWLdrK3r0D8,7 diff --git a/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/REQUESTED b/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/REQUESTED new file mode 100644 index 00000000..e69de29b diff --git a/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/WHEEL b/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/WHEEL new file mode 100644 index 00000000..98c0d20b --- /dev/null +++ b/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.42.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/entry_points.txt b/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/entry_points.txt new file mode 100644 index 00000000..0a868232 --- /dev/null +++ b/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[console_scripts] +dotenv = dotenv.__main__:cli diff --git a/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/top_level.txt b/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/top_level.txt new file mode 100644 index 00000000..fe7c01aa --- /dev/null +++ b/.venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/top_level.txt @@ -0,0 +1 @@ +dotenv diff --git a/.venv/Scripts/dotenv.exe b/.venv/Scripts/dotenv.exe new file mode 100644 index 0000000000000000000000000000000000000000..9f330ce0f5ae68e86b9858abaa85dfd985699036 GIT binary patch literal 108410 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 X-1y00grQ=bzu7_`tp}=3v0nWTA00WC literal 0 HcmV?d00001 diff --git a/__pycache__/webapp.cpython-311.pyc b/__pycache__/webapp.cpython-311.pyc index 649e02f7cc0afc065042289c5838cdb79dfd0821..7c811476cdaeb148a6953d6f74aa5fcea74a3f92 100644 GIT binary patch literal 5491 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 diff --git a/server.py b/server.py deleted file mode 100644 index cc0d1e6c..00000000 --- a/server.py +++ /dev/null @@ -1,60 +0,0 @@ -import json -from os import environ as env -from urllib.parse import quote_plus, urlencode - -from authlib.integrations.flask_client import OAuth -from dotenv import find_dotenv, load_dotenv -from flask import Flask, redirect, render_template, session, url_for - -ENV_FILE = find_dotenv() -if ENV_FILE: - load_dotenv(ENV_FILE) - -app = Flask(__name__) -app.secret_key = env.get("APP_SECRET_KEY") - -oauth = OAuth(app) - -oauth.register( - "auth0", - client_id=env.get("AUTH0_CLIENT_ID"), - client_secret=env.get("AUTH0_CLIENT_SECRET"), - client_kwargs={ - "scope": "openid profile email", - }, - server_metadata_url=f'https://{env.get("AUTH0_DOMAIN")}/.well-known/openid-configuration' -) - -@app.route("/login") -def login(): - return oauth.auth0.authorize_redirect( - redirect_uri=url_for("callback", _external=True) - ) - -@app.route("/callback", methods=["GET", "POST"]) -def callback(): - token = oauth.auth0.authorize_access_token() - session["user"] = token - return redirect("/") - -@app.route("/logout") -def logout(): - session.clear() - return redirect( - "https://" + env.get("AUTH0_DOMAIN") - + "/v2/logout?" - + urlencode( - { - "returnTo": url_for("home", _external=True), - "client_id": env.get("AUTH0_CLIENT_ID"), - }, - quote_via=quote_plus, - ) - ) - -@app.route("/") -def home(): - return render_template("home.html", session=session.get('user'), pretty=json.dumps(session.get('user'), indent=4)) - -if __name__ == "__main__": - app.run(host="0.0.0.0", port=env.get("PORT", 3000)) \ No newline at end of file diff --git a/templates/home.html b/templates/home.html index 30a5dde9..9c0bb488 100644 --- a/templates/home.html +++ b/templates/home.html @@ -8,13 +8,14 @@ {% if session %} -

    Welcome {{session.userinfo.name}}!

    -

    Logout

    -
    {{pretty}}
    - {% else %} -

    Welcome Guest

    -

    Login

    - {% endif %} +

    Welcome {{ session.userinfo.name }}!

    +

    Logout

    + {% else %} +

    Welcome to Rememberescence

    +

    Login to get started!

    + {% endif %} + +

    Flask Cohere App

    diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 00000000..8be47262 --- /dev/null +++ b/templates/login.html @@ -0,0 +1,12 @@ + + + + + + Flask Cohere App + + +

    Welcome to Rememberescence

    +

    Login to get started!

    + + \ No newline at end of file diff --git a/webapp.py b/webapp.py index ba4eab22..8a2da4ab 100644 --- a/webapp.py +++ b/webapp.py @@ -3,6 +3,13 @@ import os import spotipy from spotipy.oauth2 import SpotifyClientCredentials +import json +from os import environ as env +from urllib.parse import quote_plus, urlencode + +from authlib.integrations.flask_client import OAuth +from dotenv import find_dotenv, load_dotenv +from flask import Flask, redirect, render_template, session, url_for app = Flask(__name__) @@ -16,9 +23,59 @@ client_secret='8ce1ad629229430ab7d2d7278ebdb9bd') sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) + +ENV_FILE = find_dotenv() +if ENV_FILE: + load_dotenv(ENV_FILE) + +app = Flask(__name__) +app.secret_key = env.get("APP_SECRET_KEY") + +oauth = OAuth(app) + +oauth.register( + "auth0", + client_id=env.get("AUTH0_CLIENT_ID"), + client_secret=env.get("AUTH0_CLIENT_SECRET"), + client_kwargs={ + "scope": "openid profile email", + }, + server_metadata_url=f'https://{env.get("AUTH0_DOMAIN")}/.well-known/openid-configuration' +) + +@app.route("/login") +def login(): + return oauth.auth0.authorize_redirect( + redirect_uri=url_for("callback", _external=True) + ) + +@app.route("/callback", methods=["GET", "POST"]) +def callback(): + token = oauth.auth0.authorize_access_token() + session["user"] = token + return redirect("/") + +@app.route("/logout") +def logout(): + session.clear() + return redirect( + "https://" + env.get("AUTH0_DOMAIN") + + "/v2/logout?" + + urlencode( + { + "returnTo": url_for("home", _external=True), + "client_id": env.get("AUTH0_CLIENT_ID"), + }, + quote_via=quote_plus, + ) + ) + @app.route("/") def home(): - return render_template("home.html") + if session.get('user'): + return render_template("home.html", session=session.get('user'), pretty=json.dumps(session.get('user'), indent=4)) + else: + return render_template("login.html") @app.route("/generate", methods=["POST"]) def generate_content(): @@ -35,7 +92,7 @@ def generate_content(): # Use Cohere to generate content based on user inputs parameters = f'Friends:{user_friends}, Interests: {user_interests}, Location: {user_location}' generation_response = co.generate( - prompt=f'Please write a short story for nostalgia based on these parameters: {parameters} addressing the user as "you"' + prompt=f'Please write a nostalgic short story about the users childhood based on these parameters: {parameters} addressing the user as "you"' ) # User's age & location used for childhood Spotify From ff292219d95d4dc7a002f4d26526b8e432c58d88 Mon Sep 17 00:00:00 2001 From: Yihoi Jung Date: Sat, 27 Jan 2024 16:17:15 -0500 Subject: [PATCH 05/16] Update on UI for New Question --- __pycache__/webapp.cpython-311.pyc | Bin 5491 -> 6240 bytes templates/home.html | 41 +++++++++++++++++++++-------- webapp.py | 15 +++++++++++ 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/__pycache__/webapp.cpython-311.pyc b/__pycache__/webapp.cpython-311.pyc index 7c811476cdaeb148a6953d6f74aa5fcea74a3f92..e16d30f5b990a747b1dbe6e89373c1a412c4c4cf 100644 GIT binary patch delta 796 zcmY*XO=uHA6rTObw&bU=3Bg^AGAh_?n`#^Fp`qX}Qkz;7i%>e-pb`14@Cc|YHK^WMyC_kJAcdJziw z0hLeA26`KQ+9mTqe4V%_5Sy2|L!=_a4)#0%E0pny(RSoY63Ip)&ocwdNLlVD7ei4W zFx0hPQWX@gZ~cpq3~(>W?(jM{O5TMN+$8xP{tV|jj$m}%v{1HHsf8ll1iH50kQ34# z@-vu}4Zg%Z1JC(+-jn`Pmqm6^8I<@nVTGeD(bbZ9p(Gfh(l)^jUt66Qy--^R!0?qs zllwpS5>TZHJW5G(cTedqGN5fiFK4>Y&Dq$4u4m&rNtm?@2o@bUTQci)m&gN+NS-ykqg5xz}|JKqlavj^E4PK@^ zm(_(#u*%Yct;f-JCdO0Lm1iuQLIrFEB9BKZXPQzOD0`PW7dxx_kJaR%x;#`BV@(M} zvV0SO3%t&@mO-&H_94D+DYKYaomAcn;G3F^9pD%22VBail?jvpnOV%YSw{3J(`0=KLjXGnC7%EQ diff --git a/templates/home.html b/templates/home.html index 9c0bb488..9bb14c61 100644 --- a/templates/home.html +++ b/templates/home.html @@ -8,14 +8,12 @@ {% if session %} -

    Welcome {{ session.userinfo.name }}!

    -

    Logout

    - {% else %} -

    Welcome to Rememberescence

    -

    Login to get started!

    - {% endif %} - - +

    Welcome {{session.userinfo.name}}!

    +

    Logout

    + {% else %} +

    Welcome to Rememberescence

    +

    Login to get started!

    + {% endif %}

    Flask Cohere App

    @@ -45,9 +43,11 @@

    Flask Cohere App


    +
    + - + function refineStory() { + var generatedContent = document.getElementById("resultContainer").getAttribute("data-generated-content"); + + fetch('/refine', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ generated_content: generatedContent }), + }) + .then(response => response.json()) + .then(data => { + console.log('New question received:', data.new_question); + // Update the UI to display the new question + document.getElementById("resultContainer").innerHTML += '

    New Question:

    ' + data.new_question + '

    '; + }) + .catch(error => console.error('Error:', error)); + } + - \ No newline at end of file + diff --git a/webapp.py b/webapp.py index 8a2da4ab..549fc766 100644 --- a/webapp.py +++ b/webapp.py @@ -104,5 +104,20 @@ def generate_content(): # Return the JSON response with the generated content return jsonify({"generated_content": generated_content}) +@app.route("/refine", methods=["POST"]) +def refine_story(): + data = request.json + + # Get the previously generated content from the JSON data + generated_content = data.get("generated_content") + + # Use Cohere to generate a new question based on the generated content + new_prompt = f'Based on this short story, come up with 1 short question to ask the user to get another parameter to put back into cohere: {generated_content}' + new_question_response = co.generate(prompt=new_prompt) + new_question = new_question_response[0].text + + # Return the new question as JSON response + return jsonify({"new_question": new_question}) + if __name__ == '__main__': app.run(debug=True) \ No newline at end of file From 6b345ed0af612f4ba07f713c6fbb1011bc2bf110 Mon Sep 17 00:00:00 2001 From: Arianne Ghislaine Rull Date: Sat, 27 Jan 2024 17:40:19 -0500 Subject: [PATCH 06/16] add style --- __pycache__/webapp.cpython-310.pyc | Bin 0 -> 3545 bytes tailwind.config.js | 9 + templates/home.html | 341 ++++++++++++-- templates/input.css | 3 + templates/output.css | 717 +++++++++++++++++++++++++++++ 5 files changed, 1029 insertions(+), 41 deletions(-) create mode 100644 __pycache__/webapp.cpython-310.pyc create mode 100644 tailwind.config.js create mode 100644 templates/input.css create mode 100644 templates/output.css diff --git a/__pycache__/webapp.cpython-310.pyc b/__pycache__/webapp.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0d98b8472117e15d8236fb21b3aecb32be6b4d8d GIT binary patch literal 3545 zcmZ`+TT>g!6`t<7Xe5Nd26OXm@Lg++02?rrYd09{wZWinDXV#HjuJuL_d zJUOrYf{m--(LW&nBhUSss#NVyh*P!XbdO|=lZcw0)7__g`h4d*=QK%we?fzvx&Jr% zYCzNeAv<6G^3eGWJn7$&rV)*xP>Ya@BJAQwclF3{4J5~LXu76)Tdt+vIX4GyJ+z~| zoA2rr+yaalp%wMHMKxxI{ZYv+MFZ}D>RaJpbjiJ>va>q&DouF4qflmCaeZcP#%$O(F=)@^QTE*VramtaO}Ts}o) zhztjaTv7dzQ}nY&MnC9e?AU}8jGx>i91Fpw<}W?D~Lv@;A%91y3)lI@K`i^J%@Z zlSH)QvvwF(UL^H)1msLB?PQzpzz5UH4>Y1tjWU|nfsypT`unuzw_4M!17Ru~r(x^V zg2uuHWSz15Aa?SVo&`ex?b?Gjhf9BE zDbbL5S(v09wbK7(H>-f^Iy_zX-$6E3V?f~sjVZ)Gy9APEtAn8gnKr*;~XviW;%tHgppmivVVeSw^LAH)eZZu6|ADS?hhXPqRMn~46 zMf%3IrgfA9;uH^a0a7saS4BREAumAnNrfFIb(N`v4oOtxwi%Qjl6LHunXugHpK{iF z>dQ{2IOV+RE`grA0jx=>v(Exf9p8zQl>1>Ls5>bn6z-%vVF!+1gJ^L04s~P%rcQk) z2+2;85T^!OoO=bd9mZC&aH!_ed{B*6|!{H;!LIi zaj6G7@gM_3;p4z;>3_B)8|heKwisA0a6J)rPhA)svLrKMzHAFaCSp;N$MnuY>R0{G zNZG0@;VLSriJXaPjVhZDtrce2k9Mq1C&x3w~!X~0+N3= z9?=bWTW1BksI%8F2}y=gsPY#%CauunQ5<^)!q*%lSn}orK7z#3G!A9;kSv360;ZV2 zGE4HS%M`1sPTcwP^K&l+>6f0Ja_SIkPP^so2Yknw?ary24Os5*1pKvo?mXy2R&o3| z0e`b|cT2?Au(7x}5vUxlG#3UdU!mHp-zUdnsj! zyC}%z8DqqiFSk1PPgN>^st!05%$S!bd z`EB(HMjJs2fi6r2xq+(Uuc~KOBxG_`JkP+@Sv&s1G0H_MdhBOWLfRqyR_1{8kI;;1 zvJl%)g5)!Zig*xRg9tM85_rqdF+@=jTM$p6g+U7&P_X0*c%KdG*1zmR0S%fEb@C|{ OP|1R4Ldt{4IQtJMp|Mo} literal 0 HcmV?d00001 diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 00000000..80af1a8e --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,9 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ["./templates/*.{html,js}"], + theme: { + extend: {}, + }, + plugins: [], +} + diff --git a/templates/home.html b/templates/home.html index 9bb14c61..54971986 100644 --- a/templates/home.html +++ b/templates/home.html @@ -4,50 +4,197 @@ Flask Cohere App + + - - - {% if session %} -

    Welcome {{session.userinfo.name}}!

    -

    Logout

    - {% else %} -

    Welcome to Rememberescence

    -

    Login to get started!

    - {% endif %} - -

    Flask Cohere App

    - -
    - -
    - - -
    + + + + +
    + {% if session %} +

    Welcome {{session.userinfo.name}}!

    +

    Logout

    + {% else %} +

    Welcome to Rememberescence

    +

    Login to get started!

    + {% endif %} + +

    Flask Cohere App

    - -
    - - -
    - - + + + + + + + + + + + + + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/input.css b/templates/input.css new file mode 100644 index 00000000..bd6213e1 --- /dev/null +++ b/templates/input.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; \ No newline at end of file diff --git a/templates/output.css b/templates/output.css new file mode 100644 index 00000000..bc406f35 --- /dev/null +++ b/templates/output.css @@ -0,0 +1,717 @@ +/* +! tailwindcss v3.4.1 | MIT License | https://tailwindcss.com +*/ + +/* +1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) +2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) +*/ + +*, +::before, +::after { + box-sizing: border-box; + /* 1 */ + border-width: 0; + /* 2 */ + border-style: solid; + /* 2 */ + border-color: #e5e7eb; + /* 2 */ +} + +::before, +::after { + --tw-content: ''; +} + +/* +1. Use a consistent sensible line-height in all browsers. +2. Prevent adjustments of font size after orientation changes in iOS. +3. Use a more readable tab size. +4. Use the user's configured `sans` font-family by default. +5. Use the user's configured `sans` font-feature-settings by default. +6. Use the user's configured `sans` font-variation-settings by default. +7. Disable tap highlights on iOS +*/ + +html, +:host { + line-height: 1.5; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ + -moz-tab-size: 4; + /* 3 */ + -o-tab-size: 4; + tab-size: 4; + /* 3 */ + font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + /* 4 */ + font-feature-settings: normal; + /* 5 */ + font-variation-settings: normal; + /* 6 */ + -webkit-tap-highlight-color: transparent; + /* 7 */ +} + +/* +1. Remove the margin in all browsers. +2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. +*/ + +body { + margin: 0; + /* 1 */ + line-height: inherit; + /* 2 */ +} + +/* +1. Add the correct height in Firefox. +2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) +3. Ensure horizontal rules are visible by default. +*/ + +hr { + height: 0; + /* 1 */ + color: inherit; + /* 2 */ + border-top-width: 1px; + /* 3 */ +} + +/* +Add the correct text decoration in Chrome, Edge, and Safari. +*/ + +abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} + +/* +Remove the default font size and weight for headings. +*/ + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} + +/* +Reset links to optimize for opt-in styling instead of opt-out. +*/ + +a { + color: inherit; + text-decoration: inherit; +} + +/* +Add the correct font weight in Edge and Safari. +*/ + +b, +strong { + font-weight: bolder; +} + +/* +1. Use the user's configured `mono` font-family by default. +2. Use the user's configured `mono` font-feature-settings by default. +3. Use the user's configured `mono` font-variation-settings by default. +4. Correct the odd `em` font sizing in all browsers. +*/ + +code, +kbd, +samp, +pre { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + /* 1 */ + font-feature-settings: normal; + /* 2 */ + font-variation-settings: normal; + /* 3 */ + font-size: 1em; + /* 4 */ +} + +/* +Add the correct font size in all browsers. +*/ + +small { + font-size: 80%; +} + +/* +Prevent `sub` and `sup` elements from affecting the line height in all browsers. +*/ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* +1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) +2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) +3. Remove gaps between table borders by default. +*/ + +table { + text-indent: 0; + /* 1 */ + border-color: inherit; + /* 2 */ + border-collapse: collapse; + /* 3 */ +} + +/* +1. Change the font styles in all browsers. +2. Remove the margin in Firefox and Safari. +3. Remove default padding in all browsers. +*/ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + /* 1 */ + font-feature-settings: inherit; + /* 1 */ + font-variation-settings: inherit; + /* 1 */ + font-size: 100%; + /* 1 */ + font-weight: inherit; + /* 1 */ + line-height: inherit; + /* 1 */ + color: inherit; + /* 1 */ + margin: 0; + /* 2 */ + padding: 0; + /* 3 */ +} + +/* +Remove the inheritance of text transform in Edge and Firefox. +*/ + +button, +select { + text-transform: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Remove default button styles. +*/ + +button, +[type='button'], +[type='reset'], +[type='submit'] { + -webkit-appearance: button; + /* 1 */ + background-color: transparent; + /* 2 */ + background-image: none; + /* 2 */ +} + +/* +Use the modern Firefox focus style for all focusable elements. +*/ + +:-moz-focusring { + outline: auto; +} + +/* +Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) +*/ + +:-moz-ui-invalid { + box-shadow: none; +} + +/* +Add the correct vertical alignment in Chrome and Firefox. +*/ + +progress { + vertical-align: baseline; +} + +/* +Correct the cursor style of increment and decrement buttons in Safari. +*/ + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +/* +1. Correct the odd appearance in Chrome and Safari. +2. Correct the outline style in Safari. +*/ + +[type='search'] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ +} + +/* +Remove the inner padding in Chrome and Safari on macOS. +*/ + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Change font properties to `inherit` in Safari. +*/ + +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ +} + +/* +Add the correct display in Chrome and Safari. +*/ + +summary { + display: list-item; +} + +/* +Removes the default spacing and border for appropriate elements. +*/ + +blockquote, +dl, +dd, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +figure, +p, +pre { + margin: 0; +} + +fieldset { + margin: 0; + padding: 0; +} + +legend { + padding: 0; +} + +ol, +ul, +menu { + list-style: none; + margin: 0; + padding: 0; +} + +/* +Reset default styling for dialogs. +*/ + +dialog { + padding: 0; +} + +/* +Prevent resizing textareas horizontally by default. +*/ + +textarea { + resize: vertical; +} + +/* +1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) +2. Set the default placeholder color to the user's configured gray 400 color. +*/ + +input::-moz-placeholder, textarea::-moz-placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +input::placeholder, +textarea::placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +/* +Set the default cursor for buttons. +*/ + +button, +[role="button"] { + cursor: pointer; +} + +/* +Make sure disabled buttons don't get the pointer cursor. +*/ + +:disabled { + cursor: default; +} + +/* +1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) +2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) + This can trigger a poorly considered lint error in some tools but is included by design. +*/ + +img, +svg, +video, +canvas, +audio, +iframe, +embed, +object { + display: block; + /* 1 */ + vertical-align: middle; + /* 2 */ +} + +/* +Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) +*/ + +img, +video { + max-width: 100%; + height: auto; +} + +/* Make elements with the HTML hidden attribute stay hidden by default */ + +[hidden] { + display: none; +} + +*, ::before, ::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} + +::backdrop { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} + +.container { + width: 100%; +} + +@media (min-width: 640px) { + .container { + max-width: 640px; + } +} + +@media (min-width: 768px) { + .container { + max-width: 768px; + } +} + +@media (min-width: 1024px) { + .container { + max-width: 1024px; + } +} + +@media (min-width: 1280px) { + .container { + max-width: 1280px; + } +} + +@media (min-width: 1536px) { + .container { + max-width: 1536px; + } +} + +.mx-auto { + margin-left: auto; + margin-right: auto; +} + +.mb-4 { + margin-bottom: 1rem; +} + +.mt-4 { + margin-top: 1rem; +} + +.mt-8 { + margin-top: 2rem; +} + +.block { + display: block; +} + +.flex { + display: flex; +} + +.min-h-screen { + min-height: 100vh; +} + +.w-full { + width: 100%; +} + +.grow { + flex-grow: 1; +} + +.items-center { + align-items: center; +} + +.justify-center { + justify-content: center; +} + +.space-y-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(1rem * var(--tw-space-y-reverse)); +} + +.rounded { + border-radius: 0.25rem; +} + +.bg-blue-500 { + --tw-bg-opacity: 1; + background-color: rgb(59 130 246 / var(--tw-bg-opacity)); +} + +.bg-white { + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); +} + +.bg-gradient-to-r { + background-image: linear-gradient(to right, var(--tw-gradient-stops)); +} + +.from-pink-500 { + --tw-gradient-from: #ec4899 var(--tw-gradient-from-position); + --tw-gradient-to: rgb(236 72 153 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); +} + +.via-purple-500 { + --tw-gradient-to: rgb(168 85 247 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), #a855f7 var(--tw-gradient-via-position), var(--tw-gradient-to); +} + +.to-indigo-500 { + --tw-gradient-to: #6366f1 var(--tw-gradient-to-position); +} + +.px-4 { + padding-left: 1rem; + padding-right: 1rem; +} + +.py-2 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.text-2xl { + font-size: 1.5rem; + line-height: 2rem; +} + +.text-3xl { + font-size: 1.875rem; + line-height: 2.25rem; +} + +.text-4xl { + font-size: 2.25rem; + line-height: 2.5rem; +} + +.font-bold { + font-weight: 700; +} + +.text-black { + --tw-text-opacity: 1; + color: rgb(0 0 0 / var(--tw-text-opacity)); +} + +.text-blue-300 { + --tw-text-opacity: 1; + color: rgb(147 197 253 / var(--tw-text-opacity)); +} + +.text-white { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} + +.hover\:bg-blue-400:hover { + --tw-bg-opacity: 1; + background-color: rgb(96 165 250 / var(--tw-bg-opacity)); +} + +.hover\:text-blue-100:hover { + --tw-text-opacity: 1; + color: rgb(219 234 254 / var(--tw-text-opacity)); +} \ No newline at end of file From 20050ec15eb69a15815887eff1ef2d6af8d24035 Mon Sep 17 00:00:00 2001 From: Arianne Ghislaine Rull Date: Sat, 27 Jan 2024 18:09:28 -0500 Subject: [PATCH 07/16] remove comments --- templates/home.html | 216 -------------------------------------------- 1 file changed, 216 deletions(-) diff --git a/templates/home.html b/templates/home.html index 54971986..847ac6be 100644 --- a/templates/home.html +++ b/templates/home.html @@ -138,219 +138,3 @@

    New Question:

    - - - - - - - - - - - - - - - - - - - - - - - - From 3fb4ab6e24838470c2ab6e6602310f3ff2e9dd8a Mon Sep 17 00:00:00 2001 From: Arianne Ghislaine Rull Date: Sat, 27 Jan 2024 18:20:23 -0500 Subject: [PATCH 08/16] fix the spacing --- templates/home.html | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/templates/home.html b/templates/home.html index 847ac6be..4a26de7a 100644 --- a/templates/home.html +++ b/templates/home.html @@ -4,6 +4,7 @@ Flask Cohere App + @@ -20,29 +21,35 @@

    Welcome to Rememberescence

    Login to get started!

    {% endif %} -

    Flask Cohere App

    + +

    Flask Cohere App

    +
    +
    - + +
    +
    +
    From f1748ffa9ef1aa01cb49505a7b91f8718286f591 Mon Sep 17 00:00:00 2001 From: Arianne Ghislaine Rull Date: Sat, 27 Jan 2024 18:35:10 -0500 Subject: [PATCH 09/16] remove unnecessary link href --- templates/home.html | 2 -- 1 file changed, 2 deletions(-) diff --git a/templates/home.html b/templates/home.html index 4a26de7a..4498ce0c 100644 --- a/templates/home.html +++ b/templates/home.html @@ -4,8 +4,6 @@ Flask Cohere App - - From 5616020e9f91a8239c746cd69b4c5fb534f5036d Mon Sep 17 00:00:00 2001 From: Arianne Ghislaine Rull Date: Sat, 27 Jan 2024 20:35:05 -0500 Subject: [PATCH 10/16] update stuff --- templates/home.html | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/templates/home.html b/templates/home.html index 4498ce0c..6140d9e6 100644 --- a/templates/home.html +++ b/templates/home.html @@ -8,17 +8,22 @@ -
    {% if session %}

    Welcome {{session.userinfo.name}}!

    Logout

    - {% else %} -

    Welcome to Rememberescence

    -

    Login to get started!

    - {% endif %} + + {% else %} +
    +

    Welcome to Rememberescence

    +

    Login to get started!

    + +
    + {% endif %}

    Flask Cohere App

    From b3918ce1008cf5d98096ab82983cefa18aa82cde Mon Sep 17 00:00:00 2001 From: Arianne Ghislaine Rull Date: Sat, 27 Jan 2024 21:11:50 -0500 Subject: [PATCH 11/16] add styles --- templates/home.html | 4 - templates/login.html | 286 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 283 insertions(+), 7 deletions(-) diff --git a/templates/home.html b/templates/home.html index 6140d9e6..298e70f6 100644 --- a/templates/home.html +++ b/templates/home.html @@ -7,7 +7,6 @@ -
    {% if session %} @@ -19,9 +18,6 @@

    Welcome {{session.userinfo.name}}!

    Welcome to Rememberescence

    Login to get started!

    -
    {% endif %} diff --git a/templates/login.html b/templates/login.html index 8be47262..75e66737 100644 --- a/templates/login.html +++ b/templates/login.html @@ -1,12 +1,292 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Flask Cohere App + + + - -

    Welcome to Rememberescence

    -

    Login to get started!

    + + + + +
    +

    Welcome to Rememberescence

    +

    Discover and share your memories with others.

    + Get Started +
    + +
    +

    About Rememberescence

    +

    Rememberescence is a platform that allows you to discover and share your memories with others. By answering a few simple questions, we can generate a unique story that captures your childhood memories. Sign up now to get started!

    + Sign Up +
    \ No newline at end of file From 61ae6c1dd896cc772e1513d7da017ccbfbc699d0 Mon Sep 17 00:00:00 2001 From: Arianne Ghislaine Rull Date: Sat, 27 Jan 2024 21:27:34 -0500 Subject: [PATCH 12/16] update stuff --- templates/about.html | 111 +++++++++++++++++++++++++++++++++++++++++++ templates/login.html | 4 +- 2 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 templates/about.html diff --git a/templates/about.html b/templates/about.html new file mode 100644 index 00000000..162f810b --- /dev/null +++ b/templates/about.html @@ -0,0 +1,111 @@ + + + + + + About Rememberescence + + + + + + + + +
    +

    About Rememberescence

    +

    Rememberescence is a platform that allows you to discover and share your memories with others. By answering a few simple questions, we can generate a unique story that captures your childhood memories. Sign up now to get started!

    + Sign Up +
    + + \ No newline at end of file diff --git a/templates/login.html b/templates/login.html index 75e66737..dd88f1dc 100644 --- a/templates/login.html +++ b/templates/login.html @@ -272,8 +272,8 @@

    About Rememberescence

    From 7ff44ec5da229cb53acc58a8ee1e9a82fff51c33 Mon Sep 17 00:00:00 2001 From: Arianne Ghislaine Rull Date: Sat, 27 Jan 2024 21:53:27 -0500 Subject: [PATCH 13/16] update stuff --- templates/home copy.html | 146 ++++++++++++++++++ templates/login copy 2.html | 160 ++++++++++++++++++++ templates/login copy.html | 292 ++++++++++++++++++++++++++++++++++++ templates/login.html | 133 ---------------- templates/testerLog.html | 76 ++++++++++ 5 files changed, 674 insertions(+), 133 deletions(-) create mode 100644 templates/home copy.html create mode 100644 templates/login copy 2.html create mode 100644 templates/login copy.html create mode 100644 templates/testerLog.html diff --git a/templates/home copy.html b/templates/home copy.html new file mode 100644 index 00000000..298e70f6 --- /dev/null +++ b/templates/home copy.html @@ -0,0 +1,146 @@ + + + + + + Flask Cohere App + + + + +
    + {% if session %} +

    Welcome {{session.userinfo.name}}!

    +

    Logout

    + + + {% else %} +
    +

    Welcome to Rememberescence

    +

    Login to get started!

    +
    + {% endif %} + + +

    Flask Cohere App

    + +
    + + +
    + + +
    + + +
    + + +
    + + +
    + +
    + +
    + + + + + diff --git a/templates/login copy 2.html b/templates/login copy 2.html new file mode 100644 index 00000000..3f2e5775 --- /dev/null +++ b/templates/login copy 2.html @@ -0,0 +1,160 @@ + + + + + + + + Flask Cohere App + + + + + + + + +
    +

    Welcome to Rememberescence

    +

    Discover and share your memories with others.

    + Get Started +
    + +
    +

    About Rememberescence

    +

    Rememberescence is a platform that allows you to discover and share your memories with others. By answering a few simple questions, we can generate a unique story that captures your childhood memories. Sign up now to get started!

    + Sign Up +
    + + \ No newline at end of file diff --git a/templates/login copy.html b/templates/login copy.html new file mode 100644 index 00000000..dd88f1dc --- /dev/null +++ b/templates/login copy.html @@ -0,0 +1,292 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Flask Cohere App + + + + + + + + +
    +

    Welcome to Rememberescence

    +

    Discover and share your memories with others.

    + Get Started +
    + +
    +

    About Rememberescence

    +

    Rememberescence is a platform that allows you to discover and share your memories with others. By answering a few simple questions, we can generate a unique story that captures your childhood memories. Sign up now to get started!

    + Sign Up +
    + + \ No newline at end of file diff --git a/templates/login.html b/templates/login.html index dd88f1dc..40f6e71f 100644 --- a/templates/login.html +++ b/templates/login.html @@ -1,136 +1,3 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/templates/testerLog.html b/templates/testerLog.html new file mode 100644 index 00000000..dbafd630 --- /dev/null +++ b/templates/testerLog.html @@ -0,0 +1,76 @@ + + + + + + Flask Cohere App - Login + + + + + +
    +

    Login

    +
    + + + + + +
    + +

    Don't have an account? Sign up

    +
    + + + + \ No newline at end of file From ebc59b21ecfa5879b76a41d5ee44fd230c0065f6 Mon Sep 17 00:00:00 2001 From: Arianne Ghislaine Rull Date: Sat, 27 Jan 2024 23:08:10 -0500 Subject: [PATCH 14/16] add styles --- templates/about.html | 6 +++--- templates/login copy 2.html | 2 +- templates/login.html | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/templates/about.html b/templates/about.html index 162f810b..edb9b166 100644 --- a/templates/about.html +++ b/templates/about.html @@ -9,7 +9,7 @@

    3<`Th2=Hth4m90 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%0Dszn71rEs|~&(`1~ z8qYq54{R*K#4iv?$w}6S^pwnow8nA$Z7CQz@$4@ulY+y_KWyB{zf%yx_hnl7cbqST zk$-qH$Ft9-g6K$0-Li`#$gS1vW{71t}H{d;@OXYxy-IXGc#8$od(a$DJc2twt+9c zbL$5ujo=6s_txBI<587&3CB28B1OWgSvhs_xZUv>$V>y1wL>wAXU_y88cKmV^B~a- zV(Bj*$5eS9gC2SIOP8r$8*w`8-CF4%A{|n^ZBRO5${U+jqnNY`zT!A#UZ=m z%dQSRtay1A>v(p*#TL&&=GFri&trwBJsc3r{5l&v?*M=1SF(ZUS*`HgLIXnH$SIa? zM8(`z^+_AEK;#pJ*nzPpT;sT#dCdNy1zCRglGK+Yv**32?95teo<*4J6GwR29;>WY!6L`x~+*Pm0rP?Emez)VLT5)ZOZO?W1l`V*yl(XWv3LsL_kBiC$X; znKW6?6(2hmlN-V;Yc-a;{ykk`Ru1)uM>y8Np&nLyA8EWg(`q8>dPn8Mz`jjO1*ih| z`m=a8`{m!C$i?oOz%`-2z0fDFhH{I3^!Ir7)qH6#knaxbxv=@{bOn^vwMUISwd9o_ zQKGxz*~e4J&PJ`YfkW1a0A`GA^~1|(H1OT=N%iW|&gzGW!o>Ci*DSiBU53~?I=s5o z4{ZEc4eD9Y#&kR;F{taivwbuK^lCbFu9%n>J6Eo6@9?2Roj^Zu%3PX$|s(aUqAm*o$$CIxOiGTPYv&r{b3a#R~w}6ZcHtE`r zqUbHbkaxJL3(uwp_%7{lWAqBWgDr&sc~d2fLm0pHCf*Xq=VcSyQGQx2a?ybd+% z=XKJExFT!|$Uks}$qARU2fQL7B-6Hpult9Uh04}lcz|{7TVt=v`hQ6K67Z;stnJPQ z30p@Y5ELZ}VlXPfxFiO&uXNxxbW9YHxM##cTt*{w0}hJ`oj`gnji{)&<2pJngTsgo zC?+5zfNVM{xJJjNGVKD4vIyG$`<}YDlOXzi-}Cc4q3^9*b?VfqQ>RXyI(5p}cSEX{ ze2!Rb{Hc?*rcw1z*=F33#6lt=Q?|8}j7R+$b2N|dh2KKYsB3=^iEzbHkO=7n9_hX{ z6B6M@gv`VELS{&W?)d6RgqQdJ7=MGRWb1sCCoY^faF)}LbAptI&b+~(%ZYiT0DvHY zPE~slJ8NY>!7S}7RD}AjVSPUVk9gJ(w@ZC>NQo`L#?+b8&V8+KVBz3uYupWM*ft~F zC$IU2M*TP{we=7MT1VQXp}T*VHfIWL969;pbcZ%e0ZWYpu4w)Fz-HySsIV1&F_0>{ z#lJmMveI~#fu^9vZslT&FJy6EXpBbX|6dx#EBOjOteHK`j|Hi_j-e^TR}T~OWWk4_ z*~6x|>lh(|X@@`~_p6;Ia`5@_e;;?!x9#FR;#n)~;-f{>_)<+xXmyb_CI_?_^*b$ zdgE{S*TY>K@OPO)%m)0O-a6d%2HunLtqcB2@Sciy6VF>v_AV`A@GmLZm69S)d`tYpU2dJzGrDx?>gv|LN2)vXsH1!KN_=eh z&@R!Hy_SZ>y>X`Np}@Agh%9tN95Zpl|Q3$BifTSZ_RX8Dv7GZ zeu&Ep$apOoHqKb+x0a$BxQ2NLPV$G-5!Wn9`*~o>h0QSZ=WJJCqDt#Aw?lLbdf8$OVncV)15Sb8+G`he!ff&@2(F6qvG8?DeS7YiYVeFA@ueHk9V1 zk}Yw)wL?sTS|ikL-wCz;0#sK1wUbcmlP*B(cA%>*#kYc9Y9p|014UA`L9#A}qa9su zCioy!ya@aXqZedLg)B_mUNO0VB%q5p<@SkZJwJug@Q&eX52K(((z>$xS9SH*u=<~X z7UVy&0g1?%WXOb3K%ryB?Z^|pCP$-mMEcnKpPhv=_WHCSo^>z4bA4KM$5Da2(EilG zpwRxVSd{L+KC$Bc-z`e*^=O+tFHcv6)BZn!{kmtMMTOAnZEI?#SOMA@y&8o(Tj2}VXccZ;{MeqWK^ZvC#?x4e_IPd$1Jm~|V)epcwGJ~E0{uq$}l zT-MamFMM(aG?*OgMr5(~S#H*l*encKDCT|X>wcl^4DcXhXvRPnV@u1ui-AnP*mV)n z0GsnxPq?gEGiU}GiDnzolk7&RZfyUjaB>QQd$4a{L^2h#kT)&wT4O` zO6=%AQLT6J)dTv0?RW+?8QS4;08lidhQ@mV(%D@-h<8GEk*2@mhhv>eeggI&!)|~r zlLlm}$9g!75jYnya$tLo^FAGIaLyVmm26dgOW-B~5sKw+@FV~kjG6(Y3qGqz*CTDT zs;SLbOY0+|zNjmD-Odu}itPv<;Va%YIdycT8}KKaMH3bPtfRqmSTvg9v5*~hXSCvg*D+l9N3>C)t?-pSk*5BcN55Z)j&hL#>e&*-JnXNKRW^>M( zfpP`kLZ(&9L7D~h=%cH`X7z{dPH(zveMk)zx z#+K~?cWvWhWxDEp-hZ+3!qKw_@s<8_(>cnP>`He@YAsTWMpOjPv4e=gyTVL~{ZZZd zI){M3s8Vka7Z}0IS-y(pJ-U1ljy^hI@m3`GtUi#_{Cp9x0{B2@2@@Q{VPEWpZc+c) z4HaMm>%F%z)RIR(Fp}sa_0}bzD~u^ zxj3EG;)H1=>wUZ%TG9;DsU}hzC6$s&4brLUNPS*XPhn~%QWFtZ?m;?5!okh}+a?lt zCw5Nt?Vi-&G4AC)gW<>#J}WucEqV;p;;D#T%z1%gmlMJ=?;2i#UIr4KCnxIld{Zlzz zfGUJa8VAJMCQk*lk9d=AC~F$g7fF@_okS*uN0^XW z<>3*P+%Pzovh6Hm1y>Z9_5UbE-Y0)-JYU3{NlbnPrMA~l+Nr!{?!WUiX z4I7oDNf-X-M!2pZf?*gsvh3O>qk@A-(}w-=e<5U|{Z9PlG4Y->Uzt`igr08#=t)Z; zjy+*;o2W)kwLv^!F^r8^)$a>E#j}k;kY9C4RAIh@v6}q=o;Z(Fb}VYR}dMIOpiDOU4>Lsr@h5N2yhTFY8!Hp z`-fW1^&^rR52WK7qWZ2l1A_WeFvo0Gzcj;pV%IE;WBAR+mYFrc%jKF1pKm{OO!!+1 zPB#;$DZoikPSC(*LT4~{pci^26IC3crX>hL~Q=(zZ~_^Wu&`? z-r{15dF~RMpFIIz>u8nK*eQ}chdZ0geAFR+nl|p|prI=HXX&K^fZt<%&rN?9d~(4m zqt*ML>vat3TZyBf?49fItUmp>^iE{_jghi5)KK)55j`N^v%L6D3e8Nho84*w&!S>P zx3|WW`>iQ(GHD!wJIiCKc;S|yyLKXS@EjXdqE4eDsY7EqM)Wfc?#FmPNOr`JN@o8k zb`iSvE*#A(Dt6aZqoAk0$c)^UM@>*1vyCL}nC&|Xw+juaH%`FM>GcN0)riyTjRE*M zwcZ$rpS*hGB>bFGZw$iE;Cka^{N&afx%ernHwNRUu--TYDrF&q??EJt&8M8$Pt7z1 z?SPOyTT^PNdhs)%)I^}W@-a=RbMdTR0R{CM=BCK#Ce;b--ntaui;4rMtLeJXP!@Vh z7fNHH>O`UIBcnH|?VxsSw%?jj?!z%W3b9K}>ldKsK|KD{`p$SV>PO*D%MlmVk4nZ* zdHtvqpbddF)>J;Ai|{<|1((UZ1w*84{&1Oz;Y(Yw%wX57HKPC2G_U!EG~cQYxJYwx z_qyANuF)T_!$%5-hm-yrm*YUFBpsf{>NDt9nec}eq2*}QOfOgHTujGU<_p zNkV4fD^@6h%f@BB;mty&*ZiPQ(pPvTjv(z6o)I+Z7mr z!K^_)VmoRU@j4dEeb~tz`EeoT2hMgPUSQHWJc^0NvA@9yXdh=+hfM0wCqm@Shd^X| zXovBvQbBypu(*SvS&bvjov}R$84!a1@%SE?x4#JBG6@C~xfrQNRAk*ed@-9kqX8~0 zrT+|sHA~p@m*bz%=GvZv%-CdW4~mV-+~kGXXfx<&{Frj5IRP!!nq*Ljqch< zk>Inga^X(66mJ;pjSw2gAk7T@k~hVza?rMw69Bh$EE0_sT-0K&f9@byH!>#441Je} zfV5Gy;~dWTqq4z*?%L5T4-*IR!5BKhY;3{C+9*haF(;ahpXHlfo6T?;g~I@R$~C(- z+Fu9aYfjtOlkhb=@pbGVv+?sxv+Fi9Jf5IVM&@+0>qZ+?8kCl1ATDTjLKmgGxIC>70=kInF{g=XH52p<_3 zsJa6VNU#7!R`y46Nb(2qtg=X|>yZ%41@Tg+4OjpENOE4soYXFnvx+%m#N;L<2zQug zsB=F>WcXK*du26JTNVC8claYylIll!xXI{V-l=|+q2|Dhf-&Axg*D_Zgj|5!v8PJh z%V#Gc-^gTNXnl$=?-O6+*XfK+*mb|Z_~6vu>QY_g{R1d+E^A@TV7RYJV5P0uWat8w|6VE@tv>WC)~9K*_X1 z8`z-&55%W{JNHyTS9b#n0NjLRMHo-Ew2NH8B zAE+Fa*=x!2{|b9RRl{0xqBx#LvhoPC(@$J{!^JU@wFyJL*gHil0}DL$$_| z#LQM7LcK&koyrXGJAM;|;CH-D4~%>c3}{lajoIdn1()ntONZt=>x(w~<`@U5Js`qJ zE_@KzYHvRny0YYg6nViwo3d>!ryc= z{Bkv#LSaU;Om4g!BN!)V^!u26c^^}#X1q`4K}(RR?rYy(Ts#-_o6o23rpzsPW;~P=^8E? z%%U1v*(UdrHVCfSU{!54(S`|7L{nCmALNv$yR#2dJPB5r3HYE&kuk}Azf-HTpZ3Fd z3Er}BHVLZej4D^~x{yR`bOpW+@*aS4b=Nxw$n+wCtQr%x0R0?VRR!1KWGl3&7ml-a#U&f~RNUwu!99bH z(u(%gyOwr^WDeIv@uU68Gwr>DeBB0kxuVyh90vRD`+#=|r@%Uc+nF#du*FQ6SHmVF zhE2qs{n=edQGr!Sk^1zVALC%@a!l%!61&j4U$tV>+Xw8`M;o-gHMy{vR0mF231!ly z(r?%sZwdu4*!YjI67{N?9jk~qRdDLjggQe_LKPiK0nJ~6mzh>g1KNyRNVf3@^E8;W z+}cl*#mQJV4IeD&5Tur$Jq+Gl_$4n6+YtKMvD(zuMNJ77{BihVe(AQv< zk^5rnFX2HG|G@OIa^=14UG+jt$b%JcskNQXkDgKscdEluiNL{!4C^DJ+^MLq>Gtk~ zmI-IQFn$=UgH_$mU@;}3pruFg`Jtc>+ z0~dR$f9d0{-H!t5*zGbTPu+tdIg)FeNcW|?F(e1PeFSFyWvk813<_6?KBs@el~-SN z#ack@tz#|tBhROUygsXh9pkQj0JZR-a07nLh~>h!QtK@$a4>^y^XF~n?Z_BTCs4_Y zHyZV+xFN1lipQIM5+-k(FQk%!@3Wte!x=hW8XfT^8SyvkYmXs3L_6~pk8@4_ijzvJ zu|5U1{P}VeU8J2qobfAsZ7ew|CV||>tgc*)DDlI#^JLqrLSyvoC< zM*L#zknU_3zRkY3q&(6 z4TzUx3JJhCCvUhYGRHlq9F50Dk}p99)4GT4@JEL7utVe5oy?jh8*zWp2~+c`@95S$ zaMIyy+{`pUekXZ_$%g;PF5gf^pYPKrXK}Vy3aT z0g-t3L!i2smv!@;yW3s+6$VB1fnLF5$(6w@Klq;WVxX(P2;;(CyB^=I@#)x*aMvCu z*6Wh&nnD>m#onR`Rl&6C16hHh@K}#Jv{{Bn_wO-0jz=*JkGsCZ@JQVXogV~)8utVK zZ~X<69SXVYZUl;ct1Q=_f-b@tFkkT+_q^|cs|<#(@PM`0U=s|DJ7o0RZ7?-(^J@cM z(f`zrcuao@;Fe-wutTbmW<+@`)*9=ft27U<-3^pg*F!Eo8 z=cR%kP7~Tjj!?=yXA9P_;O<`TT0eM!xhLa@+9owhz5FOpg&wV>Z$^kg>1Lm&eW zOYjgZQ-vF44Etgj!*3!9V|ep_For#wWQs#o&^Nmv?8bHKxDECM*SZS$i}-M}LxLHl zMT6Y)PLW2<7il6BvwQidZuLowq|rcbq3NRxdHmKg3PPXt4I<(paJVONpSo#b6B}j+ z+~Avs!=dwa43y&arhDWrFw-t_(rW6ZN&l2j$k7bQPy)L6i%t&GJ3j`aJwoY>Zy}8i zY2jVF8#J`@nusX~Sq&du+|yUQE7%!0czoEFO8L%VJkI~Yqy5FpH~~$`@D+dWo^vgv zIShyHx|smwOk-eHP5Fe3Z#_ikG zUj74&qpiQ?D781FRpNf460>D{u3|LwHzE8fbz1WX`j!OfZVAwTc0jjRiN^sr3b*o{ zU(<+6{BK*Dzrdq98DL;)DI|>hG()_mzz{&?iFrsL5SUN#*+Dqoj0Sn?`e zave(+qNF!6m+r`zQlL(BKb={q+OQ)sFusUuo9vtina_ba6IEc&=M(__qXn#}{7VpH zaTf7hvtH=-4r*ALuWK96+BO0Un-rVbs5gOH8|YJQ&?gYY9U8c}X67l@$l6VWL-h=moj`Rt>Qo2blxB8e$)j}11uU6F=;g?vm+fdV zx#h#PHjQF4)f>9xHsoHpiM)b12Q1kHTy%B{Ua9k`M6nWv7}^G~W;j>W_gDedz+he* zlXS*}z~#D#k614=azT>K>1J3IY%ao}*i)0K_?7Cf4K4Qnv}bm>TC*H2RJ}iuRhem} zz4c+94zE@_ka4dm7a6_16gC4auL==s4aR9X*vpme@HF!Bw}$nxy<%hN;9Mk{)~fwb z&uuLI#arETK4nK)p-gHK5ZB$zlqP?1vwKbx(nB)Orv|SeMZ@38#z?NJS_^`c(ZDmO zejz-Qh95N@WHzEt;X~_-C~V!s3D#=xMY{Ed+A_79I)??x-LZ8SL{iVtGps-SJW=u& zJx>&Z{X?rbm&Ah^-lFF}f;u$2JA*p|MclWD&Y^+B{f5l6bm&v}tPz#uIE`v2E|j*| z3#DN|0(bS||90)0>_fcddFwzst(GJQq1`{3i>lpqe@Cjfa8i$|e&hNF9`Ua1% zeo!ATWo+La%thHq3GXXj=bpD757tedD17K$H9x0H>$bSPN?r6iU z83Ht3b;aKJN%UzN?n2gJf2REvX)BWOTHH9hM`)D^8R>F+Td7xo!a}KtSVXWGWcWNy zHte=zsqucn-gtQ~qw`szO0IRlYn}bY4T$~SAi)`ZSj)+F5>rZxH)FK|0u;QB;LyH( z&_~|(;RNF_uGbOL)H~4Yv$nw<^JK@~5;jwD1Esfq`k^qwdYRpDPe`^2x2E8ixDCta z{(EEWA`EpFABn{bB0XU3?jPudJ!6~TA4xqAK9JpfDQ|k~Z$D(F>_Np(CpeFN9i_H~JS zJ`bF*PsJHUk3q0!;25Ji-Y1x$88j)_)t?8QY=7%wo<)IAO(BM;8BWp`)Fwdza9pi^ z(hEEwL%j7oyaB0pOK4i%c8Sfb7TMKvZ&3O*Kp2i{fna3YoyYdd80@;!d$iVKoPa#|S z31T$M#x7CcuSTW{WQy%n|Hd=&zKKjuki6+E5Cb41dIw;}2B_6K)2qxxngi-sW?Cgy>y2vb^ zofAC6jMq`Uj}0bUck&mH%n2Tk@HuqV3;===?TYg1@lUW_(ljy~?RJ@iXXhZwaMJAD zSUS>jnWp&&W>pV&w@jK19e8ZekK6FL zO+P|`s#E&00gwCjV-#B-=_s=+JZ_O0E?pWftqzyg!Y*uwMxJ^HqV;TurA1vH=#(Y( zST^IhPPp`0wB8yC(^bi{rnQWQd43sGQul2z7a&2vvmVOMK^w&Qi@l_ed*!(H!Uha+ zu?yZw!INX%_=6SgGCjb?no)TOk6RKkGh_UqXO0o&D>!$cswGiL!74p6Fa<~~W}U-* z)|mtOaHi_}nsD;PA5%-=q!sD@(nny@6JD2b8o997O7g$D4a|(qS}wHx5m~PA_Qq$) zn31eu$qXf0>QdJB0~i-#P(bo$*D@q&DZ+-j+=ENX#pP^pX=Nf7Xq7saR(3nbQ6S=(h*rrI+;j7NQz zwTo&&Cd^+)bs}c?y-kcYQ1b~GxHq?|GnpLYy)uL3TQ|gZYp%fbnz7NR)3YhnE zFR$lX75A(ROPSUqz9CAj|D6_$pje7kQa_x-Nsy~YHAzl2J3!vwMGjkYxbqm5U28;2 z=m|6JG9xkyxAYmjgt)X|LrL-XRwK3+fy4P!?s|WLdx1(8;+2$u6KqzXhfU0z{)fth z;uAOj4n`Q~nEnu0#(?X-RlNhfM%*spW+x0MEnw%safbWV{SXTb*d8hb^SNIwoEUFX zkGz{skBi=4z-4=b`_%(YRc*D6!eN$^*o}6W(FgW0t-lEgX`AhO=Y@DiRA>+n zFZJ@FPBdA(R?BNiGj-hQm;#!G#MrAx;cZNugv6+wSc$|POsqhnzEBT=fRWh3L=%aN z?VKJYDkc`<0XJ=VH@hZsi&CzLF|CD#l*Cp#Z&JyL<8B$oM(7{K5sx@_Fvf78!uNTi z&q^I=LUTKdYHdDzNm?Jl45>yghoW*;nrJhBexDuC{loVlx-NW`$_b@;YaT$T65tmev%hDk;!S?S2J7CnHzvIhm{4?NA;E24-A;t4gpAv#(Ur zYV1@(;TR-HTC*_kVE+ovkZ=`1a!<8{07C%SI!;V2$YGIDI{U(B4&;!?#IjLObIZ87 z6N4-0Dm}X`lesOlDjU?qjtF>>)4D4N79Ul`dJr2&`fUr(xZR@_|F;9Uy<*gKQChI9 zFyh-p1&N)hdIJ;Cp$u(bd9|j)^Y4NVq>olh+v#ZsmT|k8I}|eaS&>Y3DRec@R;VO3 zZ&E#hj&>C;%Dq|#t!}sCcKiqaxy4pr>^*9P5o!pWZNkd|4Rr-hwJrjK*qRxbN)|cT z`bew@E4B87t=KDYexz;V-}X-u|DSw7Qe&Kou%$}hpBUO@L}y|WkC+u|^ZU@zbl|w| zQSsD?&cdhIc_37_A!A=`wUCL|-XhmMbQkt9qH~z751qI+AgCMq^Ag;k3s0YDJw7CS z_@PrCE&P`?1@(g4bKn@84U?V`eSrBQSyv#PB6rHa92Xxn67F4S63@PdXLwf3d(Qod zHLnG&36H3<=823L(AX5JMhgGI7il^`z{|um~rH&3oqa zjp*k{rZ3kPw07pd&>U<^@^nKrp4nt|^66r)8QjV%HQ&a2&Z$4MrisjglI_}IMYCJCF=Cj+@oOmfeUp#)0S zF=Dc574Mx#A?yiGu;zWlFAagqaA;M$*EYEqt-(~Irku!}(<)$bNAHD4RRE)47xKq* zK13Q!-4!p(fxb!qpDpUrJVXvGnpP1^H=;>oB$ykvs)pn7RBS}|!MyeQ1fYbaE=YQV zkd&Lfk*w3+5pIF$DMxKT71;r9lNtqAUEowCWb;&jA4s6!g|b7a&#rTukRSmsNy7lN zPv6EE{|mtIavRGBdS9D?m2B)7yWlTqD+_MLZ){y+y;8yT3U~hzJ?5ILJ9=nof1>v` zCPp`kvTq=|!kn#83a&*h{AsOTfK#8azhNaI$)kC^yNx|E4M+jE<@bk8QlB+@T zxwY06etff|$y|{hD}3m#y&DC|i)U$Glo2YPWN2+{JH>z25BMQ3`f%)Xah{N?l)fwZ zG1%BH^B`jv5QChHgHT!Pkz2c>(XN7{cH|E_({f-_OBAwPhX*xAfCaN?a>V`V9CVY= zx^jAm>e+8~5` zKi3II&Uo@NhOg5(aC{yl>aK^XCQ=_gSbZeW+3g90cq!Z1WP}Vuli$HJ2}FLHb_xj; z>??v5mywV{7nB|W8`kf3zZ2R z;C=8LWGHSYvoxPXx;JlaBg0#GcF0gAXavT`Ae%1p#2}J(;sT_~0K7;M_6yf$J+^}4 z1Jjl@rczB_O2@w$l{|0JQ>IJA&$?(LwiT1q+!v{$jxp7rUdwQi!Y3UIhLWYfi21e& zQpSVbo`p>gP5*E0*}tW&J%{k@v}Xy}2IwBvo=Hb+&m{H4-=#g1j?|vzFWBvQ1mULG zo^c39{oC!KsT>ZGJX-?)&cp93cy7JjOdMVIZT}ul!@kDvlKs}_zQ%7-jD7DLp|6wB z%N`^2Rgw|WsBenTc?$d2`V%7g<+0mxI%PflNdw7HEoEqJzRV_I;niK*Eq z3x#|f#rd&|p-fRS6t<)13n*hmKcJe2qWRj@3_5DzuO-7!0Mi?sr%*w%_L&xr&6Sm_ ziYrO9Qd7lW5dMMEhSYx`RYYv-LC6&xoN?E2`vrO+wh)lAcP{6k>fo_bbkXyK(X1XG zmEo#cAYbs6bIU2&GI*{+pqpTcE|kgJYf4R=p8EL}yXxztd|5e0e)u#t2Bu?S+Gg%R zPrW#U^Wd!PR?0Z3us~M`7`{sgV~c9+!;0K>mQ;)u?7D)pN9!=Bh)bFmyyb|POmQ&z z;BN#cn3Vk*lW#6^F!?~L0o9(90*ETC-WY4Q<~|_DVwE;0GG1H!^9vmth-rTHoWoR6WBPE2#(26C>NoF!DABDvaXIfl<0$ zhM4W3Si#*;nunVXy^QOk?jInWTYC&R)eo7h}cPx~Wm3;XZrzd2qp~nU5b>F5f|_nbI8p4A+-+%6O#( zRlun!aE!G+)bfk5cVv00+q>TAIV!n8FN^_Gk#TC3 zwZ1iG4=Yb4`7p0CNax{^BQk~(&;|2B1QKT!lo zCWbOM1Wap+%zgibg}YomJe~}Ep{WM^RXAB~>aJH%*x$hEew&zPQxfB3wrcfxZUfpy zB@jyH0xE&=ZLu^p2ll!ZjF^erD5v!^^DqR~n)|jPUZxqbm_DVm9TLQh4jFU9pXRJ? zIob;e%D5kmX5JceyE0SOAne?6VALw}h6dNh2a9=*D>`lUW5*2ncwi@H&D&^hZ$;Qa zoSe=8iw6=I^0WaqbEHw{pixHX$0WmA*UEXL9m&ok$qN1_h8lT-kgS)Du+lM@2T*8f*)Aw(^IGCUoTC+#53ianlDQy9mt`wgYph-{|&B4VsJ>n5o#<)aj^&ta-8)c z#0s62fC^(i#ETbW1)et5ERu^N6=npnAdtO~*iXX3U&{?w zl^11h#S%g<+o^G5CDBG6hdzhxcTIfV7WxqQhpGR^T3R1s=rq!$q#a!fHbCNUe6x)# zTktGo31TVA3H2%w0NqX^Ay)H0gm%$q`=)^;kO%WQjl~yi!zc2$dwC5j`lT8E<|kuG zS%sPIhQXYi8Q%+HzP%gw^fKm=d6=Yl{8JP)jSyb9c<{M>( z>Qj*|M{?ZN21-3G-!CjTt*a~4B;r(j&|UkOV6{bkeJsQw7l|B;2qcVb->J8uw31#Za!)B&6XnwwQ@xHpvmUEv4jc>DouN$m3fes;U$qIRho#hG z_&~Q_7d$IUb~u(S7$3ksN7^jKIMMXFbfwS>%p-SCrAo%nVsp1}4w5FcJKz9f6=&fI{;d+eXhqJd-|%9j4C20uLmbZCac+ zP4&YPQT1Wx!OJvxS%Eo@ZXDLn792vw2yiov=>bekwgF)ZmmjxD6$}In`wyNSa|D(s z_VNSLh)wc9z~oS2SIe;+!;q_kE$8WW!h`fFWP8tEq2k?z%aRv$hlyQnL>CCM?!Uh0&`B{*J4U)62*hsgUX zqV`Z!P&1;8UWFDHvsT>L6*2#!`mae?Yljq&KX2hjtiDK^qw#D+t5J$%pe+}s))&$5 zt$&0@rBXQEBEAm|W3Z3ZA)gq0V*~y0k~d`k$3E~qy+RDS7aCC*sPxKFYIC)#?Ws37 zGK2&^)Im;H`4?g$k2Y((L&(6D@k6Wk#9RN3G9nV#}EW#S74DoBn8$bqz$7?8ws z1yI0OaJ+i`QRx+vy>c`<^vl)k#80>GN)a5WC3Xv%kI0=oaKL@d_A&RWSQGB-bh<%uhi>2PhqfpFRGTzamUdAVg0s zClDDCT7KQ9zuUr#ed&N9*)loUb7bkng_B6I>vRd6BZHpg4?iVadS2@%FCME=9-`mN z(`CP_JFP)R4t+$%`W%mr&E(nFXbrtiM%fE^Mi;`4`j*f7!Dk&RwSG{epueCCa1%o7 zK)tbbq9FU^O8}7D*G;Dy?0NcG?^pEmn9e6d>OV{nlPqiCx9(;BzJu&Nb!g z{n6-htXbzttBmNkaKB?;&_Es=&f`K0QAKbJclBWG!@7OkgCf3*%qG2A%3h1**~R~B z7bib}hj)WPAdlv(;t$okT%6m1g&aJl@y*@AAT3l>{c}suA`W@PFE=ph&=CyR;=`5 z@L-|46q!`l2M?3ymp}9?d2TP}xBWw~hAH2`!u{8Cjcg)~pe4dyV0AFupF#8>|82}* zxHoWV;YU3Mzf)p3iguX?>Ja(?M|5`Lo0fcHj(`_ys5vz(vY?|`Qsx^Qzx@9%{O(>M z_&tOlJs}q2xBHGL<}Pd(YQz5rc$2QLIa)?>kHezx+B%+I3*~TG3x^kI&~CL5wnrRI zV;A(~1jq%Cnjwjt96}Ahg!XrtCi^KXVGLP}O91LiU>r%=82@Y)XR+7`5>z{O%qohw zSkG113UkG}t%9`(B6}4(m-Q?rNNhV$Q^qRz8m@g!04l@Zb@;pKH~y|d`la}DWG8=Z ze>&6pM&E95>QbRJ&Vc)@9k4lLbLp-E+&=FM7x^Ql4eG7W#re7`Dz36Ow6RIw450ui ztIz29!>`FvPp?%~MH_Wun{haYjfHK-efNoZvhGwFM}RsN?Uj8-IdN;1Hk*-grdpUS z9ni-rfdJly>0PEA_DyRVOVXJfmyQ5tX|pOgPUb}%houg236lNRtY+X0X@YQ7vrKgt zazHAdC{WPtE6~x-v}HuU1`1~QyjJWsAz;8Pb824%*YpUwh4*H-5Hb^UceC;r@!9?` z1Rs!yHC@Shd@9A|C!2!Z&2SGHh^;a+=k4@|XYD|IwiC?oRq*gAX#o$1XYFb#*-ruK z)9V6LO@53ZFpckABoF2AG}=LVl!Hp!=;7UIdGtAP~*`4*eP}k8UfZp7P$M^wn)~AukZ(XH}ru1xSt#; zd$>1ZNzDUk&jNj`$vH^cj(^(^hs1r<17DPJKv_bLJqwuG#13FR-mGee$^_U|)F}Wv z%OLKg7o07y`;m$@@OnY6W+9P-sJ#S7{ZqT!n2tdz@0qRO zCy@NZq5J^z>sGb&L;C&0LWD3`9bG!!JGsrJ<3qZ1K>x?hyk_W*3Kv!)piVBSgTeX@ z@aNdo0^&9_s&$Y!du>(QaSU39Q|kbxv@7%~3K`L}k(ouQm4XsyybSH@W2l;~hp;{6 z3^*@DTeglUF;3zrdQh*r^f`Mp4@JyE>jS;9>c!PXjj?2Ir{bPG1N?{!u)WrohZ=8=&ueTXZOltK2WkzP3IEhUZFcY5+Vv%D{$2(@Dx=qYsxv@i{-nmnMiXw@7 zmJ-U@-am8K@{EDcI-WBD%oen9YZ3mZ2S{y90{>bdonv48gEeC$i_(-^lA@e^aaIB~ zueF~OfLkq*DuW0aX_lR@r5&6YmIT|#lM8v*H+G^yKkOK9Q7#;v4!tJoJRM(1$2CE@=irmuV;q4NG}vkC>8jFSVXh@Jcgs9{=sRJ-eD zVM#7u^UzWJdNUHNJ1PIH#_g)0@!4d=X=%s94*`86dJJ5d*xpXC{-8~_yrf5SZ#2|C z>TzWUW1im{Ux{Nv`gA&m(5~y|X9FyITo6Pq8mCT~ukEZl z)!HG6SxD5_A?O`q8x-uU`8VvPu7aHfYfqvyD_HAZsnYd^C6){qxL3AhOc{o_8dWM| zCF7L^5uK!L5<+WKp{_{zRcejJzBpTR^m$fNep{X1o5PF{}W&?RnH)r{_m} zJrQ3qXJ8sGEZ`H8-mnWW!kQ%fA_;->;V#OCwHqEYHC|WQcu^jZs6UfO8#sAETTGa^ zb>%q>zk*r@qZ>IreYQ6qchHiUO8iO*3+tNdB}z4N&j<^0G820o^?I)$C^NB@55X$? z_SFbHR97R2pxg*SJ%|lcygUOSkaE}Kj=2u3yd3Bo(Isdb2RVf-XdV8WW@R1#J#t3@ z`7<*`A3Rm-lZUm}h&}?4t#8S>yR9l+@&+n_iU;Jr9oM3VX7|D+G=aj<>`a6$g{Xx# zvmr1zTvHAFf1^_BG=Waxh16$`n1w(C9s!waD@cK%ZOYLR%V&gH^Q8AN?a@orR6FE7I7q*Hlz9R=1b5P8g&GcERXer2=3raRPV}(- zF8a1^VyNR?F~m~zeNK}wa&nTAqi+fKkl9NF<5IeR{pWXfv;IuGN7>A(hVWqxa5s`}LRWF`Hldg7nT({9Ktl zvgQiEoF*^R>x5r&803VyT@>#H8zAfNZG`6r#`^DYf(I@^nmg})RBH2C2js5r|8Rg` z7`h!p^t90J81>jn!#xBT(#Pu|ie7ZZ;2fUBG-#}_Zc2Eb}t1z(!V6d3?D=01bYFo8T+vo-TUOs@5eQVj> z?mCVm7$lae#df&m`A?L3P>$mIPkuM8i_KEpl!?Gr zh~7-v<|x*~B9{_aQSsCh1UYu$k~tiGoPn3;+2)g0p65e`sOpK85}I^}iL+On6lt?V zD=ibtRhXr$t4OA8G*$V-!Ip4vm$2%`^9d3>>lN4><|t?zrQ{5Uv^GNMaS znKJ{nE&^FS?gyG$pTa`|+5ciWqmj)3vZe*9puxJOTb#zS{fdStV15G{>z>EOV$rNO z16Q!4!1B7IO50|on1MueRzsk$Z4Qc^N|pp-Gi}5;0KiBi$w;_Q<_Z3wrxsudDyAb) z9`64`&LC#mstMCk#93KifmQX4e0!Io;}Gy*?Wr$`n1m|S#}C>fBJCb{*~_V9Sz6zg zUQ&Qnj2$M)+Ud83mRj3*xGP^IIkwz!!2=_*VB$5=8h7nmc)@u{*$X<*$vy8CevD+z zc&agO&HqdFRkk4+bH7Ih^qguUudQrn_lM)aG!&3qCA>v5VEbTTHaukpj*+^qz-!ao zY9Nhil!lMFNMP8pS_2P8(_AvX{plt=GWG#*EuHSCScSGzYOVEIZ+nYg(=ioKQb|Ya zanJyGeog*U+w%pFyQ{Y(QxGnY(mzAnXZVfx7%0l*Dv3BCZ0`&WVE8714iRZiU z_c#0{^ap!?q@2a`S|p?{%$kLcigTH0HKYf~=a-jtvt`OU-x`5X8Dp~jxMYDBR)BUu zGZ(GS(PoJ5I9-ULhKQtNa-iiDB_T2{XEb|b0{PLTZI5GzxB)G?<1xx@05GCg*}cPo zsQO4FQOZ$+u%}_qE6(}2Mfcmd196DDR|G$*T#!wRXSEq;5%{qg{!P-9bW{qJ>Waiw z^nA=^g(DqkKAtPfZJh{kxNzb1JxLf=uJWwRJ&pHb{s zko(?_tX7r@UJE>G^IFeG61@uZp2sRtIP}-N=8P9x)z)g)vG+QI1~;(KSSMQo z(>?a!ao16_$e1}nn(3~y9qUY04csZYYa|B@C1Z2cYkI)k#t}um3gBc|HI2~j6W>64 z0j(}#^lyAC=0pbTw9O_j{ke@z)*R1g=1PJL8jJy&gn$t^5ePqy^$3WEQ3$IbJw#<$ zA@5P>NN9Z`F=79Lkw4)-A$>b=k=^XeFjIZOjr~gO32KFn+U|(*)WGPyBdU@S$D(L# zMG#Rxrc?&B2LQSu2|dwsvm+t%Y!o1Isp7=ri`8Bv%WL)ZkiNJ!2_vL z>9^L=c>EQZ;s zokSXIlGW})Xw$@pfPA2?^p_K1s~THwZ6q-(L!YIZ#p{BnLfHe^M^s|tOT>0)Lis^| zctQpKaDnZF%Gdf+iEEK6^r2pc9PSdK<<-=??cVZv)W)L`feBZm zrUH}wodZ~Wh7P17mH`D_LJ}rCBz5_-b$QDuhuP9Edgil9fpb7YO~#SaNji+e9copM z3}&3V*`(gk&ls^#O!c~!mB=fw*UyGW$24eEsR&geiHszjEbI^MA#9elq zAWm@%mmAVtEtuA%Dy~kJt(Q3c__p5+wN|Sq@lI*kZ02n>iiAlonW*P3Qbzp&i>}*lB>yJ)Mh*&X8%}R@0b03av1!oV3BH zo7LE>!gj>MqwcS{8ZtKLd4&7f2O;V>jh%o0p2S9oU93Gm<+>C$Kv3`p;uOic8D)9( zgZI8YSnNTpHUyy_B`OD3`odVEW6f5PF6q7|56n*(z9LoLf-=E932^f;zvao~S$ga? zrkllG0>_|OsZI-iqtpCuFSd;v*ZR>-lF3PMrhB`6&)g}L1Da{TvH1bJeb)fVj^q&j zfxO0g)3Br1->A#-=38EvwVRt>eatXcy9k*jGI6GsiN@79P7Z-yuy^9b#CHH*i6Hg2wvblmF5ed2g5>mHgdv&Ri=u= z>T~*U{Q{?bzo30;G5bJC7y1`>Y$BNg@MIB>4k$;pN438o(*D%h`GhsSOpbx0bv$5m=`#2OiOiwa<|>ziwyGkHjA@+#NpD&=q8jmyt3beYM1J=`eKm{c7UCy}%d>C{ z)`d1qr#nhZ|uo0>9}|VuTrPtC{jB%P8X^gtg&( zOD7t{kV$pdy^JRetxObJ1#Q}h@_4G~#f+X+j%n`|Y7hgG%{QRH|=4kEf6+C@G{=0&6#$xeuamb)(#OJ9)2#CCyvuan4R+oeoV<7Hyt&Mq zDtT$n$a>k%XXt!^YoKVI$~-M$)(yL-c#^23y@=Cf&DDWa#$r(QP{*g^9ve&`$km@E zK6wL^3Z{QV+!u!T;l2T2I||vM$ zCAVo;Lv9|z|GSs^9(@9Ngc%!a+DO(8(UNXML3P$$oL9!ABXy0WPG)L5Y6y?1clqlQ1Y`hxYi9U-Y( znVN}U+E~3{vVhEZkOkq-AvJGOwe6snB%l`yblw(t2+FPz-9a#ywE_Q1QfVeq%bE$C zIwUSM(6INTYGR%X*pl9Y9jL?*zdNEwCPTb&INS2*HOZ6pFO;1q>#|Ks-D{U$B;UrD zbEu59i&yLXui16IhP?Le*SN6Z*6i2_O{eFX%__r0DtfyS{gFs7SdgI8vCmH*5=cV{>81Gz`V>p*8B9&r z@I3XH$qGpV|;4gQCcdLC1sT_^O>Rv6ZZLRX@C z(!U?zOTE0(6ut_Vke6Q#>7no}(yURJATsLgE91?>lR>koV^MgBUHDT>;Zm4#6NM{S z7<+4C!oP-v%PJ7wf)nPT;<8I-xz*+yA`A97qMoSzRd5T&;`ozdWhyzXx3U zf%0@Z9>AG!)WSn%V!qlc!WL!_e`FX|5Ixj{q@NPvXgeoHpwfTE?zpe`O?Mrgj$ls8 zgsTPzofu1t_3EqhX7Gd||(Q5WuYYm(@nbeGf zKyi`9KI>b~gnQJt2ja1*>Mu8dg!LdHX4TnzzL?MFs>yt&zc6OiiG2PK=!seN zaz1~~=icf+8}%1ThJE+4a)yzEXw6mS`U}VO$MWTG`b)k#TYvH3%Ub#J zg8ovd`sptmN6*QZm-H8pO2!v}HDywT8HNhFJ*{%$xBqeeXMAuSp5T`nd+xssvwo{J zx*Oe)aNFT7^naRKlKTS)X;I;lc*}5#->PQJ+)WN#u!JNHyDYNcXF$7csu_L~oHN9nqIU4G6om##g+3^0%?f(DZ=_8dp5MTQIG-qF11gFTSR< z_?^isIC^j@3#7>BR;Ro;W)4Yl&ZF$D)^uPr1=_LL!KZ+{vPlVkn~O^_)zI;9%(9R9 zIplQCKOLcb7qCI1JdBoV_oax`5B>$&^jSdykpMDINZf?&WTJ-Ww{A%HMk+rAWlOF7 z27Q@fKiOS^MRCysE!fO;&%FfQ&oyC{6TjMebO%0+w)*|o8qqDZ-{Y?3oHqPP{O7Js z!T;8nUZDd4ckMo)62eAQ?RR)U@AR?8;;h(awQ(^VKRI*1hji9V=f{3{HYePajf1Q8 z44F~<5?5mG2)*sSMYF58#$B)<6+_^;aF~ao{T3+wz6(DPDDJvBYFq6`E^8=Fn}8|xKa$Th;OjLEb?cjBVX$TB=O88c^yX9t!iNZ{*)DW2Lv%a@R^cv3TB-q~w9g5R}vswKEh77OOf~^{4n&d5R z2~3EM9KH~PA$U12L_Rk(qnk_Ifivx%%e-Ie4Pg3d;1$`;YIYHiXl{-SD?!J*)SdHp z$BUb0;S(+szzr$}Olat`;^o3ia~eQCt{UJWxWP{J$u(_jMVKUlH5~4L>GyFfH?7*aUMRd}0yh95EPLv2XWzM~k89zP^9MR&gCqd#!=16t!9rz|T9(7Nc3HFt@nG!hlRJ}V z+Ojw;_s@x~=1OzI2N1`!^^yA+*UtwdlCP*doqoa>W`(GCOqeeD|H3k;1d5BH=J`pEM6uh7Nk%p$tL46S{7_w_gt8X+zX3 zrh$gbQwZv)*oCb37y7JZ%Jv+8UW3G&buZ5ZNxHf6w&Px&cmvE--$J37?XxaOPvkpd zmMeVmwZ71rLVxjxlmDjv_y;+iw|5~<=M52!zWc@nnB4z#Ez=>8WqLH5s`AY7s-ZO)3d9w;JI@kJcT3hIT^^(GV6M@T@FgVGVYl zBnPb_3(3gPJ_Ey2mMO$hxp&%kqYuisPH^@ElnJupH6n)S;F3(fT?3Ur4PuNt4^sSx#GF* z(E0cn8Jkys9nvm)J2e@55UqSKSLE>@^FFERgc<30x_d`-5* z|Gyelnm|P!Y_n_6#PKUI*jY8GQ2G7!yy4xAWYJL@j!7o29* z@N%cR3vz-thgLj=M^|9NzM5=|Ggl6t`?4WV{c&&nw4|P{lt33A3QxnDGk6|0EVIqF zFwDVG)~Hj5^PZGoCJya&+dHaX?FtuO-6f61Ap*Xms})*;-=b0Zv#zika`^rhd@-!D zGgrD`)wQHh%>lXsxxE{Q>)$oS%`=guP^W8v9lqZ2wAUKt#oPcdPBJy8v!~YaMg*vd zi{Jwp3nz#corG4ZXM%R8rCm8CA*(6?fde@QAtcXGPtM{xVs<}0&`VC>($aR5X=Z7- z$uJPIllD(1Em4zxu*X~Ckei$t0+n6rM2&;rx;;HofnKkn2rhu(h1*A1?Ce9-wb1nJ zWX2Kx=YqFtV^U4B!+Aim)c|T5t}mU>g_qZIoJRMW_DIXmh6wmhSVISCkb9#9>Z%+&B1E@dKX`h3LUJ%rxHG= zsUG;TPtnN{qf%?0jzf`^JHHQRezzL-AqRk1yl(+%)A9jZ@LSZ_XAau-hyX5oY-UG!jA$(j zK&3tDn|&~dZc#7#5u^vdXFb8nwyMa#h|VT;Ru8VFafpsH8J3`OfDV^c$snhD4DnA>{mbFia?ZcpcFBfgiFg2@{A=oFXx;EV11;5`l$C@UFi&0lGR z*`#hnAtO4@EiJ9X%*DhnZwG!5IPF!}BaiPTXtDZgvc@k|1fp|2teyG-vxJ4S?w`{K zdX&thIqHL3Q7=^#URf|0%U-!rVKCGZ=N<+`W>W+IMC{;Ah3P|rn35w$2ahmb z(%b7Z2XC{xVmBD$QcR%{bC(f43*=MPGZ4ZXSnrVK;A4Pp7OiG1oM0{w})?p+4N2hF@XeJQkku3z0jcBmGixR`+nqbaEi%IfX_-^RoA&dpnK%eSV80jLqTvmYC1&z$BZhY#J&;CPbn@85GJ*vMHvL(Lh<*~wk|5a>oS(7F*hZqdwsTzBdlq=sS#gNpSi_p817 zLfz;$aiROw%!x+v+putmj#}u$6;ZJmG^R_g%z;kg3pFPDLI+NqyqbzR&UXzv)`%_^ zk;Jf8_l2M{7fl5v!gCj*e<%!&7fyxPCAABvC5InfjBheskaZ|yO{z5IY#K;7i3Fs} z3PQCx{(Jwr)o%7qRMT0vldXIhvo2ft6uHB)xJ@KlXqfMjZd7B?S8~@F>|b+$-YFc4 z;ZP-!270%MmV;xRl*_O)7ClcGQ!gNo7UGnFWr-$Y`Fmul{>O5bu%u{YYGpVTI)MNR z-@HGS7oHcdV&Tbf1tJGf*Wpsvqi04L{?fhe#6a8pp75XY0A=;XEz;hSx(%yc@Rz`X z_6;oaUr49U__T)$&gxLIAb8pAgo!DrNyugluuvgn;4OzRIMTg{fE2=4aw;I8~#a6J;>F45q+ zL?Z3Y0If&r2bP5pCEnV>%9h_D!0Ah6;q-)&XHSnj! zyRcssJ8nAIPapa0=rJXbxqpcZq@o^_Q2&p#H;<3Hy8izYNFc0lP*7CVsAy5NrGiR~ zXa*9P=tN@Oux_+iq^(QD8O03~CPAieMzCt7tM+3**48fCDumz?Km|kv+|gFiTD{}A zpjAXv@_W9{eNPh5e!hSFd^{xce!uT>?z!ild$xP-u^0Q9(lv#!YLZ?ch~)@mNgbq1 z-`2a@N(qKyVyV6sw3{0V`OAt`l*h32iGtJ`S~_A6YNC}Xes*B`=(qwvLVs>3{|H5g9D|6wCCEzhsR=)hC{Ol|@CAMEb*xah1}r`ze7Ls`@tA;y z*SNJ;AqaI6IJ4fJz^^TIysAx@;Pfkl+zAJVb!;!B%;T2Wk|L~m48KBYgJ@PzyC*`KSDnB z(p6TQYCt`sC~gu&Zm!PGW@j)tG>i{#dc6o)9-$kgCuiz!kD}x$`rET88B1T^P@D?l zVFM0~t=!2LHcVA~PD54UF|Lq9;t<1oN5b+F;k~k(TfF~6bebO#dl(|uMGV=aesTqF z2T$(<{9j&P&P!2AmH2PGGk%JDLWs_-^=A0maIuW?F!bb^!O}g<{$6pancr7oes3qY z?X36n$EB~q{C;$N`bkI~8{GE4NsDz_ClL%iAYla`J2^(*-nB)(Wcs_ra!&A~%`#HQ$PAEc5!;5VW zuVW7Vqs`$2=CDGz6L^EES5HJkM{eZ~?U^p&wha%t5W{zPQ!-2m$@xzI2@ zhFz8WXz#bXp{m38-I6OmM6lXyvDSPk@6xOG@4R{{ z+y9psFnYR!FP6{|T{a~)bP%o7k(0jJ$9VNejQT*8vqQf_gYJ`ye0k*qNEk7bYy={T zXa3|q<< zgC=g7h;!>(!QjdN2nO{F22XhxEnp(|u??R5#f(^{cg5vj;0&4Gv$o>?$HxI;G6+vC zk;HJ>9BI(0lFTvr1L}NS6v-4g6zL{Eg;vI=9vMP_*KmI`kLgud<1{;~F^Dlk^AcSB ztKrpFED`d8c@GQpXb5%L>yD2%t$tIcSVFtQ_Y3qCS%xMAgQ`bj`5koH$kF^eeB_LH zFlVFGpV9n!;rx$h1dpvMAppgOAO_OgeQ)r`s48UjUX$tVo|`SIVyDVXE^(9j5bXCLWfz9xexsZ5*cLSl z${A#gJCas()v*-u+RQv-Y7}!k)@Aibv=(i4=-#}S|LkgBYI=V9J+{Tixj#yj?ekn??b3NrB$qhvT;l~1U-=C0 zUTwH0So)58@?uf?nZvkEu2oKsy6`8Oq?+)o`dIp3WvTDR!XD#G_;78#=Q*|M9m&*q zH{wJyp#SqK4CqtgQn)NKS3<~#pCs@2+Uyz2W37rI6Avw`)rD7VXz|$j+RoBDdLh?t zvF!u~GFviG6}KnF!l${o%%dUN2%aG>wc^KR$x)&wsVJ3C%zD2zd^NqJBXxjOlCtpf zA$k~M!b(opvUAJPh}xj~)jT=#$oMssS2e^(jO-lAetsl-795uUVQoeZOUF-~W86Ws zTda~ZnJ@7SxIv4qBaT&WN%a*Qy6vJ5jk2_P6{J?^{@y=%k>fTs;x9ZPr6`^_o||?o z1{*=kN&IW!;p^Q2mg+7w(!CTnT;9Zlw&_|da5-Bz zUCWo+D=hXiGsuspPdvL+8-^IR{oriSX58{Wl~eUdEMhgYshj&#%Lw=JXw zCifw9PQQ<(=y#^|do_^SRT{hYJEYKWKkGMW`56$Z{RSMd!O{)HQt?6)j~ENPPW5+N zC)3kU1=}s%fcoCDo~-v^>0>iStytEv1M_anie$pARpDQFu&#rq0PC9qYoov&Nz=f^5D&=JdD5<>Aov5zOTVQQ@JK} z0Itre6lNmfuULC);Kr!cKhtXN2XFvrtbgjlTC!t?Q_3^~uH3{cFdx%P)%=S_T;?ut z;M&pC90^c3Sf6&^`;kfTvfVV)0ESM*R^yfq*S8HoT5&7x75OCV;+fm$L$iiO%i@Z= zRo%Edt}5(|srl~CNk%m1KqzhZ0Tx&)V@G!P0B80LPRunh?EFM`4dvRDJ16&N#7}pT z9oz3iS#B>NkONR}G6_M1YF+R6`txhFynG3UQ3p8W4 zjb-bv$e#Ec_am_Dk6TqmBB+V*ib;`&LSFB4utewoX=qJ^AS0t?9mcwgesh2k(eFb3 zK%Vunic=btAwGua*Pi4$IM85%KberHV%&-$1Md1h&iPw10EF|kAJt~C3h1d({1?Ar z>B=9mzhuaV3A*%rfAp-?r04(X{@h6d>^G>&oq;6-&hyi)$>uN^F3f~&+-o7uF5QHXVUuO=bEweWn=Cphba=YL%kHbQM?U1{1XWmQN8Z!2;!QHh6sY0o%~W zL9XX;uDGc}`Un`JOw;n;MQ{ZRrrC1=&g<4;V{m;}uuQx`cDYmsu(?JOz-Tw<8{A5} z6(a{|x^XwEihFP%4(m+pA^DS-Z*L!X>rmMTwxQLwgwnTy79HjbL-T{h%Y&9jcuX50 zp!sh+d}?I{;+OIlFf+N<@`D>KMg0B z_h2E*JY}veemsV6Ytk;htzEufe@NurVqYq@A(jg*tNv)*zt5+WhYw=OrTP&rQ@J%* z&<~=s_?d*PRJ;=N9W8ZdTF`tYEZxHP!{^;cuXl6=OHap4(_S6c^$(UlF=IupY(ATf z?KrmG(9!(UMqCyn2imFh2g51MU||7A{JSgu;H2+HLL*nfzl7Ks%#vOGGk4Gr<%wC( zs`|E@e75=4CdL#@usd~w0i3#aBtF-a> zlH{7NF{u|ov%kCSFHw-hU1vo=lIz6D-TA-}3`UV7;V(=-J^pdC0AJ&NWSs`h_S(C0 zN%jSM2%4qBYA$|{(O}Fgh%y!DH&kmN>w~3RVw{O|U&4ri_&f}6m&L;y#Fq;q*7s(l zckHPPDffmT^Zj`mmg2s^eRv`sLlI93eML20sDQbGe#3dJ>dLC&$%8BaU06Ts@^5|xALR+o$m9P%?Q1TCS}--j%zc6tAv-?Z8&hrfZLenGHDJDs zg|AkJ=MAq3->M1ov8I1(SK)$SP6>gMM0j#J*9NB!O_0~J^+Ha+=|2>R+EHucpXTI= zUeQ7L@oHxOgm}+wd4%HrkJM#L*t%MzRK%M8B`K;l98?$9m(_){2gRq81cKX^5?r|4 zNEg*8*o*i}NZfqO6i{()L$bW_p+B;Z_DGh4IRXe-7RqgBSrcKR64utMKe9G&Sdo5rAdo>XwO!tz$xVpkXI-`wST zsSan_59s22ek8Oz;-nlY8am{+EFMuzjfzZHDvAfUNGtqGrs1#R#4BcDl2y9$h1Yen3_{mmZPdwEeA#5IVb zw9}wV?wU7?Q8K2LFMQH*a1q>MJg9~vUIc>l{*SyL-&3y^oW-l^iu(=ITmsEgqT+!D zE3M;3Jj}F*19?bykTYbk+RhH0JdO0z(^r#!dhG9_Oa!sz47aEzJH0Z0Y;1Yb|Nb)n z&De73IlM2+9~fJ%9fsduaW*b4Xr;uc9M)wnB9~ zLv&3fiQ<7IzbjO?JvoXkeDIWYRD$^Plt$nd?YD+ti-Z{a~J z2*7%A*2Dahnp`b=tD*0=fG&N$k-y@qvkU6W3qoF&=pW7VIALU6Rjz`+u?InNhoaQq zBA*F#)wyG)jw$Ti-}F28H@aHpEHTtj7e3~$dJffKU3%>xQBd`|a8v$5`&NT!LYKorgp1ahQQ(0@Rt>aZq!9DWWS zjg21-UMNBQv8?fn_megL+FSAi4Ah0d9JKwXcLc5xg_;Oj_5`N_H{dVbKX{Qi%u{Zd z?>@Q&B|nx=@BPSs`VylI9r1}Ci}HK%=|F&1tvCFqcx+h}pAw!D=>gxC63m=jE4_xrn;68spr)EWRvfnDTF^Gf#C7I%US|ssomPRGz9DVgm(~wM&=IUp=tZ!{>w1`C1+m{4g{W$3i*nB zG|G1!EPWZNi1^Q-*v)cs&R(OL{DXC%mhxNlEAbQP6f4*nFf7J1Jc^Z~F%~VXX z3J1-<5m4S^Gd=RyOo==;RR|Jg(lXHnhIr4+d~?Bvi^K-tDA8q6(tV?z(E2qylt3=Gr6aLS(_Y4qZ9B)dxy?P$Rq+yI&oJVMM20hd`D7V z`;=&w75PSgET-pQK#W{`o)%fq{1f067{gApMR%EEy-SWZ~A8BQ7-UbOscsra6aJKM!OuH87U|H73_3uG~ zj*j-)%Jy0RDWC^E9@mftWg;7-!?PdJ*UPVOoopksAYY5{4Vs^~!93y4e&S=S2d`jD zdL=oqauw_gXUMADa{IiqLGT-eVHFIViHh5`yR$!rw>R>``{bDB+a-?HhX1KU{-xcS z(sw7x##BrEZP?^ZuuU>sYoPlxlWK=UG5t^BKuo-hOsa(gF)*asa1~cCR!kj{+%u1* z>jr-yq-29=y|i-XaNB?Bf7i?~SKX$iKyDWAby5`X zRqy*JnF4{9T*0nhq3T+CU7N%?nkg4uXNNADCJX&+X2iXBDt;U^h?*&=cC`Q1_^+_Z z88zuj_YB0)ffgn#fF)baR*KI@=QdWHSWUck-G9rz7U?(3CGD19C%Owe0Ahm#D$lkh8A)qbGCH>>ZA}r?4?V-EzIHVmi8n2l zcD{iuY-N0SdZCQH>4I?vOYta$BM$iftA`cMSd_??JVu?O851iKWu(+CQ25)h?*Y&? zS<8p5ni!UpMM+T-VP>2J7qRrUatk!cy@pmXJUNhKL#(=Sb&5I|)9zPZAwF$vt*toO zL}>Z2^wrVXr~wMB|MYvF)^`_k?Mbv@=QeP*VvM`Ey*pE(Oz-I#TFkoV^PH3y-#S!OW^AzuxKR+lw zeb%s8`nV-UvQJNeCSGuFSDHbxEVjC2iG)An0oKo~+r1FbwRb9>E&^P$?)lx4$q}|< z!xG^$9O4uZF)VdG2)Po4P=mZu>1A5HTw-S!8;RW6PBcNbNqb>Ddz1DwECec>8$mg~ z%=TZT1{c0SsD;Bh^xq}_8RliUEH7lBDlb5F6*dkW8yweR=jupaSG9F@aq7zW#t&G* z)4!|D;@7rw^gqFUkik)cS!_1_PynifB{33V_3S|+{_1}1 zwb|GXvbdDZn3O3w1I<=i?US_JhnD$`V%&PCnupJvS4Tu`dpF5X*pva$pN2Re55T}! z>+dP;#!$32bF^WvHgiJ$3BSgm&(R>jRZlXE;|nSrxs4*xH@T}|BGG%HK6<~-eXr}i z7Ix?R+OGGYx$FJ6yWZm#?0Uaf*LxJxuJ^@V@3j|nwx7ez8Ns93?|i?p>piQY>-{p` zLj$92uh#qyJHs3pHts}?jk_>t@(}Y=!~%V6v6vkBu2RRl-APmjo4@|Ph1R1Yqx4wkmhh#mCkjP$nh%b$&fYjpf-ggH{5eZzv!XVg@# ziU$+d%+Q*;57BI8>YjcpMUqoE?UpG{RIUr=UdomRh0)E$bQ5bWrBC++gCg@)L}>fV z-!oP0sa|9{O%vg9;^}V}d09x(AtxEo+`SWRZsb>DQmW({wo@@V0;01+x3h`FTB|io z=5!p^%J4&%tyP>&HS{l>-b#(OV^s|w0|(}D7PD&DOJ2}*pt97V9sYS$pRI!xORwBq$1@ytCc#UF11#|x>Db==H z!`jc}TdYW{?JI_L?$4RS{q}6{XK^my(0av%h5Z}w4Be*j4srkQ{rQ0S^s9%Zk9)W% zwWs$az3Ad&ZF}y$y5wQMJ0oFQH?w{lPcK*VMG%k1*hxAXs2k)5_d3(q*5C)1I+ei< z)8Izh;AS%#izis;J{qCbLL*&M+qJ(I;s<X@#5;lMs6r`KrGB(E-Op)Iw&S@MlvVp;R2ZUTg{mE=O*}y9>4sagbg3x1Y~)#_m2EZ}VAWQ6N&J zn98l~xY-}#t9W{L=rMp-yYYP_6e4NaBae1ZO%#_=u&?Ld&{9Ily*iR7aoA=56Tw@* zG0#+o6HDURvr(m1Rm3@-OAZfzJlCuiI-cwDI7s7V#5?xoP&iSF9L*i0!!8M803M|4 z2kSXEL$fDynwwquK>%=rK$NHW%q67!x?*ac=#n*jq5J~M!#v!(0O%#Is&3I861?qH z8m(24ZA`7Lq-3GBDq4%@*Mcw3Un5R#7J@c%7pkS-F1_K{=;TlHh<3gZu9_Wi>Pm68 zO%luDS}V0FkFH@B6;+fy<5<{hb#_v*8$MWjSJ1qKdXQwQjN3{5RgFZJinjp!hAF^K zV5tewtqTE8S95NlhWVOL${tQwz*Fv&3BtY6$tekV6C2Dpaq%e* z>=upjRaMDc1F|j$S$tsdi}m3#|ABE|9yhC$?paiivI2TY6hCPI5(?Qa=*K+i_7h5) z9^K4iOb4MoeUeIh=L2nm^k%d!*p%AHH`rq2%NIcTZlck3|v$W7)Kpr zF(08#(EZSjlMr_-HakDS|K(*HFL$mcuj{n@)$#BqwUr3}ptd?ew6BqVe_{luq8!BN z5NRIp+Wl66c&|XL4ON`7ubd;$=!j$dG)N1a!+cMt)&GU^HXm5Ky9T#^B?%2+eR9wTpP}p5^uJW zdwCB6rNzr0G^66X!y`M_%5ipn!1H<;>RTv^qY<^#^hX7H_#m6`#KTF_m8`7}Cyb2Q zNoGm8!^4`YLY&9S7&mWfFXJc?fuh&%hw<3lFy>Tg|(zjbd*hcu*V_K?L4In|HsH(IO}VN2BA?s{T_M(= zR>z9T4tR*2#7*0;Q*OC}9!zdo?~Wa=ILO>fG!gl9wpNwjLqMC>!y|?0h>9y4Qb+Q= zoAt1k00~7)toN3~l|EWxgR6aAzJ1cZ)4t~^F=ln7hm1)9R z!>2JH*^3-dTaGB+2!!ta_Kpr%+_XAe(-lj#T?g}i&ZJbcM^Cf)>@?4h-5j5O$*^kR zEQG@7wxOpI;g|02>mzgF0@}oVW9$$LjF%*@YZ@n!Jk@LKgyF@hOI1C2MB^hqOoQAO zH|XoulDmr^g1$MuSo1;pOBVKr)(}wVFKT?`ZWu+66b>VgoG3w)vNJ(BiHhXLvgDFP z#n_Fhd!zO~ExB8P8Tosx(db&3ufePtWD97md_FbDqHAA}di%d^GPou$YML{|;6F1y zUD=iz3qYvn@Y;>!8bQUYuDF8CUhtLtpzw@A(hm+f+3Qe;OK-x>K>XMiu9gbdXNUVt zNB=vKOh>D(?H^;f$%CsaE-9DSgaOxfJlaJRiOS#GoXoufJFDhoX7na?7JvxNkkTE= zZvm`mb-kNI6tSn-)DXppe9!%9Z)oyqXf-zlr)oHJ7*kzn#EKm6GAi=2iX2W603uz? zCD_S44NZTFac62Fnnbo_VU1mIG$Omb>$_JujNI|&wBUn+dD(F-tDdKoVt66 z&_bzS(>f!rkAGgJ?QGUJO}*#5alaWACzqvmuQofmO-|V|b2t;F@i<}rh+v=0dWnDV zAA<&4rZf2A?%T_Br@z&rUVKV_EYm$EvrLx>0Iy!?#6h%7ZysjL^xM=VjRcS%*$Fx8 zAN>3EuZE}khR;&NMRv-2z(ed*ZW;||FRNf3x+S^XE?f9_*kb{5 zQ*pbc0*+C9x5Hii-j)vA2F33pW@q-+UA>rl)m1z+j@FZd$ei)An?SwrKbD|{GaKcX z`?rVtw@rZMPu)xYtI4-rKQTsgi zbNA1XHn-kAxTutdqqFi?(y*4#i{ohc6^^I=<=rimV#E()>!8o9u#pIF+9n#*mi$L7 zeA$U#rnmJBZukwqTUqyH7urGK*rObqNCcC&fPx}w3r*5g2&Isw6YD_gZx1)HK1ZbA zA-zvMwe81og&#xpV>_Sv^TS9qd^xAow_QmCzO&RP4Y+HeP7iv++kTLUMm#|y%=j$e zeeKjjz?17 z7u5vLlQ-SoJir@Si>5L?gO~0_Ta7*sb(uTyLvYC8$7v^PKHLhq_mW)x-73bEt=r&!djtc>)@@TFh(l`{ecFh+MTHy?HFvlV4$~x_Ml0F6MrM^; z7D2zt53ae}=Z&aq?JU2>oiJ1RB6NYg^?VKD(@&^?c5>@edqD=OZ5re{cR^p#%bZIR z;f;c|7B&HA#ov$8Rj#-LfG?Lo0u9aobc@QKDc$u?TeiSwcZ#wKS{|U?XrB)j+|7gS z^?`*EVF?@yPKt7itaC*a(992LCik?EBxBIi?sPrt#Hz?Me!+(wbpl9haAe_rDm&Zu zRL9ShcOuW-9zAy|!dC+s@`Lo4iTMqbOZ7Lx4qweF`Yye#2kA0%N7*Hpv_&N6_M4KPx`&my3|5}6AecQBp<1$}Qm4^6Gq)uQ$%?_Vb`4FxURpo1WeNuMFA<7Sutt)o}5z|OU-KN6?5-t@`aEC2#3;v&HX`j>~K>0+7Y91yegz> z#e1LlUg7`Yt9c~sUvC!Jh~)cdl{M667fxkP36*yJ#_f(f^mg$J_TI7SRi%0IwX!co zVCVObwNCbfIxrg4T)H$XvK0|>>fiRb(O#!sHt#x1tat3;?4(VP zYFCxb#OIVfyKrk>WKXjA^wB`$?im$ryqj>yNL$%nn<;C$rV5p{C=;snIhTg%f@(f+ z*7v=I7gTODhMnaSp>L*aUsG)I-rmtK58KlA>yj}J4jarqJSBO65`+!PB})_F}<3fJCs zVWat?V{%3hK_jlk8C{Dr`aKpR9i6>O!8!j4mad$C+K8A=pmF@H3SF|^@(_-#4Oha6 zPkIEm_*eZwGbU7=)~AGnX;B2o+xe17;gCKxVHH_SX{IK8!Uh;VTdVbcHLS_H^aopx z_Rx2kJO*CweXQeFN&JEbmos{C3~m$e>)zJEwX`Lnjph$6FcF@DVdfQ*Xb{g-BlpZN zyb}LPa^Je}r(S`_{$BB&;YzK?=%v7~n#EBfR=a!|sI5J#GkcrhaH%*=7(+nn)a7*^ z=ERZ2Pt5<0Xepde_4P8pJG<#igLD!Le$&oqTh`9$ zQ~4RsH9_49Sr_)#aQ1HMD1mNMyYZrTC5bIoUF+keGCis*&KWT>Nfgv~1~ndAlj`4i zb@4wt#3_5ntf+jlK0Q=F)~_|xCwk}t>jA|n+)B3{g#6sm;Z(pC6L0> zTQ+T1sCw#PNGE$nvHRz~vi2nRSlv@or5@Q1w5O+ih~4Dw6P`M<% z7oAP`6}f8@w6>a}h1RX%XtDAqf_GD^0*oHwJo@}txqXmCgQfJrgY4=uJlihz1;)=NUAF%rv5p+kYd;?2gMP&b?Y(RH}) z-a{fRzeCsA`ZoymL9=kRC+nOeF6l-N4Il?rOhB*sGlDh>)9GvgZvFr}qwQTyK*AcW zchmbthqSFrl2;?vR*BKYrJ~?2!CG=Xv;kh^ZtrIUoQh=8_Lv`F@^}XLdj<|4+IfI;`)YvsO7}xw>p<0d z*w;E8@qWLN8O`@9rPA@$Uw%L;Ir;I_mOl$Rcxu`b+Lv6Me zspCWU-eCnPD0P%;?`y-mi4DK)IS=Tq)NpGU0K?0kikUs&K!~vQyFNC$STN{@<5(*3 zY#iAJ5%7gzFarF-g!t9q_#i%WG=-m4q>o!D<$<@O-GXlcTXs@aZD#-fN`o4m`6te_ zT!rq)5fSy3x&tDO7i%n`SnP`3Vm}kxgZtx*!)K*Lka3e z##*cR8F{R^f8;4|5c`QrOIQi(jVFG4&wXc^tHq74pp-H&XP@d zq!bD&c6`I$)yO|okqEu_B)Y5XU;f*ng!kH(4l@kXcf%ssWr^$iPMKTbOGMf5qQqql zazos95JPWzv=JD*7sBI4|JwXVQIdmHY}DrTRXSX`Dftbz{%lG3QW6QNMy1^UeXSdX z=dSjw4T6&RfSe&NrKjB4)ah#8+Q&q&Yrfb2JusRKPT77aLxJTGe7T#sAZU3La67f8 z7kP-ZCYji01eccnmPHT@?hy>0Fo^%l`G0hH!|(W*cB2S=z2ac_$F1WKAV+QNk|zjH znqS?wDxR$^Zf;L~h@zAo5ch@5-nh&6sKITcl1HYu9Y8kR?5W@PvoAt`x371Ht&7Z| z^en{^JhUUU?U%nQ5#CT$COWxIr=a55lfLhsm9QASj*5MUXys`THhVxKe410&J>BHq zItFq5(e9GowxT9ivZBUN24E*1%Zj?9tQ*4s2;+#S^s*(@H@=v74dcL?7NkNQ$YTff zF;u%`l-+6m$?#wfyiLqV85&k0p?q3q57TrEi1e~@ZB0RoWZrnXHG0y8%lO;3Fjl^u zWBX}`4W_!XrR%Qk|!WETbn4HN}vkCtW zGNah@$3Sgmy?9>_0zCW9{hG-P2K81pkzg>)jHu-v!Cc)BBRQ8x=5I;gV95l609W={ z@p@UmHQWGRxhj}jNtwhbIL1e)z{Ysx!GpEaN-(%L63CA^TT5fF(p#|P_;@-`QQ`JN1Z9!SZ(g%Q^M zgGbQQQo)LB(yGV~xbJ9i^k#{2P^77mzt%1Fg{G;{b-vI76?()94S*Zu&vZZag(_9( zN?+(g75W8**ezwK$)0i~0bLinD|@iA-^-72=lMFlRp(+~XN>C1u!e7^_qHSX$5(e% zRAX>wJ@Bzi|L(U=d-YSUmS<0p(|pJlijvn{&)1ES=O~qX6|K0UeIuH=X$_BT3Bi)> z(v_z1Z zwM`7i+ohUyZeMhSxT2~p_86+FJK?A=6!sJ}H*~$!{#mc`ti0MXH%n5ky~?Dme@?(y z=W&+x3U03qy=ok)|BjnC@NYWY%)cC(u##25k{7wu#n)wzt>P3dLr(Nem#I@zqL+@h zaQGW@)YFJlXYYDq=b(ZqVQ+6r*qyWa>T27;$#13GpV9V&TP6aHUg&{?0cG)?H>(%7 zmAl$C&iT|~!}q|bOy$bdS?N1B^Lj@jym@ws&4aQagu17Ubr7|{2yEC`t47OW2H>b; zw%F=GQ+R3>*zVjTl*yxtjl9^8any!*#`^SBQuxYdGPQ82G^IVm>EbuG$w!jJ<9kOt z34$Zr`}%DCzqp;HHgxWs2__5U=S>~y78coJ+He%)d>Mvq7Sjb|Am`hPciP_A6cPAm zkq5EBM^RIvea(1ZwS=L^Oi+5-{esaVq&%m+`Nm_cw>|0YQFnmv?fdHOYI@5rG6dxR z)JRb6_v#Z0SVtgOY?cy>cY{M;!QW!)aq1vOGm0V z0cP58w$2-k?WinhsS=s$PMTx%!=E9Ehf^EG@&?4ivqtiR=IrB5-bmla9o$!3)AoVU zXihC33kO?veB9AC5W0fleayTtJ&%2x>DkutF}$uHY%He`VYm%uTCxcVL@y7>mu^qXi?_pbgiB;lr9)H6c zB8T^RYGf3Rn-E&n{y(DIkj zpyhRdBl`k%sbwVl$QL5n{Dr&{Cm^xai_z#c8CI1Hg>`BEt z4S*Ho;3mcxPKz8mS*oID`ZTc;31Eet;caqUv9hC!wf%zqKj^QDwq5@{jsC)4jcDZ2 z(hP7gplXn-xR#2zVHB)qS|;Ixh9%z@QwZi$rSt42dtE$h|D(l59eD_eRu#M1Vn z%o^DN3%&)09szT)*4`qV#gvPb>d~=fvS&zB9(aP*Yx2xUwR+0!OY11rll=LOuCp7v z`VvbpQj>S_DTSMtlS3FqQd9agj(pl1?-%+wV>)|#;Q9%;e|q3P_$I&|Xu$O>?yuRW zvd!R^+Y3x*n%^rCrW+(oEA*wxcFl7-ZAs!If4rFc%K0IHfAp&of+O zS(=B@?ve&6Slk#_R8gEFAKJd>9x=QqzmGel`}=S4{(0U<@eo|p%#a3mY_R2mKbvLG zi#>2f4@*}TrT%G>A*;#yA-u4?B05dzFG=q_+G%W${6A;--F`O@arnckFb31f1&H-# zDg)u0hf{A)>UEE9ep-NL$Jg_XbIN2F9ffNM{ckocN`{#xdY$PS*;I@ZB}dx$Kl9@k zRAz!={Azs}y>h%icexFJ;xHev#c-;{Ma>*s9oCZ0@b$9f0Z0Zjo3={;2%k`NR%bw$ zti89l=gTVTITrk?T{hX>)a|i!+xATcl>=$O19&7qP9E6VO4zQ3qJS`da=%4Y@ToR{54X|K7&UY+4Q)+pe`%z-+08x!X*)q%dy+UHy?PjLQ}3wcaVj~@_uCE)(C=XNTTQ>DR-?B1Xhwf5u8bXKV^&U5_VELWadl4DQUU6&?GotPW!w z0B|!$YXM$0*e@V4c)U*MvkYr8DSz_6^9`)y7l(SP-M5$@xQ661(pn}_6*)zeczJeB z#iBBnZK}4q;wCL*lCglO*duH*O8ecxqBA>x(EK3pBN$`ZDLn*d(4th?zCbKUtj|e+ z?>>&DvDJ#Mwf4UEY^MI(Av#$6$)iPGO zBgrmTGt9h%-TX4CK73+iFLF1DIa1gg!pB(zPsW;dXjJ@sRLgP7i!IO0`He9IpV(tP z41t^Tg6bXIrIK%!1a@`}%WH7OuZ>^sP6Ng-#~NkkB(jrnMft(e)0!**h~>+3btYBC zyLhH%nEOMO=rM@{EB6Q$`~eJw7_>?O%-zF35uB?9ndRIBxb-b-XO})AFGF?3?#bCv zzJx?Lk$B4XaqNJvQf=c+G=g9ox~gN4l;y^E8ju_ z+nryT)2rf{)G&9~2|~d#ZPrL4A2J>JrM8_tDWk$L5yv3E4C}#$J7!>EGiGpD9CL*o zC3!@&n+y*pSJi&{&se4?(_^3ZgVivQaDIt}wJMQ4>hwdji1_i~!SEEsvba{yxSBC< zY5|dy{@OkQ5PDX07w(Wdd$w0K&}ZR!z3W=(ntmWy+LoiOeNJ-?%PNH33`FUlymz2yIW1 z^5^*Qwy|)Ta2TenGb&$BVr|^n2Q|3zWt(Nw?1IFa{765`%j`lVyoVc`J{OS()hn!A za-t9T-#$ z8Rnr0THfb*>!gw%IFENqRTi{7#}{O84A0~w3VUUGWXf`PQ>5VE=<>gh>hA^IV-aP-jBtZBiv97F%Fjq;$`NKlm&Af&;%)v)fz*J? z&y0v!1sn1syl2&47`3{acXg$esa(No*wFIK?ER(D6g(238$EU%qm^Pg^l z#_c59F5O#oDPo-fNlqOW$+TPg`el?}HjK3m-ZpX2EWJ$HZc*xdwp6h`i&GirlEhXr z%9DgqQE%oNhS}xnKESh&R5ZvJpd;bLgKvUst2h<*(<$3B%e7AmDh=K~`n9fqtGW2} znN%Mf_nD&XgyL1%pA@k-dlF6t*||MQQ-FE$iW2lN?-WaaR&qrtofWStWCnl@n@lM; zb|j>)qSTc=V;LX&-EEWqKlG<^(BPiz)4Ai$64gpqpKN%OMbKR<4h31Y8`nucU`)92du zQrs*?K5%b1A03`C3^Ol$DrmV9wo#aG)Y-V`v0hr&R84=Rb&;Ju*}LP6vf50^h;Vg& zqo)b7lC0eifm>!!>C>nP{bX26x0gXDABI&W-6oSN1$)nsvS^FAshsmZkhYwF$GZ34 zGa0_u2%7An57_}LL7V&J{YZzgokA-c3)O~qBOL~V4-SHvOrm@8O6m5rbf<6W!Gmb2 zw{K~-TDs@!TAJ6brB0>MP9PNEy`XntEec)%>(SL>F9-#W$0-5g8Es zc_0D-@t(II|7U-IIOOYqDDDOXMo0}uPQdM4pG0G)xQ*``ZdM*hV;}j(?owl$=mciq zz1ha~z|H-6-P{%m6u0I&Y&P&l0}SA`)q=8}2kNJDC;wzauV{|2DsDo5kwHhdxIf|U zI>_t>6QqYhE$iJ;huDj6Tcl^4HP>@r#0-G`Z zr=0Ysb%juGXdSJoeZ4dSr}Va-g%E1YO?KR440yj*$${U|UqIsE8yr#*bH%!EmjL1WKw-+oX`GH71GH#Zg>`ru0vvQN&V zn4AGj=&_Yd0aQAiMc}3|LyF(P-l9;r$nReu`dEeX^=wrs|)w=SRVGbP%-slB%5^f~oE=*5MpHv+3FBIc@v$nR0d6cs-G1 zW$t}0Nu!gqgm(C|VEpAGdj(e`juLOms^N-(NYk0y(noV(?s4uJriM3Qx|vobSSX*N zyC(;1^90-Zz~+9X$3{KY^C-ct-m3b*&S&f%95?yK2rrkY^g@+BkkSPZstkmm3WSS0 zK?s^<__k&WuvlXn!>3sr!?m$+(vb1WahdE}8s$~KlGE+cSl7GP_WJ^mc=TZ|7}PcI zeGa#I@9#D{pt*}~^JfY->)ezc#%L~!wcg8HkaO2Q5Fg9$X9m{O?p5wG^Lp|{?tfJK zR*mHhc4&9A9_!UuUw4CkpU7|M_ZkKV{hmWhZXv_>Y{cv9#$|u>_BLML?>jsy>hR#G z!;9%qJ4ao);vR1A!3vcrQ-zxz)vEQ5E-s5v^6T#WUqwf4*2&axQ=|c|sSa1VeTxa#id zWks;al4Rf2P1?JGm=SP}0?lExRuFayvk;hgnj%`Q=`(Gm*B7*PI;5uXS>Si-kuvJNz6G-A}QF zot8Wp&))36Kjq#wcATnpe|gJr_8NF<`>B-~klqWNEdiHb!P!m!?li_|!ynx#?-AVf z|44{;ApR~bXh<-mFJP?8#_Hwia%cZp;Tg%haN}29v4-KT9ToM!b*eOpu+Ob;~J;kTr^aUGa z%u@n;=;Izi$GYsl4MA^#lr}M1i0b>pK+vs#`4t2;yxB!mtJ7+c9-}kawu3^?qOUGsS3C8O@sX~q4G{F9l(Cqp1{6|F?|L0`~M}_b6<*rGRsBRHm6dEy9NEE zz7m36aZLk@V!17fRNvKU{m`O7?F*WRd3ww&-v%x+*CaE`HL}cdMNzx&f2l~b&Ml3G zk`+ETy0m{=G?867HNZkLG`R8if6_rvz8xgYmR`RZp(QhMX8uyEctmH#gQC?&Tzsh5 z7(Sb;>Sht48~4yB9r*zf6IthSfB&STV)=YXM3GY#OS7e;@mE4;w)D6+d>36G8ug(I zZuOizlFtn^0Eja(t%GdX_JSv=4bf+w2J+;t{Gr?me}73Uf@CC!NDq{&6s9Ni|8akgT)G`-Z`ZRG~xIzkg(?;s1O-wXcE1Z&w= zDOu`}7#lwxb?#r~b&S2SN4G?Zh(mV&?auPN7x=19#daE}12^{zTR~0B?xk0WdOkr_ zYLBqV$S2doFQ+uu^l-FZG(R&Q{$ZN|m+?j9tYI0eNBlnnLZRf0` zWu zW*|J|EAZDALKt`K&=`W|S4}qRjBmhJV*wel);+8}8<4^|FwZL@gPqZ$8xSj_zz4ac zEuthEZf&Lz5ogq3PCOlFMgEdW!6?WGu#r&=RvBmlBYp0D!7- zm-Yx+j_|*TV>^gn5rxDv_lOegIKnt>Y@y+m^JJhkLbZ^KH`JpS{~u8!x&D-O&%J8Q zzh(%`Uq>Hc{(l$@^Z&AR`HLk@Sy#1cR<_6 zgEmm0#dZRXOV%%R`+3lm0XbTiEXp)b!4mv@w(4S;UOZ$B0C#ektw2uKrRVntx}J}t zQHrxfa0;yam|)4|9`W##V9AtXF4rrI_gll8p3%=j$xP_$?Hres`MdBF$qDC(p%t!r zJ&)ilDAb=ukr|VE!X}d)*p(O&83j&MySnB#na(f4Q} zY?yCN62V7ec+(IGa9CK_$svGKOEyv38^ygx?pGWfm-RYu&-??SeH8nCPF_E$lhj+| zLJsBT_pH_YD5&!-IHvIidf@Ba&sF4D zilFU02A5>%Trv>){4KD4MQ*zGWo@g{u*o+@saUISd2mO4!R2{q+ntnBFG`Vl4DX4j zl)`?>1xJzX!kaA)`y`^B(#;mFz^U z0Hazm_%y0g*y^cQH{^x$BkB#B2UFDj`mcq!q@Y=+sO!Q)xMI8TbqO&t#dEjYfb&yUF_@5Q{9}eJ3)0*)Qz>)sgM3v zty9iLUhI*Y7*EeBt4hJAh_Cu$ONUqbN9r-uqwcmK@ln&9vPODVKKAu)mOkjBi&QBo zkn>!gLT+Es63o5E7+iPMbm0UX$=-{dtMaj6?xB=SghzWrQ}H*W9nexQpN5)!52%7BBfA^L4_>>#EP1j61 zC@g5!X|zQ6n1vLramxpM(NSmju50qe7mshc$|vdQZmv45@+;=5-yRp4s}{cq#G~mj zSIbr!nX4FL>iSMo)iigIjc?Am-Az@L=`>YMoMASd@g6b-y=`nZj9lQxsr~UDBMDFe zMg}l0S0zl1VZzy#<3751fQnWKl!wj0L@X^0%8E2iXQ#s2dGh2s>?-zAMX zHFj6d{gtR!Z*wR{al@!Y#iIOW`UT>O@)x>AYOkM%^LIjgcEAt%0H@(c27CoS=f}F4 zDyIOR{0r_J{eDI>k}YlUb-t}S7cdZSDzd;GxR2J+@z0BU7Whm!je72h7j^&Wdd$yy z)PL@n3w2NFdGr7Yyiw-wDSc)uEEZtn*fPs0DTC6bR`a#5H zIZJUOtV8RwQ@0M9WrESf({3uksl^_6%F@fl2MNAV1fskAdE*)-jIr$-qO|OQIFPw( zK!6`zr+_u}xh}ha2=W1Uw6DAx%(U&}EB907f0E?)Sd6acb=d-`cfm?XSMIojnCV z*{Qwme61|$Q@UzqPa9R-i9l)9(vD|zG)gsYrH9C+;O!y92+4^8a*lZ4riCPnKHG7H zxiWDPeGsoOM`o(jeDbolO|7_!Ttg#i5er2-3K+rQGZia=KAqXXGiRYYHbk}w40dVB zA{zKE%i{k&$%I;6PFwy8xK5kFC+~Vi$kh4x4|Z|mocXNHPF(nm+&G8#0-xuD=WcOp z(ITjL#^mpTLVTASXUw@;)v1K*>l^zV`Y5<@UMr=s-Dr#!cAlK~Hflk6H%{>dW^2tD z{JFns_3UD%`))zLI>pOZC&nX9_UJEn(0LO3*E2SfB7b*yE!DK<>UtV9^Rm8 z#u~tKa0lJhR?aC)9^+o!Xy7hXTbKK`{;sy(q7M%vt!PQ-$qSQpchr4+uooMsRw z+%HO>(b$i1H~GdUsIeyB*bFuH^X`p}fd_uyUEv$kWxQs`tZ=9K%B8BD@s$r%<#T-H zooDSBUtN}>$kZ7DL%#XQ)OqYy7KXQSD$A!gaUSen%DTDB)CMi{z*?vE`P#@HmQ?e} zJql~$2W!z?l&bdm~}SvlBYv9bDLHQH-hjF&%L2BhsH0Cl7Sj_+~%uNwb@Lv-N5=O|#iE zzm>1aESKe1QZW15K~hbsf?HS1UEk@%bVvI}{;EcF6Ev{(QzOR&tMSpd94v*Tksyu+LEz?t zB5-pcIO8%z2sWoZ3b|_#6}iDm>2f(dw$^Pfwv{{5z4#POJV+Dy<*ejkZnd6Q>iHhG zT)*$r@7ohd4jQ};${|Vj4Cdaaxd?;WZ2gzPlFN#TaU?~4zb)j;C#7reo-5wsA)bL& zDqjd%nkkI+wv4o>xs6tFXZzgc1@8JI&t0c;V5;XVY>xrfHrl88A6omav;BXU^>b<; zwzxZRf`PG+MVnn?pB>;j_96c}=!vzSD>NKJr!M~_<9Uto#&i2y=CCwb0kZn z9a$g>@nb?M+W0y*{6VuAM$TRq9t^cmu}$KKIBKDm8@S3$7Y$tMs5Pn96*M=kF7pGa z`k?=BJzG7J7vg ze zz&oM$8g7+mv2et7%vN{fUnIl@H(tU=@6Yg|!&ls=$OJ8nn_i+H`SXJ2Ln#!-$A&Mm zS@YB4w=ABSUoTc}3>NO80#)NWVIlH*fueK^n`_Wq?VltO6$Q;l^Ry+_F>gLk1oOZ& z^q94ef|DG+AAtg_M{dAIeT<)qoP#fTz2d}-F~fZDJwk8-qKM7u|wxNLC>Fr z;q9bhtJ88Z>c7?LHJTv)>o)&VP}+G#>4JUPeC(nyVS6WB7gpbsPjV(C)sxGFcF9#l z2F#9*RDZsjBo!o9a804wZdE8D+2aV$(j!sI?N)-4!ITwVzA8taXq^Te?l+qw3G2gJ z9ZY{h*As=?-P^xZi0oC>?vlq1$=`r4Tfh<2vs|3#3XpG8>5Ys2wB0F>*(!ypET(P9 zW}1RL$Y5T^!LayZWbZ`gcOx442J4fJ6Psz_0HjzkO#1#2qU8jZ$wm5$zVydjV?tn%WGC?mG8f-V)9mwERxpF%UHgtvE&%zS0>}pRW=m4sDv7|6*Y_%aF9#gY%^Tp7WhVM)aZ@A(M?*c zw|rfrm-x;_c-`l)Qf1EOeAxw96}5rF zTWng(U7sPgX`Z1JivOk64PV>p;a_c4>rli}?*6{JkwkUu;RfC%vg7+QOwN+!sq~Pd zNMqUaHoNOqeT;RHL|U8x!Cnb+>Ox|iA5-A`)9%uhLTY677iAc=hMuTJt)g0yME3>I zwU+hE`;QL!r>(p6XBTrz;AhFmRWzu!xQGkt3a%onDEWU_H~BxF{nLoito_!_OqP4~ zAJO_Pz2)V|m(bF#;SpLA&(>(6ab)Fg61!!7u;$YZ{JSB&xtKrgnVJW|!5*LOQ)D0S zNN?Va2<4-Bj)niImLKZeMxS)(NZvte{rGd-Zb9>p=$G>z>CFcmcR;-vwt!a-Ub0xZX-x0yD&+=+JNG@oZPA~4D6}EbBp;((J5R^9X+l^Ye)2`@`z4mIy zS92GD$F@GsxF@kV$WkMA;y(YC&}kWK$hr!<<}#z2MQBP)b~|u?tRZPLV@S9_)(arDw7byRrU zA}!Hp?2=jmRk2vUlN1{NLeJmUCQquo$=*$LCmO(86bN&%+t>HJhkACt=O3x(gMH6r zPmZtK;7@4esqn4BpL@Y?EmS+>KSO4`|Kc^-|0OJco8 zyE}awzfv3j@oj9`N*nk1HY_=o-_6#$8`Q)RBFSvc9e5!Xg?agl7Irl(ThF$&-i-h_ z?FQG@f7FrdLDBGxDiu5YBc>-)(_V012$Px^pQPsa$tEwFK$KbPf%QSDmC)!i>=wjTd+o3~#<0nD@Nu zt)IfHvits?hQ+JST@0_>{vRGdI4gk(-oV?t^CLQ0*Jsh1yG2#Rx8P~MuSvTLU*dQ8Y)Adf{IKYYjEnY~msX0v!BUR*<#*%qnAnP3@7SjsIi6k|ORvRR zCpNOaI;?pxJQEAtpCS?ZcOx2UUh>s!A-F-4HM*SFBppSC5@e5gEtAm<_4Y+|dQdOW)nl8S^okFA^f}=5L*j z#ctMdl`!Y#za{e8<~DHip)Nbu4i+?DNHM$h<~;pit68yhn=QnXdA2RaLKj}C@+OIK zysfx@gp@z>8kqBZT_UJKW#WzdBr3HV4?apjJI*a;rE)Kg_f32PhPoP_8PSXC~t zO-hGY?vBbo#uo)>CbC&AaiW4Qh&@aPKwIZE105stwAMUgi$3sB6{j)ClbPz8CVhbB z(DtaWhmmIFaqrPC+S7Tyn+3j+Zmo-)BQ~;=ZV4?j@~B7ceSdmCVk})`aFeyo9VDQ9 zox79!36&3G!3fQhD0SmTPpOOa-1Mj>wmYSIIbZWX$l|~4%#!j7HB!)xRb`!TD1GPY zP6}w?3p4M1q3)(PZS&FD?Z-pO%GZFj&5|i+0yqomBG7~srGw}9P?PkAI^!eXN{pQk zZW)}V)cp%av{T%@@f3R>+JbZuOW_ZeeGdNxBN};E$jk2+Q)jh()@?&JOc2o3T16=l zg&`nZ=kxm07HL5T*9|JvuOZ+0Ri4%QaMw=zTcYx^(J8X3gk#~d`BOTLELELGmZL48 z7hjb4a018+L{T2ae(5R=5&!QD6#rc*KtgTc5duU%GeslpYz1JULKHXQuD+3~BA&P> zHlwrb(8Z^NDkCyaeF>Qm0=+4B!^+6p20J*?UGjjjgWx@cjcpS%4RsDt7qk=&AI2flgO;1FS$QvWHo_+$S0eazCn4Z zOn3m0f?d2WGZ=z(G_(hqv5iP0T zjVQ98mX>@ZtE@J3>Ys8D&PQ(gd@V8Vm(C7te}^3-be!xdq~lr=E1{J&uwFMRuAgl1 zTih1CWdV+JXZ+ph;x#I^Ez>Bn1McLvJMVtKQAmv`Y!t`-%`7oT1C6jB(l55PnA^>_ z@k_PQ?%OzDZS3va=xhLwcD?)LJ_)iV^be(^e5{?q*OCzQFccAG~u(z9DCmjNUx25GCj*@Otc(ia#9>8f!zg>-d6 zwH6rnQ`0vV6YJ;yBkfJ#qbim+&_`xhATCkxk`R;(BshVIL}gP%P!v%? z5oQnsAz?DWco;yzt6n$UcR@v%3@!;E0fQ_q2(ExzkGU$iuqt`qSAEXRByj)l{eBOf zoUOaMy1J^my1Tksz0TQO0OFLG6snc3t#&H#ItFMLo)9M5(}!N4!St2@=fXqN%5;q|1}UrkH=R>h*>&%bUO@ zY|T{9#J#%c%{od%k6xRtVJSP5C!Yw0}oYMdcZHpnX(26wdlqPh)4+p-R8TLd~nJqKT_DA<4PaSNo3c? zdSppm)q4ml2kKK#KwNRVSLK#bPsl(jQ=NrY5oK^peaEB_16N_`DSA=Qyvg@&9-uiq z7pQ)#rM|OJls+yxm|BK=H4t=wK^49e>6}4VYqb<4;DBP`AhtHFV!x2L2|U9H;ml#X^eW1Tra(N$T2EiC$=ZKTjVYQePkoQ6USymg z5?+A(V)VG88DVRXTEA4X>i%r95nfE=P}|%ona-fO)URkOdt%u90kzntICZn+Co zgV&_x27?;mak}M(<6bpEi`HqmYtWRIYKUxu|BW_0t-tVp%tL0id5a|+_j7`dxQ&4i z2p1>VTJ?UF-5G3!JO)`X2|~4< z%HChVnpnYr;(*^W-hXSoAA=WsAEJEdtTxipzlX-)gKA-;oLsdj+OJcjI4U}>rth=O zV}xuhC}l4?KU-~oMW}W!saB0L!SC(A1Jyo#wZ3xMsn)zKJ#hs<=G-~0Tx?D~{lZ9y zSbSQJFVdsNwA=&^9Ar8l6hWiM)MPOqRoQ zF%mf6=j;eZ&BtjDWnt_uc{1IJSZcro4bCQ`RFC*x8@^xTJNp_~wuDGOV`CSZ)>6cX zcZpHI{}-3Fbf)(_Fy2uKQagl9CRR-Z6F_`IJudqIC*)xqaxv(N`ZhufKt$W&LJ`Gsq}!$l@GrcJ3?;#gjDmgE zWWf@lo(g^)oh`72F>~;SODm+ExryUtwi5e9vIhIaoXw&u$wOFhjOz=@W6~d5{$y)5 ziA)qCWB|LYeeN7*%Jj2cW(zvMl+&b5$ki;`YfcI+DiN<%i%5_n1t zj^;61By}(JooFz9sM~CYyPq4tcd9Xd&IFzsP5=F^?%dtedl#CO?!;~G-Z)tiQ5rBf zNiourx+9ueqRZZ38G!$?Z*#j%B6aQR+vmv7YV>i*k}x{Q`R?3GgxlFx1GgzmiZl^I zy90w#;NzBx=_z-wycDS=0B$<{e8K}E8gHs>qtFWD)&3QhFctuy97jmU0IV<3@`n~F zSO#}oDjA-my+2UkLkLE9pa|=L1rMovS3o~bJjNm1L0D`~IAU;pdf8`qpc8m7y(whF z87eVQX2w?RZ6Z9Vn||u|7eunZV^6jKpCQ@b9)M(@cu^$VDQgA#IE!la+4GoBrvI8c zIrk9wWj|qLtJgJ*CkbP*hVdw2tg~Ur@~@uuuU5+mWEoiA z_4!!FkM|$LO46fj)183g%&jt(ZNZJ(yjQA^H15E?PpVR+1FV56Q^RUcSg+`6r=u<^ z3*>-#VUKk5D7xu$$D~ScVVXMvH)VNv9uHVNFQ$S=x&AMBle3U}Aq+pAEsAuFK&4hg z+Jm!-u>YiljBt$ANwfN{I{`cLlEB1%8xO{*JYB|EJQ)y}2ekPO$`&}On^y1$2xDmx zK3QiFV&?NVIen1SLXV8|CFxLg?ov5oPLAMnV?>Q3=2Ev@*B(st?>vF~k=}-@E^=#? zegcY$dOQIL8fkK*BT0ud6M=6L{765?WbQ+pgZd49Cdqt+Ubn%KnBUu}ntpqdh?PAL z*v=4`fmn+XdH8_-vIJic-;|YMhA*twUcAmXy^mtn`USjq24`ltChk!kzt_1&;WH+_ zU!ZxAjh;x3&}02R4C?w_!UQ-%FB6L5_u_wbvJ|Ty}#4hC+Y0#@$p+{c^C7`0_18dtV(}dIxALcSlP_ znjr=kTfWh}L$#`<{+h_I$0=dIVy+9^>d6u=A~qMka)|y1uoF03VLg5mQPnM8T`T8> z)(mj@-lHTqjItM)iaf~NPvLmO|1&o;p*-*GOyz%CP@M^}41c3Vboy5i(IAj?hJFUv z$PGY`jd{;)M-WqxauX;5U#g)xYc8{X$9kNDgjEG}Ds@B#;9h0w6z!SfEYcx~HLbT- zp_A=R+v-v}NqL$91S=Iej@2D5i0p(bV3KOKpUvkPY`zU3gYSIUv?Dv zx__fqlDE#}F^8NR81J&ebwoY}P__IisdVYL!0R(&K80`Z(Qj|(+vhYXZUIEK0JS(x zTa8<#wN>(5XshAOo~yH;$L#m&?3v6y_)OW)LiR{!WQ&>q7@!JXgPcr;aKza1nqU~zxTlY+;SUjvV;G#+p510Fko-)VTf^aSy!aa%!0b}E-> zNPwBI!Hgl8Yc!ZC1heQ&U~bf4Vq1W-IG>975{6Xq@n9x4D%&%|YQ?N_%cgQ##*^Dz zybIL8$!|v4M?#kSxsQq}ILlePn~I3LZ%jO13bV;!ETVv8UJ~o1C`dM4h3U@9Dc(G1 zi1OkJES7Nyj4SgkLUWm~^9A;ci{xCasmPf&?d0^b)ZWuUTfVU>!2WgVdZ=5T5b`bt zEy5m5yu%b5u@`i?6ZEP_Ug(3zg}iU8i*&B5m}{!ebry5w*txVJ&u+g~wMH(Q+%BY#d64*_8K|DBSuaEsBmQ@(e10$w?7mMOmj1|dzFk4|r10XZR@(NHpx^80Ta||4P6BR|dvG)^tbg^dXv!t=PuXd~N*hR*oMIbq-F{-kn*7dNlt}Nj( z=Rk+Kvh*fgT#37D5Bg-cNUbNmN)8~o0J$}x!69Qe`6RGTqSyM`ss7imurlc|mfno^ z)A@VUO`%`5tNSuO>eN}j4UBZ$z%IXM-K6?!LWo;Z%6s9Dk-t^Y3z$+*3rT`VknfTb zQG)|go1k+qsmOYW@2g!(X5CWQ2y204IqT=I2)AcJ1-k<)SVqwKgAK!h!EmC;xEJ2E zd;^+aU&p=L_ULI+TCARZgi@+e zthj8TU|ePriy8-?7fdA|7oH#FO8nK;@fDN{>B=D~&n%An2BVsjP@q2u5NLqF zwQ+odU>L$ z&o?!r&Np~x#bA~~j^gm7tVFB)7aXADzM+KJx8n$I5cdrnWqlKJ2rW=;4EJ~jFS#_B zya&=7mj&t|2JXH$>wu#&()m=@!@`i|AA=!_fF7EvGwxOPBNjvcmuY3^XR&JaP>dmQ zj?B10105UC^iEu-;kU$k-i+&h{QkC{ndVHtc6i?xzotl6jH@p$-HTSxq|S z{%K_QN8hihCqKv97-b)Wp1xxl*w_2^zlHQmcZ2kd5d+dcy$hs&_n|ZBf`=cBk=|GS z4uCkkGf^wCHGL8t1jjDnpuq~tf(OBa$|pcf9q_L&(&aqy3Cbx4=c1hcENA4I%E^i= zM;zYN($y)BqkB76`1WJ}ok--z>Yn=Vt1nZuqapXA26$4ppnCkP$6O{3NM8MQFfZTM;Zw%#t_b@=StFbzI=4Ln^W-BV{wCmRY(pWX#5d-sj9$7DN? z>;x7bz!v^Egu`cBXz0+G46qWX_NniUvTFe$8ZdA>#-?%kNry*ZN=oy-FGWRzYC2^b zmcJw3nhrUY!C2B957Ht=St3)z^3H=rYwwQcOpmoc8jukeE``)tFF1la+$VzF z)vNqtk6D%9h*a9?_z|4m!1B(<8|m`FOntW1reD*!HL$N!zTy7|Qxq1j8cPo0!J^I& zxFzxfEcj)g;)UJ>eND^1K<{M3KO6<1YN>;~Az)_Z4vv#+Be*t|dM@_~*Ek$xk7_BZ=_9@5xWy{$i= zeWkAc6np+|4|K+TZ`-!~WcNVKn3a|0tz6#L%H?&~l{6F`-e)aq z()%cw8dH`iTx-*jIN+^b+k0EvV4CVS_fMn=U`9A-t24?%5Hx#wpt``auOoLNA{2P6H`;IM(1DI}{C>snJN#M?8|WB|UrT)B zv)%8qlePaPq%=t6eUkMeIVG+?ZlpPi<5Qf^AbnEtOLcilTM@>h+jR9Vddp_4$BH#$ zd2qEE3l!w?n-Bg^k$zXPsqevAxC2$qQcb6iK&NxDp#*f=yA^c$W0}wiEy|D=jMSrc z1wkc*C5u7YWJ)ArpK1byIMb<~(7-Mvuq+MCB(Uc-u(~txrKf{)S@A=TfZk|mrz+9_ zzu69eIT~Pp0vu@rLM>NMamhLBkiqQ@^(z;{fZO zNM{|Gi?grsFv*y)H)T?xF|R_r@Bfh+!!@R`7I6o8h?49{|BtbX^w$r$3n)ryW3-ee+v*$Rj(aJ!y-J0e1bE$*IB+3A7Gv)A(h^9{Pd5Q zK?(SDk_zu|B%c6C>g6TEK;5d*L@jg^J+uW)^kz^PC^$Omt5&U+nw*6JZOBBVQ#{d6 z$rpK#Lt3le2UkN0_*h6Co>SSn#5X9~O?8PqSYnJY2p-4M=!Sf%W_)4HvZ?>vfJ$9d-cPiFBU`7e7HKw7z1X z;~f05@f(WY-@^wwnnPSO@H>w07vt(^tp6o67F*qV;-wM)q)x zMj0c{mY!fFP;7u@F92D@tO%a@4_!RDLjAibb^*u$7?YLocG(j6y*3Qvg~>7hCvl4e zCG;hAMj0*aQHHmX??h`)&zc3k6NcfRjjluE+Z8~9gMPR0J<;0mkBffmj&E^8d7pF? zs6;MOSTi}^4ycwr-F8;J^e5UGegkQ(jwOS2tVPG7OQwns4vOfKT@z&@(044;So9T= zpk=Olt)fBQ`bDQ2*$+419~DX8o3mjR$-9Hs~>9CuysXXzI!IV4b$oOyjve@*2MTHVoi& zg$FqX8~#V5InEY*-m~#(?P(sF$K-5hZ!}fCcDC7ZL^MISx~Quc775*ERf2BA!K$F! zO5Cf}pr;k(>Q7{`=oVNQqucV_s|Gs0y>g(VGpKt}+-ZTKaFQTE{44OfAECSxQeMZZmGkYY~^&;+sd%craKco-fT zqGCk9n8n4ugDKw5wqe&=6pII;4J(;%e%UiCfj`o9n9gzze#8ja-9^9@%)7CqlniiOBlXT3O{;#FuRGv?m5&= zozW)L7H{=Ta~vc3B-%WKX4)~Qz=}HNl=ne#$2mh5Jw4scC!y&blC4({Ws zN8m@18^Enq0hUlN0T-`h2|CqHpvm32?n~vn5zS#ucmsE5Q99LiP!-i49FkWtmHOvLe;_aKh90T+m4GVWD|{|p`U$ptZKg#3&c zJ_>IT!QTz_${Tf_9!0!|M90|=&|A#m!Ny*I{ zHcHW-8aHX$ELEHK^4Gkd3i!yz1kd$u9MDi`N;ouGM(yIXrV-|*Yq@HEWMhh_u}@AA zN%UTTW7;r3oG>@}$i^gZhUI-}x-yPbCVB9#fv4G#%Hj|x<$y=FIAftiJ6Un3BO4of zdmP#5^1wZ<^jISjI7H!dc#WeQSApU>>w^{6G^0jZ*2}E*#)`)*op1t6WCw5v#wzd~ ztPd{XZmy8kK=>N?cHyn%H)yWdDoJ)C{)2qi=daP`vV7sx*agyfYb(%rKc-3Jx!ytJ zP4u0i@h&UX)>Z68C*p_wQP|324VpUINCGW5l+iqjvyB+PE;=278GqX}YK&Xmr6Z>L zmmmtpsS;-_m>%9hH>tBgdbRB7!|-0nz%A4jqlslOWib6ABq`^;dhIE?oJB*FwZT2p zDQ_uyhO==Op%I3Watb;JDxu<1bvv`7}Co; z8XI-~Mt(=EBD}PKE?GrQVU%r=S3A|;>va-6E{h+gH}Fj2!gHPl4e@edH`#0C-2T#4 zpnLj8i*r;;4ZG3zJI`(Iu!`)}pOs~l&YdbK#d({l?!>ql7}pe%Ajvpljyq^+?^mnQ zGbG38S|24w6o-yygxaGbT!_Y?L=TQPseSVSDjx~aQ~iUMg!h*o>%9_%h=M~`G zVeI#t2BcNKh6n%26aTjSC%H4ye2FoI`qW}aRIx}R`Tch}>@SY%N%bh#bBl94&un3X9P}n7ff8dM-${y9VzAuZZDp%8@HX>fjA}6X0=-04OjL z4vfrhHiolCl4?1H@`C6S?KP%DiRl83X+vV#RbyJW{r;W{RG$}++Nm<=Tbm5(z}Xyr zc6Y4r=zuKITMNUK&*_ky7bwk_Y*Xyn8IO}?ybscM6ueGk% zSl2O8qqjmFqv8HcCvf_0qf-Ef&`F-Mj5c+s((PKvWui=vYutfpDXQ_Y~Qq4npQ^z*Ycb(m%oW&5v78c3j&;XZiUc`>|8c|a3g+1!QZgCa`^LAnc?tDowm3oc^8 zuj+yuv*7M_!Ft=A_64oI2L-=`#ud2r<|_^VyP#N9OxEDR5|ihIk}_LPOS1X&wmBP! zqp{HB7rbg`EGWUPwJk!tM0{W9*6WYrpwcyS?Gp`<%ypt^o%^k0elra=Z zsGkhs1=<9ZUU@^t%i-3%v}NC-9GWMPZz#{nd1Qs)Y|oBlyZ?KFFJn z&fvTIQ{X8cOP{IDPIQWy@mmrs`)*42cCqtKvNbd`B%>J=;*dKuYFu~s0vRX4T9Nw? z9xORthFe!q9GE01xC9_{P28m&-RO#b>TPY!yb0d(4NQP(_tgs>9Ug2DU(pG#wBt1s zezsO84B)M$w{qU#T$UFLGJ{iK&o}TIId5^8=tW%MHz@7cntCoYK?PJj;H|=?=0Xb{ zlx37n2F1<6dFHPX-dTDVYk|z`(s}~{OEYE~s^{IXSe}3gM_Lgpapxgc7lt)fKe3{i z3AeUpnOt5$#D?1CRBE>MCeHW5n<-YU`4yOWaYiUz4{FeL*ICWOQC*s{m1Hh|F0fcn?vUs@2QOxK@rB$y;zre4gq!6SPn zS{erY!+)YKP)q$-iK|dKU4z)Bj-Bc})?%AVUqYYcq8GriO_10bN`*bEzI{-8Eca}P za79O;GH}K+_MRw@ln_~i5{~NO4~AGW=6%F&wR83_ttW+4US<=3L*7=dWWwDHiLjm?M7LBXJ&&X5jm%stteYL-<%3JOqTb!vtWpdNe@JTSjQuPjD0r z_(A)&j;aFbzEx-0%;M=EO97vV^xE|u9IAo-)Ft)_YBoK)bz96o>n$RF13*=Oja@FW zyHsP>lh_S96Ly_}9mJubASL2(@|CDK?0P_pL%T$X!v=5=IJnFx`wC=rJy-$#V>Lhcs-0cE!2CbI*EN<#`;4LbFgM_wM1tRGW#%{eKxbN zME2mQOlK$;nIl~902fmM8tc*R?hLF+A~Rh7Y<$xgWj{B>b8zGf*QN<|UPl9jr|KgA^D>Hj8>l!#oJOqarWWf& z0VcXzC-O4Ua!GUoaN;%CZFfqOUA-u(!CXjeX|T@s>n6K70Zn!usKFjzG!rIN^S!R4 zd7ZYRQ13v5!S-INn(LAcmONjVeDWof+=e9wM_wGy&Fb(S#;}gi#xuicD>_blrba{@F8BMSXTU$|*rNpW`5?SZV|6pJDgm}aiO5Z0ChPo4-`u~BLX#duIWFI+2HwWOQMGJA zZ?ag&1gzHRZhj-Vh-oHR3YbSp79CZ`dT?Y{)W}!S=n>z+M!`-EDo-Y=gLrGbN!(a@ zEV1`q*TgS9Js`B$ef0_9E`LtL!VUV0scfYC;>3|P0 zGvx;BZ4%y^BiB2{JYZoi>q89+!=9}wd+KcD3;f#Q4GrugT`P8xKf$PThCV`5sCSkg zhK|EoX!pJlq1mLWr)v2}1BF-X#tI?1`s9u?D8tvMfOo%)45sWppfj#u#*of9pBevi zri@;lu?aI?qcdL1j8Ex|LzwY~Gi4m0GxGcZm7z0sWyTM6##Cm^JX6L*o$+C0M13JH zSRKSYm|c&H#-xA->k*R9DC-ZbT&DMPH1xOV{Sbpd`7hO@f-d}ojesQVQ_qvI7=u4N zMM(C@i@@Vsjfekv;IRt$#Y>!YNONw-V3mp;W)SA8V#m{8f#c~%Mvtf8p{BoVfzQ$4 z`xE^48vHo~?>rOuP6W>ta4_($7Tqvj5Z_Z=bjinNh2OIy~W^+ah#JDw!BMgKl zpo0Z=qy3%ESY?=1+H|{AYBLBL{;w`|&2uQV8rYmxspoG)sT}D$OYhZZhmA$~JM~HT z?RRpw;yert@CHm@t8UrFHz?$KUC4MA^1Ci%7z>$X7h**a70NkT$Y;XEiw^M;90?J{ zjzJUEDf-Qwhy(Bc8P8tnP@##sW0v-1B*VAWXvy_7uram7O0G9_KsHJewmfprB7_EQ zBC`9)>snwayLM)zszOdNfYdB2`v*iqXa78wy~Ard`wQ~5;B#zftTOx@22iI!`fh!e z($@$bjk?S{jIDi}fCfqiufadIG};X~C7l?uZIF(LUw;xh?B4es^eBO%TYZ)&x?1(T zzG=%QnuOW%rdfORT;F-x}0k&>HXS)Y*4E{QcXJ=d{!ua7Kste;|c5#8*sg zIh8&20G-P8F*NGWTcq0K&=6rp4nSKTcna128{~*Pm@2XtG*eYNaTXJA(uvnH@lGZl zf+C!uzwtNn3KEy*)Yc}T!@dSoVzuG_Oxy4X)*U>T@|FQ6^P&g*`rToZ6$atDp1hfR1cv3QvBcpNaM0%vyZQJRA2|tyAtKst z#hiI2%SBnJq9mrSW9nfkI&~9#hZcaGY>-X>(JStDnzgFqFzUj2w;Nqb06>!PJaq*4 zmC5fz>gPNDs^xCUL~r~29Pt$}{A~fO%11aXwWbTlh#Q&CF$(F#rGL|{y2s=qBg?I= zQfm-@GxykBjIHZTs~CPB_Yvjh8}MLp^C-!S^{nq1)@fuhx-3>{EA#@9qjVfZ`Ks;B z!rUcjyYNMjS+GpflW4~-Af_`^i6r99gKmr2k58oCTU4wjAWAe*Q=@THXf9n$rV6HS zdxC24rW62v!cPTjipB}1uaOTo^MfBB5Vj+*K|aMR2X)^~g3KR4Alz0Xb2l=o2Y{qA zbPcK$0UOk+8+E#Brt6{84QIOBkS;t5I6FgLCLV&swkH|_RIT8&1Woc3Gp}9FpmsQ3 zsGWvXN=UgHQZgZB5YmMLDU81n#FxczMrOl`bZx__cuy-J6NHh-Gq68rsD9)0+|?dr zfIjmM#i8#WPikxs9K}!ab&cXHQ}FMD3b&oB8%eR zu8_Cbl|iKHGKBY1d!DVYFoNfNOdIMpFgb0Ah1?(jtM0kq8L6&b0;7z`|sf zZ!5`g2|(HWt~QL(y#Dh^=;i_hJbQRt5Bi_J>upx2nM9K<#nNJuLyQk+~)oP;oBZ zB1DKSZ{mD&vj7l$yFfWhF!T{TC>3$=L%RS6+`pFw7Y7y)g=+QgH`L54n8#Aiy(c1B z04RupM&z4&#*2h}2O@>P0^K6lpPpB8QKGyxE+XVErVEodY9V-y-cf-emLoh0+;}u`Tg~RRS~f|qUCG%!)V6; z0$WRGjzrSP*5grR^K(LnfGp<7UeKA-n0Wv-4*VaPc{MUSLnD~aL_S;3wDy1O9cbh7 zFOAEEc0CziI-c^75JL??0pUVGj{F<)O^REvcm%e!mRgNAAwFu~CAz206jY(T77Ix9 zYx8jv>(>rH#C~lYpsFqN;`_C|^5J@Zcnu$9ULleJXt2pSI*eO-diQS27$Ke*P((~u_4g>z*}^- z#T=qI1fVBA%ayyHD<9r;!3p8P)kmeY42`nEs0}iBAhP*-In3~1hR^wIB{H^L6%;?zwC@Cf)1cbOXPBv?uHwf2vE~@gPc$0He4OzAkz5wWkxuSSL*>&I>iy`Hm%e^3)Oyl{=nRbIXNi?@*BL-s-0jX;Bjjmh(M}pg_%hlu_IUB?PzLmq>h84|a~}?k^mb5d z4{M>|LA0}5hwv9uh2pe-B1wDNTTYaof%SCp>HD^V%xsID*a=2jqiCF~zh3*YesZ?jklHN(~W zV}wk_Xt3~unwejH0A#8H`K-n}2=Eq}o*ErTCY%%xq@^B2`Tt9+b!4k8LFY&^ZbRmp z#@JY5_+Zeh0nBxeyY+`a%Us^n~hQWWvJ4US?Eu?rG)ejHX;GQD5cTfz1 zIA@2x1xVkC8O{(Xg8V!w4@D?54z|tE$Zs*UEz{VmsRi2dUzuV%wTcH|2GXlRci9ro zy-hPWdWRRw1P`v=ZRr4@!M%1iPG_D!>xai{>#T zQZynybec?{#XGmy_65&R%m6fX{hiXrZgWry8~F`ljdnKoLC_IT>Ozf=gZN}?d^!=I ze!vI3795TB#eUMv)v6V+iO||}nGLXWP+S=~!gb-iYIkrJ4sGk7ZyshGPsH~$79=8N zVKB*XbHLJouMI!jldRHPts5aETLg{|57h-fvlIot2ZY3iV5yNGScQ{_MR$fK_e_#W z@VF*l;Fn48^VKyP__+i=QUf1C;5Puc)gH2zNljM2$wu`c4fAc{DJqT`$V9JO7ie4HtV=#=G5`6*L!+zGLmYAL)mSLuM7c|2>=#in0+ zn{N7IG(8%e=T%z$w0)s`%XyhpW9p8nmP{vizdh#F3oD*oMxS4J9yc1FE}_{ONDuEd z^D}t-mu;Jky)9a&;}HRuWyua^HeTPqiz#v6z9#KRWrhdq4)G~p#MdHIP9`Wc8>?oY z+RcUVraP|^GVKCSh1clHzq16D{~SaS{=(Kyy&_Sq-nx=HQ%(+G&AYch3;~{>qf8BB z31O_&FlG_P3JpV#4xt}qN#hO;!PDjj7R_{UE zx;W*RdXw1^PANmgE11q_u%NTlw;fKRn`FdMql^=@3|PxP@DPEv>~ab-HQ17N5KnGS zB_f2M%N&(b*n6uB$K@{Id;&xu#npSaE6~st7?tAbsouE~?fxn10Shw(u7r|&2}P^T zsHSjEt`cG9 zS+Yn(AMnh4b0gY5gSrc#Fc42v!>UA(U?04Lw;-I>b2Woh3xeJW&=Ol!HQ?ii8uL?N zVPO8-eZag4F()UZRA-0|0_^R+AFh?xtJUC#V0toAa*glZd8DXr7OFGL7qiXn;9DHB zL}mh`Pm3|SjF))ChMZJ`&+5M0Y#z^>9Ody@SjR`rvNDjuJjIh55pXT<>LfJGj1*Hr z+hr?fv2f$Hz&)IVi8@r^0#=|96(cvse0Hi;51%-!-S~8md9}161fLj3Q;ar$BP8vmV}z6q5ilCP!lv%-8_tV zaD)2B4VYahm^ga?z)&9wN56Y1nBrz>6dWeS{abPBIZktOBNjTA6&p_0@=$@AVtKIy z7rk0`n*Ps2SI;=9YQ`c(LabjH|CK`=( z7u!>il|QC5J>-Ukx8NG2aQEKg!kKM(lK5wd3gAlI!_%;IkO4#jPjHoqbrjx~m1Oao2t9k1GHByJ@VUX4UDk;niNTDV11>k6q8L&eyK_7Vh4n^;Tq zk#T6v>`7>v(#>opxRzt0gSZKkIm;a^m9a1%VEMHVkq~e)EIr8&Gux;o!-S$=gTcb{ zfJ@{~O!5ND-fFu3vWZ{HG?wH2!15koF9Q;gc}iq7lEWp7n;$@%%aFhsT8z}H)f7@A zfLqT0;5`pQ!Z8e4>iDx%-8dBq;gOk(?;f1D8*8@j^98~Tx~dj&I)VRG%}_yb0MS^g z(b!uCH2wg3&Jee0M0RjVBJd=$=((_+c%k0Z855aNyu^a3PcmZ|8SC)MRP|7y@XCwG zmUp#mV+yrHGphMF**t&AjZvOw=M0NS&mrt{n_T9G>_V$^~P3XV}7bm8X#d#u9pAOkK7oKKGDdEqH?eMgQ5c&Qe%i$)n4(vmvL zTNdSQdLGZ_!R;AkZTi`eGq-sVqD2wQmg6NEeItwVRg`mUisv#_S}2tM9c>kUOQU>; z4=4vv6^*YYTvOE~mk?}%FxPa*{@Kn@IkP~Ni-9m$p%1c3mzf1@%lSv;-O5=^MIp#m zt#oN+ENz1>&B4+->e7NEVY}JU?T=nA#YF(w>Wi?|j@{9zZPD(ix2kjr{udKsrH1(W z0zlk`lA?W4gtIr)h}{gTTVp9_{NNv}U!L_UI}Kwg$DUYOkcIzX`Y|+|KJMh3>tR6$ z*UEtya->T1K$s=nO8`TTN72h}zZ)&AQ#7!$-FC(xcMy#mOy3-Z^?(Jd0{P^?6n)Ny zK51o%m@4*ZE7sXXkd!<%=Q>Cabp13`0@=`h4VeYkE37l3a62SJZ31avl8)usE_75E zec+PV!K!C7)_vYUmk<6#S)TS`HV;)*^Eta~)$Ge5;Qs{yYx+vF<3yKg>|o1M`)7*1 zSKyS9YR#o;I8z>E$|hVlQv3k zf>bQ~;4S11#A~lS1jhu}ZWb%SnxjDQL^F{EILS~pcmjrqA{1c18$r&9lID*TFA~=l4$Lq{Rg6b?T?GbR8;L zhituJt2676jXI#t&d^b5PFkM5RV!2>k_<(p3NyJ>R**+M*-zCB7DCJ=kV`d?z4rph z9{?^u;&&?U7z7{{@J6XW<9w&RoHa==XN||QbHhUOiWHo>5Rx(HNYUjZLkIz7tZU$^ z-N^j|a0FT~03X=BVbqxjnJ5DLj|>@U1tF>)@NEhy=l|I7|B3d1^7J=F27)i*a2MU# zi>xJxGL2=SuSzr)e9ak2b0nTrB1$vX4Nbu8UsJ@38pN|Bn$@G`TQ;Dq3S=GZ8*wXpX;aHi&v2Lp0-?cP7w9GPeiqii&i7C<=#M{acm zi!xQ`efY=^ZSY}eFzEt#4{kO5`$c06L%4*a;4MxFGh%|_?}_(TOBhQ!;6Yl$C^K-2 z3WR_-^b(^!B9aca7tB9}>u?;IQ`JD|V^+Fw)bxV$nB4Sc7Y6$puHMIh-F_S@%=P0U z{}K2Xg)nAG1NOm@dl6az>YKwP9u1qJuER*0_|o?Z%g~w3$CK6lwPDGEV@~CGJS0b_ zp^9>J@+XB;i$c&U*Uq8VnGIG{7v6Zdw&q%Bk~HuDqI`K@V0W zs+UtZI1JVgU#>a04PdB?23Z_TLRh03)hrJjd-Fo*9wYlXEJb>k4bP zXd(4x18Kvb2BS@)0AQ_~=xw-%=*=X0%WpVb8+nd;@%cPKp&wD0s!>>hbn11W1~UWY zN2W5}Je|&9x_foH+nH`5(#5I3NC6XHiNxWXkP1EC*APi)`^%X48UeZp6pL_;TlLaF z!$=YyuYtB=g+V|BV;XCqx>N!OI=wldwmfhczb64Wdtfk>Q& zJxCm5*_SBPil2nJ=`~0Q+?)isNCSMF07FDP6G@$+HN^66K#dQy)LYHeIU6zOQk`=m zbCNz`5AvWhzdAAy`P@0rOaS>jE%j!%cgN_!uovQ!PlCH+_3nFQusR?3=l|z??sJkk zcK>>OQH^zB|Cx)z*66~H%tB!;P?*?lJY6XAF-noi_iDBGWjZL$zeMf4Oe#2mIUm(I z-(k+r0ns$mu#Tgq;M^V)J0>|98(}1{H^NUR+yjz<^0$cQ>*4{cxi<9 zl!iBj@D>4{MKG%D$PmD>Dx{jWM|A?S>TGwgW}t%Ybk`?;U^RcI+J?rVcZIbg8CcA( zR$7P-und&$ioHUQBhCDK2hJUe^MLe7fe>HE%HWi%`e+0VU@OrozN)YJd)S)4lh*v{ z(G|cJqjg*PqR?-V2Dt;za6h*59dNv( zrjP1-sWi<8VDxa2CS}*VLCOIju`@(8`tO7?e4|@0liM$^(dNN>djHo^TQ`uP7Q%#-k0;nG4$t#{{?(^=ajbt z`HV7dz{SHVc?ja6{;uiM+*H)%1EjLcQNi#wc5T7bzB5tT;UEJ0XyIaODodT43k`Qt zIzS)&!07pU*7Ui&q|ETk@8A29^G!MoYRi!=1O6p;Rj7cpFxlLuyx zr_sk*Wbc*gom@dBnW*g3sJw)fYBNv-Ds?6ySM>)bcOj9@5|HYN>Sfa&Mo*Re=8I77 z>eHJ~)dm_;r*j$UG@szc@OR-U3GmeEuQBj}0AZyu=t&F)0fV?;W06m#e;tkS^2eSw zF0&EVd0fFk*l&aFTbHL`aTlE`iX@k>5q#$^PdSyJa~V#R5-A1(IH%57ASVWxjbM75 z0wx#}WjDan5029-43IG$7>; zEY$0GpQ)RWfu^7H2&s>AsA;(WBytn8JfZU)LGbw-gpXI`=Qa%bo|q=zMS*IgW# zU7GEq-UA7pp&)Xp6QdZEYpDQ8PsMxE_y@eyzHI3FrtrYhwcSeq z5glD|on?5--y#+-JJozr)JVaLRt?s`> z>a!7T7#^Y58Rp%I`aHsF+e^oh4}b+a4orJ!3-8OD(0tPY$;mj1nBazg|If9xHRJW3 z`smB=zQ)U;NLLnpRq-ue^~0--=&NzR;#GINN{ha_?*Lx4Fv34Io`GFcQov|A4A$ck zB|uk&ED7EL;vi~=+SXUyZ3LYP!8 zJUPo3AhYU-mJsNi=kf6aE=;YvCwd(MU zSi^a$vX9WAKl6X1^S{pgq>p6{Utd6Lm?nuB#H7cggf$wlEOVWcg<0P5mYoTE{pYT< z*TuZ}ml~(b*aNl=|Dwwn$}(<78Mb-hK#xqwPC}M-NbSj}_NUTRmM|JIGnU4%8nTs^ zo_3VQo_an7NgA4X%@bKd{5gP;BDPj({BFchF2tb;=%!VEZ-v$j11uj{&Jn^l@?Z5HDB z&xn~eh76GA*8KA&&a1bNFg9!Q&6DVjyjkkNMOy!W_Q6rzpncZhPSspY%2x!hXdP|< z!mC`gM5H-+1M3~sF6ddaT!AIsg~$GxrfvRTP@XsxxPxWg7xN*wQc`f(?@|kq42}tE z>8&Y9#u}{q3PowvMP@=cT@ac8=&XY#I$2h>1Gdxd3)XDwC*s73U;WT&oK1{*~ zm&^RfiGz^U?UH4O>bBu1Z2DuaoX4d6nQpzG+#OufU0WTW5VeN^hwJ)11R-le9d?bm zQa-8I0FB%3=H<9*H@R{(tm$DCraqoT+<`C8kVWt%oPQlY3g-AowVRADzRhEta$K?s zWC>lbg6<0!v68{mQPhL?lirwRF2OsfiW~9HS9>a40@{XPBRk5`&Iq8oi-$-H%A954 z1CiEl6tAOkA_zHT@0P3=FK+}Q=8X>JA-QTjRNCH+1*AS`|NHf9@NrJ;!u-xRzcc^H zH*3_pb9MW*hSU_Ai#S%mLb4Sr0V{t@jO92^8fy%$o6VNoFD>{jFh|lnd=y8_o#Ybp zp-jnxFeIpnEY4)AnHLI4zJ+!S&(XZ(qe`6zQdv7LX$V^wxXll^nr%Mh(xpp$2HJLH zrdjGZrmJl)m#9}Y28fR0+i5CVxCVZZE#VnW;i_e90hKsQ~%4Yr(iz@+NGFOd4xB1PEL^?QbD z>qX`VmOtPJGJ1cvf!_#Ux7HSZYEae3;U^QC4zSiDykzYS^CW}v0lmZcxj3*1khhiUU| zDifvR(p8YyuG-_uz-4(@g{d36O!gnw^$?T(kK^sQO$V;aEndD0N&@RG!pt0Y2gsM^ zQS&!75^PDO@{jO?xR(@hi@Q(r{R+*;viPB!edWwpvu~AVm!xhJ%bI41@ZE~Va*4|{ zP0g8k#M=odRF#ZZxRjZ@SEC9Xa$S$K~Nk;H|i;X>fJ z5Ed@X3LAGhE<&^_xfP!(siSSG$d$EE#93}uF{K#-qf{4Ds*92BD@Kb_T}-Jirc@VG z8Y@O_Sxme}0e?>*sged;^iB@vMZNGKE&FKCWME1T%XhGc8Co?}SAR(L}m?GFtm>o=7l<_qx+z+gKx22=y}VIjPAQNSh3SD&1J;|WB!W9 z_jFWMNbe3lLyQXpN!=wwwPdi~!epcHGj+OpgwO*%wyvan3Mm=&Dw<%HPQXe_f)bs8 zYJw12sL?tB`2Y#H#cA0z>tk!xUwbH+-kAA@Bj} z#9mfr1DOf=3j>V+!h0SDJh1YDZ@KW=`EDsNvZ`h!jrio1m2Fv`1+JGfgYLtV&$eeunIC+=m7vwg9_rM z)FU5gRH$C^p}E=(!W5d#x~r|Y!T6I6sNT`{Y%8@!-?LfNv-+N`pdQA3p=qe)`W-2+ z%5eYxOEhUiX1ZZUWVuZU52rNXYYG9Q*^vP)mJK%y3u;j3)x ze&JSh3t6i7sNHBBu{dEl67Fd|fh5LY1A{rZ)pO8s&MoK`5RXVSAu1)Yhm3*`&B~f& zYf{ScG=FtKEb4DYp*aI<*Wc;LvYMVD7b>F8K`QATlE2D{5)r=j?(Uhj=?Sm4f}g>Aecq91 z1Fki_lmtC(_&Gww-hRW+5tLfoRYc-AI-c;G6s}~IjNT|5 zO#ka<>ZcQ=uNh#srXI}`HN~2PGM~x!ll<`eY>qYU9mdiHS~F?B5TD=z29Xqsc`j0( zF2WQ4Ab@b9{%|KQ1Y&)$Awr3Pp3ncOPEi@BlfRMH9q(52qUUoYIW~TDuV% zM0)gK`d)M?&QJ$fn94tpRDoald-Bb!#+~lz-(y##dNh!jC+DlVXJJT?fh>_nQI?v@ z$L@Swf=AzP37$*&$MDrAcqR!~MW~@v0n%ZFu>&QB&qH#M>soebMIa-meD$PB&E)#4 z^YwQEw`8RE*bx+G-J$DCUJqWLP;-g;sxuJ!9w?)<2`B*t9cBmiJrJnxJ6^5c>m-UabLgnMwl z=Vogi0vleFybX`!Wu$nn>LU(i!K)JB6o;rO2nMos`Y-qcC*bC&4Jxu4H3(m?$<~dv zX@lD6(HL~jg_!fcL;cY)rg!4RnF>xGy-li0$v^xTH=wZVxAtH0^~2FZrLsx6?m!VT zw3U?#rayioS!WhdQbRA5rI~vO66oPAR%cs$$E{oTQW=IAcL6n zT$I4kBZ_c_maw1$1FTaH`402Q3|^2kXPT!cq?VBxfL236YdKTDh15tSA8;@tzjI+E zika2v=y>MqE{WFO+mrga9ok8}NPQt%st6gLA1Gzi13P~vTvD$@ss)@FkmG)SFdImS z^0{AKN{wdTK zxhWo>ySHP(!VK((Hdh;Jt<_R=KYYP|6g#U@!Vk2k>_wxFHlQys>#u%E<8}%?W5q=) z&TjSsL=G_`c$V1;Xgr9-C(1EKM=qpliXKHUXDnZO<{%iVoJX@m9dD-BpB@r;h^JM| z6yAKboNhJ2az5)c-im== ze?_jJ2J9f=nZN!5!+Mwz0ZNwazF?!j#eWx68(aMEae8i}rWH zm~@6Vkss4@VqC!2{1?Xsr}KB~cz9hjJStdcXglG3kZs9}DBXaM`u2?cT~#_oc-H#7 z$t-OL;|=Tkjb}7R=-Nq;Y>I*IKyJmIYkY^I5hw zabn4%{-Ik8y=N^18cR4sEeg*l`yIESNK<2h!X0fj?@Y0x_u(-=M*^yO&OhQK1__?- z(IxZj8$Q1R9vNO&qTI72t%ucos4 zwKeNra~G_w$t0>#M%j-Y1nrrEKp(8XccKnK=kWYXy_7CRd#-fNfP;{J_ z>kW`gbO}b4kM3N+&|)))_$)AR7M&4v9MW-{TtP|X%TDlqQRSel)_lxiIx;$amtmOk zE?&_*=F*`Zz9m)D2eCG3)w<0M?SL;A%%{1{XVP%bmB_{TM7!?w?@s~6U!3MY?wl#z zr_H=`IoH?t728^h%qs5qB#uaHtnWJuvB}k(Mxq9CouMS4B+<&N)w)D^d5*I@32et1 zq)fO?<>Q)RrC6Dy+o*)lYO7qia6+8^fQ7VC=EG~dVeg62yU^T%sULVCTVzKJ0z9zt z9+$ePHJWfc2#)q034%jvhFlA}=b$~}oY$i9_^Se3Lx2lc=(ha*8o>MkW%+**hLIlMDA*O*2uGK={;a91s`LUSZl19=YFAlW)L6HC0$BOf zhb1Qx@4l36maQsU2myM5`r$pA0H2Kp0k(oL(h}_P*b;ZB=hE!zkB6C{O+i#*gt2Zh z!3LeR0}}5Zg7w)7bY8XF!mJWiY1StPF$1@Y9bN76Rj9Dbd~z$ExQuo96Ar?b?Zu^61)W|amn9=u-v_{O)1bViC^@~t_qzG$?wMZ?gdVJB=4Bns>L`SIAxB<}#H?V^vz6wmnum{x6eWMi7Q zo4L`qKcl9ZTs+AIWfim2oa|;i&5*|12xQ>Wi_=!6O)GzHc=Ti6!31+-^bAbPzKr@m zhcZAdwXT;?*J(za=3WLbIPCQALbrPs#y^01q4;E-UH0W{gsU3@tKW`tp5krYr=s*9 zDox|@ikikks+tCvWz#0#6xe|<2J^HrNDg*0FgaXW?Cy3Ji|?n4cbnzhHQVP1LrqR7 z^!-+1q+MKKs=~lUm}GI85x&oJmi|zJOrA7YRI2VCp-#SE~)p zDwu(ZF5iBn0;%Mc$PrYUUN{v%#%=CFY|C%pSdMOiu`6-Z#MGJ*D0HHez8Tw-#5*0EYJVMD8CBmtf$IkWM&Aq*O1nhFbU!@2x0-0K z;+N*OGs@OeFlsk~g0SLGbe>)V${J-)u{Nkx2-gCf{nSW&pK4OU{y(P3@WL3hhweE{ zkZ*3{8u?kx;PpdEHH%Z6{ymtx5t%E9XCX3uLQNtLd^P-BWn~Xe5HW(e&6S##(xlBw zih|9yNAi%={t%xOr)+L<2lLXTJ)|joCwqCD6XV9RA?R#m#2%zVVAy-R>uAJPc>+%0 z8*!xJKx|+`eP>+eJi4W10+h%lzLV#9vPw@Tz+={v={wod0}(t@mN^;Lbpvl(sk!0n z0)V9_)j#ZL7}66F5h3I&Sm9#Q=l=i=K;J zrhhr^%{@6Ir-62CFw8E0$OFW@An>Bcfugrovc%f=)IOBF~~f&qtue0{<2d z8nrHw8#<3vB-A9~Zv!uU!;&5V5jPi_l@iWzyBH<2(-Mk;P6U*xq$RPUsmR3kD zEfX)|UOn2(l8GxXbcQhfg!cMK&1}LAyWCI*kt;B`Q54!87_#18^QP*kQ;uND5}h)ODZ52eUR<*a&R>#2?X(+ zW3~dDdAbxp{(;tb3BKk@bJDHiquS3oN*)Q7CTDhR0&}10JbkmvT+)3j=@{tB+g+>@ zS}=uz1;@A+dJKW^3Kjf<#gS>0nh8*8vutBGE-aGhS4+vo1{Hb8s;=xVO4e=uT%{et z@Dc!z2a7kt0jW@Qulj139<#3kBOTpTg1?@0>!6g6)as%7qYtm)_UA19sRSTA90^2c4Pk`{U!sP2XF~sZ&*_PMtb+>J;c)A2+XQm09L)=aJ3np8f^sM@%!(muVz> zuPc8`u;5HHugJFmb6x^=Us^D7aflSP%wgXVD?p`D-g3O+q7S(T18BfleVKT(>Cs2M%FFnm& zCJ{r_t&F%C5fHrpHdf^L`S?+Hp|O8sQsqt(K?CGe1`I(&&M*;apF?f*LuQ>8y)tzo zgX(g&5D_FFb`sBk$5{K_){k^Lw1NwtLf?C5=sTd?I3d3RAsCW(kLIq&45&&Mu&X`^7o^dQ2r#)a_>9Vfr6|WperJtr_ z@;CRfDqb6$w=EiS|7Wu&Irrrm44i< zx7poDOnP8*Y9+3?2c-MmHtC@Pe;b8%4K)BxHB07T)Liy(Qz_joH3b32DkTXnC;f$Z)n)>3;3;M+5 zS=U?=uiiW?ZF{qjcG6gcp;7sh#`)n4+APmOi@LF?HF{J?O&v0+rTuK`OUOSX z;_##zG3?qja%2kykeh?2^j%DQ`VRAPegtr2eUtt7p2=`#jHtXrZ?M(uW+_Q%m2GZcIYYfT6a zStwK=MiSu#xYBFNYWW2b5%;MF(Zpx_HYlLb!Q0z5AkV2XF{ZtpasvFt$*0E3-JpCQ zrW<$QoF)7*@|&T6_jW;cIBoJeFl{73!SOQ|pqPIVRD`Qcu+0ul5A8rn+|*i_ICDyF zxgY6N=f}A7q&2!L5MZZ;UiYFUqSsyefDWbJLpVH``vkv^x)V`oJQKCRFt5;)7fN)B zR}a|9!XqWaB_G1|NYlq;+3M+7(!jpxDvb~Pi=k>u#GQt0>2p%qg%mo2sxH*&21cQ| zQ$2vYY;fB4a`lHe>7+lRWok$3PP!X2fVwr_UT{S_>&ovyUxP4k41R~!weLePD*fya zm`1RB0@yM~YhbTFPJP?~*G*2XlX8xAkaC8woJqQzZY(D@T#k0guJu*_hz*ysfaPGZ z#358-RB(bY#(90?c8DG72^UtW_UAgm9}+>NuY zG~q*JAczGwKJHXAacK`~JVzzz8aq+T+L^k>eNEKZK#R*#Ho9f^$AoK4u}w9_N^8Y4 z@2xs-Gnlvf5HNp}_ti+=E0Na?4l1W`i!?dD#BPH%$(#rk z1yaX7+Y`$M_zEZji=aKan80ivL>ndyd+=)S`ZsqXN9|TuU*hy~ObOv&CoS?p!YKbT& z2@MyJ4IB0Wn*WE&I+yXtW-^0jfKzA2NM}t%-D@Ay?JyLxo3xK~78V&8A6i8f8#;>H zznSg3&>?F5(wS|E&h`st7IgsNe$&TWPaX}mc-0!6=X-#!y+`M1WS$Mbm*+9$kx|2oapCV}oE*s*=e7Vsb6%ca<0M2+jO4(zPF4$?ha*tEJmiB=B!sSg z)Z+-@axw%10S=7ws&Pb);swrvAf84p*Yw8Bgp08734v1yow=y;3keTm-UfK{S~?|2qEKSA^dmG z=u_8ckwvg~5KpQ=AT@mrnT5HZ&w9$9u7L(;>PeWS#q+M~2GkK!$~RguX#WlCYrpPg z&(xo~%3EX6D&Ec-4su_=sc`BpQjvtHy}6WgJ$>cMLe5W&+((-fj(!@wu$`?A4amZgytzsbcEgU;>)!f+?A1v&Gu+Q%BrQ1Lp8A|eD35;I@ z2diVf(2;65ki`-`!+ggL%>Ku-Jr3XTao&sF{_+)o9msnF{(8!}LKigo!To;yVN;0P z?{w&Za3@e+Y`34}B-u^qY4?Um?Qk)Gp`VYdh|3UJXeqvOKB5OUYcK8q#qCURHBR9u zE2xKj#DJ=&;rl0&(j+O1=WBeH4>h|@Iq4GHyF|fVVH$OIIK%Jyvg5|NN&MXRuRyI)@r^PtN-~xPS>h!Re3g$mN#vKb||}m_nnf zMtMwje})FJ0wC=C-p)8f%th2~cA9zr7#cGAIqkykZcFJ2r_76_lr=$1GL3p+ocIlG zV#K2u8hsDY(XMjX2$4;=Pw+9E+fhaZE6=Mea@Nq5p>|{gH{s+XkUhbaZ>pT2*^9!oZ4UpdXzynl*MuVSKw!6`q)5x zr=pxJPtw>NPp4#Wx1o?wys%-x{?N%;kK+$S#KSFPWdX1L1mPJ%ZDk!`!EXHDfCH8O z72;x!Gue2wu4OgHW8?OdV0%rCw6cE7^iAmsz8SVJn5vTaEl3_RViw zaOi(oF#|_u>sTZIlSteyW63ba`JRNR1@}BY=6jVK0+CiLU%R{#Mp|y5v`G^d!l!qpJBxeY~eTXV4mg zpNKj)sY{^3Vi4E1;tFt^n!4vlP4iV20`slW`Is5eF|im*G>YHTUdB+jGYKixp zhc}{uqy-@dZbgh;l(b_Uxe?E&(_*e2=X%(Z%Thac>YWP5{0PPM| zb!|^7sv1?t9b!v%4j_R%Leg*2ryk_%=EJ32Yw#=RSuap4Ao>CvNo5KB4l5s3EF4Y-r>#3O%F^&;lL|9L!v6%u(`NR9z zC!t{VcAwK?%KsUY&Ia7!mn3R&4R^NCaxDX;(pX0-PSSdSLy4& zB9?vaO~7Q*qC5Nvgqha0=y2SJOPc_!T82{zXDog~cjlVjbs=-Pv9_Xv=U*dYtR)L; zei#vB#%&FKX>C}72EeVe*M{HxuP~&g(ArR?V@6<`UcX&T2m6I;{9%zu2Ty~L_z>z2 zMdN9BSCfw%g2NWr*~`KXru3_h9%5ra8R4Wd!la0UyRWo}!@b8H>Se{&-NThahWh1a z0sL_(06(q)ugANJC*TCkb1g4GJtF7x7VyNizSe3>=Yye^1h5R|F_~8<8_Q(7b+RE$c0ZFj znXC_z>00^M$ks+fuqT2nx%|ay2zCs|<4Pc!S|aEOHZaimb>a3X^v5E!8KGf7j6%?M zov@~T!gWyz8HI%05&^_Ud;yrg`PH&^;ZsIRC8Nu6F;-}SF{(azx1_e18Xa|$SO>>+ zLq|>P{$m6M###-ykcv=(Baub?UZAHz0G>|j#I=WUvpa&-my_^z_HPnAFc!g`nV=4L zEe2!pW>cK5C4Br_E{CrB*L2DP;RGuR?9!>76OmyT!d$+Sab7ocPq;KjlE|Gr7$HW* zYxss;ZN8_YD=;b)d`?3sA*c|I4tP4YUC@Dz3+e z+gd|Q9Mk%f7~x=^Gr>$eBL(SFD3>chi~wM)>v2aR+~laAFb8wV)74mK_QjQp&*7VE ztab5sz{o7kAOEU}2`{&0);4QX@C4ke6k+<&L&*%tI6{M}w>F;)1wTV9VZ!AuM;cPe zFw1H{Ts`7se+Tjr{5qp$LY~uPYtmTPs4hUE!KabLSXUQ(48K|`ipY^(EHAXxYNkj( zp0k|U8*ahe;Yl;rSv0Q^Q0kkyleoS&c#S|1{}K{zRmGE|H|W?)BvyJ0dN+s{?6Wc0 zTnqMXi=pZS!8b#u3nsJ$BZD>|U}P`mQP{k)`(7{97;^!$?LZ9szH$>^HZ+2PW7C$& z(JQ!m(Z`9K1mxR;m*6vY@`^{8L{k&>f&e!d;%;yOg0W$y-M1_mjn2QlEn$JR!^U_c ziSO!mF>QFgz{pFYB6Tg7UWMR(ZNY6BJd8<@7+;kTCusK&hN9){;=)iRKMa0@Z&Zi# zuF&>}r^Ih&e3(erN@9x>zfk&%_*Q{)C=K`|(4VNGE{o1prgKqrkX$pFYog92f#F=& zN_5KvnE;I|`UrhhjgW)PmK zc)uOb{dgARc>y!;(+Gb`jfi<0&n`UQ;yH%L2#$z38&5GFAD-v&+^~N{OcS0Uo`jYW zG1Ykff~OwO=XhH2ocH~Rn9+Ey#WNdEJ)T&Ub32~RfbkWcBY3VxxvNpmmx#Xk?`WesvKr&KU$`hU2*c&qO?P@Z5}N37!>r{)#6i`Tyx( zY$SDu@LODRGCC(Ysl7e)t^|=7A^H_s#~>Su0C>+;kj>T_w(u9b;^+u0jvgs@;MX1Z zfeWpM1y8Q3Xc6(@cG{sH!kmaqE*ju2`5qH~v_QA-hp<4GMKO*d+)nlF=M>?%$pH~A zM}s<>pjtJkBQ$As5tN8m+D7k^f;LJnB!zJl{Pg|ZYJ`29=L}q5 zPx-kc?3qIK*&VzGjM^XjLF7Z|J$Hbnn20{FwTxXKsw>NhVWNZme66vwAY0!c9hG_w zN+$_!g9mNM*1ALr_dr`sQ|Q3SNQi~*7$yvK&A^YkGl+1Jtv`nZrJP8H6ax@dd#!-& z`YSDAO(wfV`d>?8G9d;M4#IC5$|4`Z+~he8rrsKv2IktGOh0j@I^=H%A$k{R^ujZ0 zB`HTWeh2u|kT7@y$l7j0-39&)>4e@!F6dFNuTSluqN$CLy8i8O==s)3)Xc|tC{mE} zl;N`IZECQrNvI>lqN1sFGQh($8a!`PRP-rvx$i~dw1D)R+`)})DQvu<(To5;-Ub|{ zO72M9;4Vb?LrQ9qum}E!d(awJ5E1!JG`I~A-`k?Y0!?&^C!$iEn)`m-l5Xezy{tD% zw2!(;^2%&Ac`KKQk%05mFW;aqpG9ASkeXq<3sPH88{T;Kv4Qn(aJC3lK&Vk2Xrg-1 zJ6LUDt{0K3r4d6d48A)SEnX-)g*ozWF}?0MweNv1bExu-!r3)8rzT<(ekhBe1`k|4 zMOyQFH!B?Z+&<0PdNNuP5@nyP&dynjU`0`9}2fLCKZb<@ESG0q=H#GJ(M z?!zNu=HmS!Jdge~B4$3GAwQ3ZX~u6ces>=l5p&TI$X|G>@T|cz4dD;q`3s)+@qB|P z32@HElZR&l9xvaK_H#T(@tgzrw*%%DJge|Lj`%fr9t93DvHd&r*Z<<|-~aX#j|2$` zOqG}voi@26MJI-IGx|GH_;OnJ{{4HT_V3v%tv5gMkAjna>)#&&l>K_v*;<R`r7aN6^n{jC`A74^M-w^fTL#X6U_ZmGCC)uQH{ke?4N5h(~Gd>|1&tt^XlF_nNi)9j#$%slFVXGFW zNd#}~QnyJ&lgj8o6=L`r>rs+mAQOzyIc*i<1rjlc5kqu@sgdX*5f?I|w+-^g^z2nPQ}t{Q?zu;*cbWI}bi z9haIPaCSh<11wBpVi@ClZ%(vWs8>r58wed5aFFFo)Fn84lQKhxHk5>xRB*1w(hctuB3wpzjz`1SZLo%-Dl$z_k4>%53mNxg4J)KufDh__rqB`U~mTG>=S9T)^Ij(1H+-))bq#D zW8jO_bvmcOSh~LDpW*t!e(Sc3bbH6T4-*b-#u;krXSnV2scijO#|o|DES|6KTVy$* zd2UjUGfrSwL^P=)A-ih2#U!9sJdufc4E>m;_Eet?l`n9{k}|EuHK?{Vv#+s)`y$RG zTO3A3Io@h}vNhx+X^UD5$W$)%1FhDMj6}Snp0Xo&1gSPZ67jaGup@pTsDI&4c)Dv+ zx7ty=8Fipt)L1);8cSdp2Mp&8gME3&*@N2^d#;^s89_uB+f^bw_aQUcjW-(=>fjlI zWkt9$zbI;B(18KHy%6k7cqg|!1Ma8O!oGvbw-M)SGP(^r}5}!YjeaHPx_~Q*9prG@8|bu6*2&q zrYLwx+ot%y@MiYeYV}&NA%p=NOaS3Ytr!=HqSqd+2lEh~0{V;QEi6FBf7F21&X`_2 zs)-H*Iz2yNzONo7{_qJCIS*Q)QxsZzaQ6#0^<7roIY<psTrz;igqY!e0oOV0|8P=j}aa415XCV3#~G>nTM0mzda)O z!|8dE)hfH{dK+vgd2J{s$29VfVV$N8mdR2|Ae3NOO%J6`oz^|Z_b&HEV>~58_vM_4 zw4YPcd9`nY4!r_Qdu3;oQk=wHM(<_e?-KoeK6UV(Jx3V_L*^zm=Q9}2`nY8h@^QnY z!6$%F0&OMB@C$RjhQ-y0VzDA}j!Ju@m)_%toh<5z`&LlLP&HFqdwi`S?^V8cnWKXj zhH4!s`@jAVx-T7-CboaD4geg<2|(74sO(hq?X>o&a!HR$^CUQ$pyhP#z=XdvJ}50l zpXc$=?sT3U^3*2FHwe{`8Z(C0<;0?y>M^BwdYQgC(|J#N87s;9NUw6P3iCHdRHxb7 zl@}kD4jT%~&7bJq7EotfU*z-#R1o|=Pic-czUMl-t)*$y&IIWIXSf5t(BE0Gz4GE_ zrXA{EpGYtCV=w%)uYE801){BUM{{9=%RaaSPASJ?cnLCy(G_hGYwyRkozI{9vtW*a zAilLR&!lF;OckRt%T+Tr1!OV+mvdp{`A5V0a&$JeghN@S!DjghS%zNbT0b7?Ajuqn zO)F$$V*WGTP%{gfw72P>k{u;*13Op;Y26AWYtAZdA+$e{_O&O;eTM`;&VUsC=!kpnZ#r&1?mwnk|ISc#H8OyRJ;Pew0Sm5` zaLi4`wAZKOCQ>{Sawy<6edumY`A0_1>)>5t@8h&DqG9Aba-2vrMHesV=w`AJ65bj` zkGEx{>8({70;-pOvimexWE~XaW!-oy5eb$Mrb?rNE)#~nA4(lO6->is5C4l4{Xn;0 zu#+c;L$8StF7`K7&$#xS<6Qj>&aqQn_E8(>_@BM)X*Qa3aGw;-iCq&MbQXz$108K! z1*F2Hj8?c!IzbL*!{-O-7yJ@!8dcwQKkCs3(-N3(7bX|czck>3d0HpwjXYab{9SYx zn+u`47}Xt|3;I92t0lPo3jNjY-jL}SbvXD_2m*oFLYq%GVkCx>)a{cn7Qlb73{@)q zqhlnsrJI3pk+oB9l%hptF;i?;XF=W1=ob-9xv3aKYrDza)2o1hI_)S``=V3KRNs6e z=$%XSuF>c{hotHUpsgLR1{a=MimWQPtJ>WxWIx$lhxF%}>&nE#0K(Mo-YMya4dO%U1&;KXBw z3nPuDwZ%w$7^a)9^|umpkia^r+IDrIm{ml(=@C`J5k({YaA$&mr9Z`eLBz%}c);$> z0_#h=8#NK{mCiIOo(HxNVU3DE;f4Jzebd%es$l}ll|Fj%A#Gt4hooZmwO#doTn8OQ zouj%d4@Q~nuD#M-?fs??4)3y^qj%ZPL|67q>IsND)%hn6AfKl*SPXmpmA^q;wR`)E zQS9wA(JCtAaHO}-QAa8IT+jG~N4c@ZcPRwpl{ z7o5N4(KOrFMePqZxeWb*hcn2t@n?F36&x$#G1=Yl2UGT;H2ViYq4r*l&Tyhr1vJS6 zcqJ=aK*kHOA;)cV3xOKp2E+(I;Ao$zCgXl8;Rp04AM=48@F^rq@PQHlWj9V2n`~M% z?ofSq=`>tdkW5NsR{Mfq7_`%kijVM$+Y1D})Ti@-UhpTju^V9EuMq*Rn#Ix!2h~oA z0Sh_enahdxZYk9bX(>`FD2T?Na1#nUkYsH%}V*LVs)jhSgXfbX0ZX zPjb~2xI$@TTuUPQLcA7@wSD`lFW&hH*Hysi{&K9ZlkXO`K?C2urqy+B8mi`Z_XAGU zKDJ3nxZ0J%VZv3CAirO$wei#>@~!0sThNLOqI@oiIC>`36r+x6-hQb*widarkt;(< z@{qPL-{Dq)JseChu*%8-s zbcJNyl5FD0!BI%6G~%CW2F7$KsG8R|mPUlgRv5RhvF3yxbv<>bm_eF-MWL9dE^Wlk*KC<+-iuJsg*TJg7f5LbS`rA}w?k zuuMneb?Ot-p;QZ}Q^;XrwW^n&3x+hA3{HfBSuy7`%xt znT1(HSPe%!58&MQ0N-13^a53aY`xvn!?k`s$^ahooftrcEGj__>F_~_r|(>xY{e1{ z9qH|cYH|GHhw4U5zQw|w!%Jq42guuyAKB4irA?`_se)clgS@Z-mX#nw_1V+htDw+g zR8V>0)}BU9tJq=UzUnh&I@m*At8>9ix5xaNZy&E>F9!C>hN~q7>U5Y z_A}H4%;1d?sLQWA?3p1ETLGx62pW5~;lxLVeKNR7?JXtH1>HGZveYYILuVU40mCxx zGugjXq+#G>vnfEnxFJKYIBfg>@9g?Pc8KJ~9FZh*Pi7RGm-$BBJ(e(~UI5#uKA9@@ zYQyOk2?*oV>r|Y+9UX;JIxq>F_lx|a*E?DXV6P{?`Bo6*?duqeWNlNQIvHX|9F&eg z3*!>@*Wi~8RIm~!Icoo+Tk$r$t958yPH1%6uO~E|r*6V&o52{WksHQ~9lT$dvs2{};Ab2lX!OlDNuOM*`f3QNgs@ga*gG5$GBkup zcInvAR)F}UfS4fk@wC3{XPEl9NouwOS!-)Gn1=}FGk_P#!Nx+s)BsG&gf{y4gWyu2 zsx=TlfxM%E6cNbs-vcrmKr}^N`_(BFl{qS^_drqqc5w|Z%b}$E(-u$qd}EUudhsBH z)ihr66@3ukA=E!|5TFttTEv|1d$$TJj~Ez$V&s8@aqjsUp3GE*txzpv;|RexnfX2m zI2{SK-esryOHUdMAPWZJdBV-Wr}TMxgrwRF%qUaUtSPkF)hvUHGRWssHW4sS&b3Py zd|=lyxn1F;u1%1LLrlm3WU)(-AXi?k?|{HSwszCKt|#XzTd$ z;|U2^^)eb)&A`!1d+_#oolpL$hXeewZ3~40#h*b-p9!AvuX~}OFTi@CmMU==&rC)% z!b|54;N5~Rs{xFoY7TKO9e3Yr5;vBkFxV0C?Ml@8x>CD5OqTF5y_E-9(lNIg%T5Q! z!%jxmb4swkvupox>iD6>Yx@`0cV=h^w!ZU1E+C;3f~!k^G0+L6evdVvX?0fr`>zyx z&94=XfCqh|dKbYBF;rm-M{3(oaq>8r_Vgz6_gi0S@(Pg6`6uJ?nx_B$Vh9L-Xy&HE zX55|(D|}lkWmH_j*&5ebSGe$^CZe37`}`ovZWKf-J7bRE^t;2Ao#^Qf`(3I-#ry!K z1=+p52lK6F95eg5Um+ySkU1O%fD4Spn^C3plaN(COJQ7lHg~Aw_-Kg17IjRJ0&aMd zhz#^nL=^?*WyA^*TRR&HVt7!9W_<{OzGOW=L#a;{cZVFN!0xj`sa!V?zZUePO@i&L zZF&5YMVWD{&I6Ar#!}8vu0TNt6Z`*h@0$Uafh!~L>15U%ge3v~8K$rKpt|SFlo+ch z2HO+`)=t2KL=W7Y^q-a~Y&n$L13)q9RqEZuZt9KiSKf^^i8wwR;V_Ki8!#?fw~m>LXb{*kYr4t%djf~ zJ*Jtt$L{G^nEQ$0tJm@A#=`l0V@-DYzU=27_XOY@97;1fTvksv5PNJ<~b~~=r*LuEZ82(=9>5soRc+M!CimS@IjJ6WGX7`ElyG|PG5|Z#% z>UVW$>5RyR{Lv@RM`M^)PjItP>K)@a>bl`J1dc+!`PR#L^j;7g0NW)s8mj^A>MuA5 z-zE<-+avaTCt)zVp35kdCv>gh?z1 zuejrq-uyDDQO*}4vloRnq4yBz-t(Z<_naNIe+Nsz_#1&}RYh+Bg|n5pU(5=^cgU8q zi5PLHM4~Pwct0$$_5S!{2)FmgpZr`1N%qG>jlR}|du{^zTBP2^VF{SY9qi@AAqlZ9 z9D|M4)Wer>eR(;D@(^4)Wm;n#2>n7rhcmPR2uzWo}ogtJwlz_n3NJ>IwRvH$sU61)kRLXvHTyDum4l<(Mf-(i0H z=4bYRp}*1#QEb3$b=CX%$Es&O%7Hkr!BIZ&E1TU~-0$t;gR4smwQbk?uAPAkf zAYqXDWV4ux2*wTAe?(IMB&-6WHnwei!{rZ)F8{TQqsw3aZMggpEKne?tw5Qzuj=wE zkW?j|TKd{3Ho<0Lg{a5_*aE(bW&?eNcjtN`OS!~ebVlKmcJPFZ&%MxfKa%e4KWnM{#*IOqRW46XuJB8_;vm3 zr2bBp|FB(uBvnbLmOr6g`7+G^P5QSh(VMQsmOLa20YzfXs zcD);D8`#SFDxAMMoPTe?{8GD7#m90jqS9EBxlUihOZybz$ALm&) zUZQWi!2WY4@~KN~$i92wnmO5WL7#(W#BG}p_#J#VLnWqg4CmF*yhxr7I*;$(Y#{$B zTp+=f?dR_ZfjoW@x=sYOK-Z~wSKq!XT?bbp-oO>>)TQW2-EpoPvH4uN4_E&ES!cb0 zS;tbw3v|t7)>m}az?eb${>&4gj;Orgw4&+Z>c5z>&LniDQE>neV5eVl&>AX%{j6?m*EX^+zcn_%jlyZb^`kMb+aSrebyWT4w))&c2A* zJKEXD4iW=Eb*%=l21%^W@QlliV_z`VsGv3mFP>ZZ=Nu@?jLP0fD+xhx8w0pa5s{pZ`0JIhv+?{4ry-uE>-Vf>`-w?!kSW+vLR#vn=pj<S51U1RDu11r9%M?R<&?@FFfPXq=JtVn0owDh!uv+bOEKAtIr;Ud-6m2}- z1x%1Qcfa4{YZ5HGjYTix6{p$7t)&+1ZZMa-tR;)SKg)^ZB0EA~^0Ieed-eqpk#5R9 z_WC%AbX_D=M7lzRQl!I~w;MmuA{|~I9;Zb*yk=h?CDMI3NSLkaj$FYzAPYB)yqrA- zo}znRwzauw3$o&7pA+^6ur+IGuD%|a`J6TU4UiN*%q{- zTdC|I_rzjS7Uh`F6jTSCJnZ{{#$Vm$4BZT@%BTT~H6|ts^;r~@y$|eoh~|W)W^qRe=7=Sxzi5T4h9bSV>dS|c zF;E0Dfm0nK>~vX2j1*MCWu0_cpBpI!W!yEw6>tUBY7MRha0Mp7_@*dJ4TF@fFK>k} zmO$!glv)KJEr?kH*ZrWCOA7@b9rkUUMPCu;~}g_&R->K70<;GZS|YV6fwCs&z{bn40);Q?FE z2M@TNZ5-(O3EtJU>$My~Yi*I1SJpxq^5JDDh^Mn@h6gRgYBr|TfV$Q|1A%999o`%9 z?7^e(wBkv|lV*>DrqE+G%xfXFH5r+`tF>4GQ?LmbKSc*o`M!s+O1qS!*D9(}XD%a` zD{4kWE>LsTjA2L5;XPx4qE=;GMT5ef>gZA?(>w6pC0!5&sbZwl7uO*Fi2+pU?@+l2 zBrOMoG=^?dwI6^M%ikjjg%|NtZoGc-rXuSk*3)h{QlDh_c23;yjg2-jdxE}6b8BwXfD4c<>xu$EXV9{WEc{nVJ-0;vRn(uvdiLz6z0_;NU!)y9Es&2z&8&ZctI1OR< zw_v>GV=L1%Dix0gGwchz6k)%5nycn*6pq#oWNII)!{Mi!fl@*;%JRU(LdHhu2mQA6@Njinr=fQ~xK-aix=vxvc^+!pd(pohH_x^>i zX&y_=tUw)l&GegTc%?QHujy|891P$&5Q^|K31^Hje2o;RX*i0?a5!m_;V7ua_jI); zoBg~cxEr9N7?{Yb(MsSIKtuK1srgyp34X%cf$TNzryVYo@aW_1A#nl1g*$e0abqN3 z0;y+Cq`0tCy+~6xOkTJE4oa-lBm`5li%v*apF$5WZ-yhr7=WhaxhP`*2;nEg;Y|NY zIFQPCpQ*0l)V!Su!ItJo!jvT$EG(Q>I}8bRk62#X7M||FlNl?J4i_c^;~8nV`YrvG ztKXy*SbvATiIKiTYE6$XFoJs@r^;Lqh^ZEV7>!ARJBen_UCBIfA(C>an!SiY!z)gr zr0`+{aUKt(o^b%fKl=#|f2bY$StRr^oRcp*Yo1fUlMs*fm z1z%3$X%qFutTVRjuCndTT8Pjo&L}7{MvfQ2N*%M$hDIz%V!Y|FG4s)|%+|8YR_dD> zWs>H-k|~?EVDP4{r(Li$(kTbGX?AGs#1O!JHLo5G`C7YroxTmNIC>l7y_9`_-2HRt zoET8`aIpyP&#-S1wx0ISx%Kl;vv0z{$be^>dP2fAon@qFOqSGcfs(}FlhriUeV_db zj&D>@p7L!VvK>5ac%vM&*>CX1Asf~ZCkW{N9&!vAL<*Xmdk=R55WMAtEsa%B3Yh;U zxG2urK>holndPU*}X?v+L_(iel zw^%$p7iKuCtTeomKSDijWy<^S)N)KQMi_(&>??Iv>93PtK1{D!;eMqvQ|#*c$`IzN zNd-FaPXvPt@-Q$A_}>Gs`ChhUhz6J^E@9l0%ng$Fy$;yBK^0%c*_BSV&%jZ?#M)#h zQS_Cw!>paI`sU>P&ULO36pz4@c3Sa7I6#Dd-|AkZ}_17bnm>#*;rL;#vEaK$q9&>OPQY|BZgVvOdt%D9wsg}7o%Bc#(MDPy~%g7 z1Md`jSU25n4>SZ;GsdV|RfWwsJ-jsap&MhIRWkmZRU6o=D*026I4@3Ih+VsGObE-u zkfxZS71hWip|)jcI0`+@`-M$Js}CF7@ufZh+|HDf5{SkCsj=M!i2_tbHsF%mJgX4! zMrwr6n(+MxnhQ#UhRc5*C1+ujNIm|;NCDpAk%EN)@DmLOUrw2iWj6zN$Yu%2Rd>&rA~^-QB8`-fFx+1-qH58_>Ay{ZM}ZxFV=2TPp)+M!Uy`qyc%l4ZTDm&#dOE0v#&amK{leV*F2 zO5m3$PclWAF)49nuZ4kIT?ut+EX(LuhG@+9IAA$3`H1-M!|LO@G}8W6>D;@l`(hX7 ziq4pQM*%JSvhNeyWR1y{XO@Jz07ZQxp*z+67qb|YR}m@C`=mV}MmZqd_^~-N7D^3l zdYS%F;1Bj#2ph4pK9Q=tyZO|rPKaKcR+gMi0eEsm|4y z`PNgs01d(RLCN^qJO4D=2WSI&NFhsi5is;1BS^B#Zo_S&b!Kks-IuBl;hYV7CD#DI z+Hy`yfv(MG0M~tgA@PTekg>@>OVz9tdu`4=WU$vp zjA0@8oN7se@P(l=EK2mq`i6~CjCY+=m7Ip|D*bcc0_Wkmu`GD@};9TD=UAG zn6#~p;ntO%xe*CKYgj34Q|CS}EVK*WHQU_k!N&HC64SpbqZygo_J5J0p@7{5{pqjj zOvz{K6mZU)Vq1={1V6LpqQlsDR6VLohK9!;FM~J9eAe{g0Dc~T;EDo1D5fJVJWM!@ z6l;#Wy3!F^r9-n2x}3loqzo31SC+$ngsA#Aa!l=18?snbllm}=rfkNtF(NQGseiu6 zDq_(q+r!bQ8Vjk)cUym|qXZq;KupZQ=plAtQUW>{I+<}0A-T>COiV}Zcng&~FcEz0 znv6_$U>x}F-=na?hCW=3UPGHih@gS48&B6X8jHd}qqItHQj@VfCweJybq|N7=cGf*RSh&v(G_`k(nkR{eO!YRLp z@Tw04;bqsLS-CK7QpX`>v!TDjLOZxj7VaC^GiLpFiDr3&jY-*pE~%ar)3+d<1KpQp zcb#v;Om?PGF$h0M(^DUrgEKJF4i)FB(?#e|U+c|=?+4b~w;(gdsHEF7I809E&lqR-hHo?<0W(t^LV%8&|{bYI#-1|jm;35!jvY8BQ?}r1A;5qnXjhT0(9yc1TPe66nj_%^T>>%zrglKqq4{vWUjGjg%57U}3O+5%m zXtL#uOf@RWQ{2|LOcTe$<=+B#98}KM=yce87>n-uGyA`mrl~Ms>l6~g@@*h_ zB^VW30htm9FPsXuDUU=pqd|g0kp4(LfZmO|T;2m}HgJZ^(QX^qu^{YcpVJ)U75Vm& zAdPj&r8yvs%A3eVK+Ii?g%gFLparSDQSPpwV_Z9c`%a!fDTLGeT;W7jcZlPRCe^VQ z2h0LAd6O!#%eV@0ZN1&guF~ZQJ>sL0d%RJ(P_jpJ1+33Nh?Tb@LbGL5Bu4$QKdy^0 zr0hlr8EWgZKZa^W2aocGulq41ZqJZGl{_sKtaua66VVQ|03$@oG+L857{`EM+=Msii{3Rl~io;PF=E z`xS$uoTXV6(%=3ya}cLDzg15SX&NE1=77|nkj@08{Jp(*8 zQ+CxHVRc6`@jRV)I}^)oWw`gAi7S{`*Ks=&;dL8S*1^nfCbxYnx*wezWA#Pq5Ji*(c zAn=jzQQS%-f2@K6^UVwjF2d<>fcI>2>7H%9`5YX9vNs!$9bLCspiIm(a}N?&D}foK z51Mfk9Z>D6PLQC%TggmuJ)+EO-aY_EXUeee7tT~{L-g7RIgnT@9{m>uZ$V&N;pf;% zuRy5XD!{>ouV`h`zm?}FK$QgR$Y?>n5T2==Sf*aC20Sf2^3Z8$wOe$LT!MFX5n2<% zV%P*-pYrPRlr1&}e?rad1wwasdAQhPCo(tT zM+WXz)uZ7mcoDB>#>ZzuLg2L`lj+?89loBOUc*Vn$cK6E15SL~xpEsl`Oq;rfy_-n z##M6@QmJPI)iEYQ-4Z&Lp?-wAYHr4B(21GEv;>gptMAhCx@j#WR34o1V^`l=OdO1L zRUF-=ei%2}A#1C$5mJRagh!?U5Hd(g*swEuzJGS6=^v9W+boC@Rk(j-7G9|i2k2}O zLYUK7H_{PTH*jQTeQPpwZ08zlM>;yxoj)=YALpsRW{C6#Pb7lrGNL2Wq(2?ys5{O% z8IlnkT#Q*iOb=LJN9jM`6k@y?SJj)KguJ8 zVN`z1bnUk|#H0fU#Pa=fOR#O|!pXOsKTGOGJV+(5Mk5blW9)cxc?uJQvbBq`Xb}<| zGVT=MrN*6Ir*-4?bssezG8R|_(L$$X8sXK&%pa{y?W$HT$Ntt-2v?E@wj8Ea!}`F~ z`|ghBz+<>bwaYy@?J{*%vylnY%TnzX$A&K13In6MK&N6XIsoQeIPfHHi4b57_avFt z26@L=?|yxlzru>9NyYQCm9;b~A0^?SOk?3+$=)qXP!Eg-S-dXj!}F-r!Y5Or9gmx0 z%(#c8dCKcKx{S54Rk-ri)u}2k7C#+vUJ^gaRe5pvNvX<<$B&~bF9AQNSLI<=b@i^w zOTtfDRbDcF&aTSqh@Z2n@;c!sy($kI(o&+^+UYdb;*?7h44AO?$Cj--PIn9z3F#^m z!W{(S2{=-SWtCvsq(=6YyM?gRj9C)fJpDl z7g)ap2jG`m(lZOuzLm@HrCaPnv=}yi*iHpG&u&AwQAsnN2*Sn5ZrwJ8)^4sJD>*p1 z4}qkfxmXsJv&CFhyt1o2PhRt4`R>y167JORaSSii@9}&$^?O2Tf&Zq&f~uR6qkzDH zbp%K!zS}@LOEp@Oani9%p|1}7ph@j|Gf9k^)=6zpOLRREbm!K4M!I9Ag$oBp=+vjW zn0`r67$lL8-LHY=fpT%`pUqX_Z9<{&&H4CZ86@iwJQQQY8j{9t)6Op-s z%mFue;?N%T9^6*IiqHRN(pU{19CDNq+S09IWCA__SjUfmIM_G5qJoGlaKNPN3$rlMx5454}=M7n_pXD7~JQeVVyolO{}uMO{q zq%;3aT^vbB;Ns&kVS4QtBvgksmXZT__WYBy?LIw#P$JWL4KM7%HA%xy3h ze@+Uq%AHuxx@z1m@XOpfw=o(=QCf|~^*U0xpRcBx6lYXEE`fd_*}%juYG4BlF3|!P zsFa6AO5K@YZD#BD ztwu1utIFpPl4dQ&x>1f&e|Z%`g#2Y#7k|ZlL&aTgyB7L1?A^+k6e3)omH+BCnPJuF70xH*vz}FWd5Jh1_jt zTGye`vEg(D8vVE#*JS2ik!&n}44I5|S2%d>5hNXmcaU6+b@f&5jB&V#gza65W8M&; z#$xw6jYVw6^$e7oF!7?}rX&{{1=#eGq{h0@j(lTXxdZ7+UAPx<5s`xat`pTy*WjJU z-zvv2x&R&3v1|mCGqhnOAj(l#T9&fTT&7X)`$kXkcSTtm zqttemg(XC`nR7#i(|eH#H6ZesYTD@{MSA+#Rn`)uG|V724CH{ywLk=>aby|k2@wf; z^6MO;MU3dmP3j~U$>GS7U9(NNa?KbGBVqB%&)L}(dZ-MjqM8qx16j>?Yal#^ zS{6l(-?07v%R*PY^=@zF?)f9sYs+MWH3H+>zMLrnU5DXat*ic>mFGiC!yY}tmJB6* zIGfY{p-E*dqjtaxuGggISS0!;eD+hT96W5>DC#RU<$2ty1LWIpj*;n132sU|Oo5#} z7a0#)ew8uNL*tHPnOk4{oiXtf_EeL}ajDehxY%kezKJAhRsNRvJ}?%KVjNBDsIxZK zVYAa7GvdQRC3?>2WbJp$oih#Qe-wh=Aw}?nU)X-zZH@meb$p&L zdR$9W2h;8A@TcOC5ewCiJvE-LgF_gG(zGA z!nv0-4uQ6W&_?B3Uus9?C}0NsVEi-UkH#%}cUsirih4mKu3Pj7rbZg8>*x_|EWMIq z2uHC|ISQ}tsiTlJHMIKO5FCFjxHvBmAD0hS6MrhU_kMlJrK_6tgLJ&SW z8L!mCp~%>@xTgHv`gxzW%z@#ciz$$hsc<1{g`;}otue_R0wdvvZd95pt_~(H^{sLB z$KpcuxsCVtH>X0V8jYs8DmGNVCBFmCQb&>^U2fyNW}B zy+4Nbpzo` zD`@tE)~9e0EuK&G>1iigTFrkUJW~z(vpp(l$7Pkv9M9n>##(C8!*B@z)|)OC7V4#N zVN*ce1w%sxfoWX|0(bU+Jurs`Ppo7b>#lUf?H+g~h(T~Q)@`i1CgVbm(@c9d8;sd3 z9T3z}oGBILN8rnC%}m~aUw{fwswl{r51Drqb}A+~3yu7LKn}#>VUtp?rJ%{iVuzzr zum#uf2RPi|sB!`f4#raKPb{*=rn{=jvJqaW*Y>3@e>GPKMS4wN>49|es$voo$JsYKITfj-g&~~@F-DMPftS-grYP;H$Bm4qW#)yEm z_T>B56EdyrFdG%CwY-~m-+ZsMu`=zhu6zw$XiGNS7R3~F!SfuP7)O|YF!#*B@9fCv zoD8p1o75luGAT5jJUyoN6+J2R!@GL!fp(LEb}e#$m936!c~Z|exNmg=PuOc)nH&FX z)5l(Hu%oxw&~V4;viKqM?QIW&GSJ^J_=o2y_WX3xNO73ou|~z}Zg#Nf*o+FQoi)pp z^&!O-W8H%yt>6x3S)1p~fcLgi%s)n{?|7`Yqi@6W=!0JH9%+|4O5ly-*A?*a)G&iB6vjc~qHgp>1)m!vz?4;W*?Nn}of=Z@~28Yq9mmy{MV-QezF{9HK` z9bTM|(N(WUVlY}F@y;(1Bu=c1AhA+H1&MDE8bP8O;Y4DWB;BE=1BpWGNFlBYOpuE* z-8pw+{x~3GAks*sIU>?|l5wuTf^&Y>BgobZLIsD zE+U{?S7N3bm&Qddu7<=R)n(_o$OjX=QxS` z(n6jKpksyGRKdG6-~TduHtMq*K8yUrGK8*M9B%(B9AGjF(di)%V_{)TFJ^d~BnukQ z^^M{CfXUCo=Nao(*wlHPj$s}oaT@CuvVc>7?LbDb zMRX0ZrvC{izVIXb!2iS~exZW*z9(nZ?hlN_9!HeuBTTZE8||f`GL~wWVnffb61cQP zH0_f9Z4ocNB}JUh;?Bnc3S!8ko5D*xidPY(p?v6}Du2W0Q{Q|>+M@hkQK9gpkhRx4 z-R9)lXKw^cK^(JZK$qH*nbwKWr-;Z-jtxDFXta?lCbTQa(-vF{i0<(fBUxg!hC}SAz?t z4X!ONoFS^ZvLo_!KBdOMl`Vu`(<8`ME<*BzX5aK%vSUV!bmL>l*l4xu0U0lC_Gw{# zhZ7Z2Wlw3ESo9N3#zn&&P}EDUqQ{bi(iQB=I*>BzjHI*3?_5S zYf9%<1e}IEX6IJ48LfnHz6?I%nz5QG_vab zS!d?Hl~%<(i*H25ZJr(0B;@Y$!j4>)cLsd(uLimU;Vy?nffBt1yb=Tv?o~`wT z)!L~WEga#b<(RQ>FB1?<X~@Le>IshCJ}G&@J7zc|+`ooeHY-P&u+uMp z20LA@+3BNrS83%oJN=pY16Rt1!=d?Lr#NUS2o?G-ZSjYp<$N!jNnarr&4?wd<^*AC zgj`8tgkk}t2>B}=7h7YNADM;=47wD>ZEK@R>Y1=;d#xqO#2&i8;5DfHJT7(X0zvaK zqPan%`L9Dj^Ddw-``7Fn00*WQDmTzu`36P~c!x+AVl5l7X{3$6rnFl{Rl%mBE8iH8B9C-grFB-ljilv$x7-X_U$m04l<2 z4uZLy-L)#GBZQ8z5#prPKUP12oIdoS}u-DnAMQd+~Ixf67k~Ap>2f<0t1SR@2izaP>gddcTlBfZq1P z?)yHPD|QTjMonukK&{k=lBiCu=Yn#xhdLWw2ulaChrn5GNabad(}3ce8Lfca=D1d^ z?-Yj~qmXY@1c@Pz!JL!AupPAL+RtdJmbN2~Ct`bFd04C}0;&C8Oa-7it`%mgn;t%j zwF1|~fz)&R^FShv5*Q^15ertx@xlQ`tADbOAr{oBJD^VHIoCkyFK72em*8ePJ3WsE z^W0)e(Vj?prTz!$_0i8j>Q>1CCkl}g4%#I|4lfosR2Mr(Hp*Cz9K^~Q$%Dhjb}5;W zQnGQMh%SXHqnqtK#gRM%3Y>O1#gRNE>UlfQB;?7m^OQvLq!diI%b63-Q(47cyB*mg zsRmS5BTNGq%}*pP*}b|8DoHdY*7vK~fq|kG^tL@6W7J5gtO@5#2{ht0l5-DpPIJUT z0^zYr?1y)Y)4KyLH>m~p9SZs0CZSRJ|K$OpzWw;|oK<@zGtQrDGasAmz<-L>wfDlk zVxQWpnP9Rch@!expkx;FeAhUcCp5KT@!yQ(oHFJ#u#o0EHpf`} zG1E?kU%k{Ho`S0f+~GZas*`tke|?iv-{H-hf;u79rkWn|7dF9ory#Yd=1lo}zWg01 ze+S854wFqagXQmq@;6KVUL=2q$lsyz_j36=O8$ z?=1N{TmDXvzjNeoru+qW3T-;?CTGm~c(U+Zg6DEPd3g5V`5cdlXDps;@LY$d1WzfR z+wjc7GY8LnJQa8zz*CLqF+AJwJc;KyJS*|Miswx{wRr0AY{9b|56g&25C4k|zod7F zi?`nsB4LS1`kF4>aGDYhJT3f^-n~coHC0}E;%~2TP zPiZNuD13n1YYWx_i62-dc}5Et6{?q=N7iE?qv&(+7Xg@}$DA z-aIqVV?bftM@4}_Bg{bj`7H(lN4Tv6@VAFEbMgOc#{J!l+iChA(Pn%8B^lKOldO_<5USDsWG+I(GLVFu?|w^%1#i=Q%J5wRU3TTRY%x z@d~3~g+WS`w-ul=D$z3%awepVKA--Z!o)w_;tiS^uw8zYmA+914082OEUNrEl;8tDVy zL9`Q8(k@)2;cGs5G|x$;APyVjewL`Xcwh4giR%y@mk-w;Qvkgapm+K&&^!2=fBkpR zlYPxce+%6u%#1d;2T@ZnB3VUgcgd#zt&B2;VwRqR6wP?Y>rAHR;*m#drn}ao@sPw; z-a(Cb8xIcC?J3eanU;M^Lvv_6sT`(qSL95!8aK9A*5M+g25t&HDJJz`bt{lQ!s;Lu zw;KVG^=P^r>Y*Wn13RZ$CtZe|YX4Fh3vQT`YBHkaf{$iIx^a>!aECMJEh)>BWcoID zFysE^s`&@W1^xo|lQ_1kwU1B9Dz6E+-+x#yW@q{I)! z$1=D6a1VtQgJW@Dd?BVcV+P5)ySF1;EH)w^$>2moFO@kT|7p`UnD!H0aX6=AS>UbzFe+h2PFH9TkcK2WzNh$FuQ^5cg()^ zPH!Tz-{HBl&|1s`y|UN+NJbsfyRFUW-#P3S(8(hiH3Hg%APB=E1Y-7uB_Sn15YHrf zxkPf%3vCbZ$H_mSlX>mv1S1u;R4s#5XqJe5SwOTl1w#w6-)#!gcan$GZe8u2Xlaq< zCU~(IzrH(?V4f~S5))g$sM?L_SMI=;0WGV+-h*w^f5W1M`fD1FHY0_4W=U8i9{)gO z(~(34y%>i!3?SZ3$0zPfDa1JzYcJgLa-y!`IuWPF;o)kVrEP#-M~FMHB%=(!`lP2B zcto>3;I-&tx#(E?eu0h&jf$3pUSJMtgknBnlb}JHs3o874ul&N4GEPeo6>D**lb+1 zC#@9m2kl9T9DgwGAYSUza6p4&QXPaZ7>GH&*->RICmeC!3%jsStM8CmBBO|s$d8st zBF#w2Eo-e&4YyZ15LI_F#lU80NY3#`+RK3$v={5ddu6P*GG-z~+KbA%BV}daAXv12 z2e^8hc=-dm&8S>$YqK)MN4MEk!*rXSE$}Nc7|+zKTDaw4Ux3${SqMVokxNaNeFie9 zNiat5Nt#4+(b5xt&|KHBxvpVzVV?mA8JZQRfwecre<5#>Pz)oqg!++j|6QD^f z$mXa^GNj^YxAhN5yRn7rb_=6t2Fl4OA~?DOe)1H-lMb4woFb+~Mq>$_yE3^momlA3 zjlwpO*djWe(aNDQ79THI*-VElh4b(eCf2NA>_)$ImUtJzBBu^vTxksP3q@6L>sKRKMTWJnG%fJcOeZ3!ez)MqFCBW)QT(}rLlQSqk&~F=n0B&M1U-n)3vSFf+0wUKD-~1u~?{+<}XgtJM!>knYyhr z^n92oP^mqhEcL@}(jcYZp+Tk~2^wS;-qm3=6c&3l4Z?)bRTZFtX!GWa81mVLYJcTx z7fERiXau%Q*HM^mIp}ctq4WJfalSg|dbq;zMc;p@bL3mS>3i}6m+wT#GaQIbit%2e zCTgsl#Oh<+P5;2iR8xQz=czR)MbLT`6o!2P!OEQaAoU%-<2?W&RYN$5T(zHS2!AAm zGi(U2h9TS*1t9nqV339R zf^m97t-$YoAU(R3BI^xaFGcpI9;lSI!nQqbH=zrWV1aeiWnlvz4)zA21q&$6)x*H( zT>7kz{A!j>Jwz+orbxp?+oeC z&EKHnopr^Z#k}(F7sJxnF>4%8Dfs6)py~8xnNzpq zXJ4M_IZti*Ux9ijv!-gOV+eHzN~?VvV1m;Ss&{C(6`(KJg6x?P3Z2AaDCwT-F(j*( zzDuvqOBR;R2K~it4Sng$4FURe4Lya>$>l+WKY(YbnS}l~Lhp!BcVJ9Bu4Zv@nX*$= z0C@^m#^vMrIVoQ zYk3ZYhJllbl0j?5j+Rf`2c)#XPtW_|6grN`+w3DwodzhuYe6mTlZ8tGi-}kNg5@4+ zQF$4O3bz`Da7)y6w@O>bk!u#{*7$-v>L#>O?FtltvV{0wNAqwiX1X>ZimJN4#278U zLzv)BHDnn@Qg4@rk=$^M32uc()}>dUuwD9soN}k?+LnmpIQW7j0=FkSU1CF0SRL4q z7!xd$L`gc)opz#4ZHdUlgV!UGS~y+mH4tfPuLKss{-|{I{JWenpW=BB&*ih6F;nrJ zj%OgAC3x)hN}K)cn1y=U4OySUl+$-Sge}Q0FkZ5I{~z|=1-i=W`1>au0+A3;xCFvQ zjSv+D6+DVT5Od@N4iW?fMXOdU*1Huo!8<||H0k59R&8yot@dK8t!-^;1p3C3(*C>^(Dk_RQ?rGy76efW9n{ zK+M-c=!;sHl$MlKz89_k=pb$>p8Yzltj!*NCyrInH0JD_O8mAQT*LC&OI+6`t-izW z%Hwmz5gZVo&vA0K*?Uq}x~g^LHLE9hpU3#*>W~nxYu6+2 z+^1ukpcr>j6FBCM+{%%!N4OgHETFw?NuRphpQ_YsY1uBIL>VazNgk%{Gzw~gN7KH~kjXtBD5%?SW{`f+ML_YIz! zdu6a4<*^+mY?pa#f8GkVQ6V;kS&Yhs!ls5LgAK9eZo-L5P)yV@tA5k<(@zNcRf7Hm z|M<47#Fiz!7LvKRVpVkhB=WZ1A zGc(Yy@z5_9^ly9UJJCdUV+g$=4ShL{Y5p1|+*Rw477w^G`m|)>x!VL(nfG`opUl&m z+-(#@OT#ic>b&_i=+OCJEW}{BNse2BL8)&N^Qa$5ua9W==aj6SUi$aCtg=H>PoF{n-E;O_d;G>>&A#;B@25uG|YHHV4l zM;kwAtv#L-MVmKMODsBw({uJ9Phxlh6a##K87b<3XwP=+n=LA~{bjC%AKF8@p!E!unOdwOe1KwX@-Z*!2g>T5JDA^IIl7 zy;OByrl336*Bn4i#>iCOqpCLCR}0o#oq3Wu&S^>&bfJ`;%jJHIc**<^-t>W475T52 zv^LXn*C~~yo$C1i-s?&`b>VN{xuu=@@La*)Mc0=y`|M08w_CSvS>3Yvw_CUD?CfsY zUAy|f`>=;{c{%T}2-4k6H=9LF&fabJ6X~GFinDPWwH# ziI3pvK#kSz57o91=P!ul%_Ty~So$NZ2 zo1bhfo6peMnmTiMW7!?Z6;};S$g2H|G#N?z4$&TyG*(h1f<5jxQ|*M^XuPpY@nQ-y zlhu-lU`h>fk7=p+b|SlT`vqs*k>F;bV9H%?65G`nlbUV)H)p$B%|*UuQl_`{n49gL zTr;2@Yi9MlyOP14a;9lX@e5i@-PVLoW#fDj{Ir)TtDOhe>Ig(~mh0W!c{&x{rvYWB zQKR5>_duBxX`a$%$F?pKCxZ0~Q&%THAWUtHc|mC?KqT`Wx4~)QYQ@d0#MRY)<0hzf z#g)`(UE-zzYs{vbpG$DYE%`L2Gn9!}ecrROn_G%Hw`9AY@F&>BIcg`klQ*P?;))~V z?AKqsI%9+?1|@0_6XB(@6iABMheE~RN?Wq+L%gn08lEbMy@H&~olpFedkS9q04INy z>joj#Zf<~e-L2i8PvwEu6hx~pp&eDX%x|sCA8p-O36jRraT%+XSow-2kQ}8&QWs?0O4VB7|w4ZvNgV=F{@%= zA}E_5Y~;#l)GhuuI*M6N8-Wf$=TnRxFu8PRU>BH zfpd2jIqYu{AzNxwpH!7S<4+| zzuax}+Rnz6XCe75@vN9P2_%nPlwQvoO#V0#Oy(M>NHBdDO)pX-OWZ%eQ+3nlotP`p zz>;NvXyq@MtCsW$(JoB{Q|8C3K4pnyFr`}OVaAdE`Xcb50*UB^-4d`7aVXEgO#xTp zHcPxNnKFB+`vCuwoPvT&*Ne;7!o5ijmdY@s*ZGGz$}juBDypLpZ0>011zudWJ5o8Eb(P>K1&147Wlnnk z1-V@h@6;(Zfl;cXkLu@853y1eZ5e7azrl=RQ-|6z$bS1pGE=G%?VMeMA`9B?d`O$$ znmt#DRp;r8pYGwgp;iBIQm~mzz{8Ubzt(2h7r;kZT{tcc-hX~cr;7a$q~mo#)-em$ z-7vvTJJ+o6!7pQlHNRv`+pv-5opoNDX}4kR*I(buvbWod7q9JW21tRNVY?zbqty#| ziayzCY`o&KvEwV|j-6I<`q(on#<@2+W?u7SP}Em@bQcL-Gh`T@e0*3R>j7XxN+SAP zjynS6EerhZX~wo@ohQ>6Swt!STW3T!MoKfkr`zxOncw62ogOxrsf?z*nWT+nX~O-O z(<;Lu;}z+6X~3cBd5^3r?Bp8z%DtJ+&7cZdr}B;lf*agVFZF_PDRTjWeC?v}T!&5} zyj0#Ynngs}{d7U*zKjz0;@6BHodK3QQ(*H2b_-l$2uz(i*iS}=(HW8ng;|+`>Np0L z$0q}JppcYc%?XM!%{_mTne}VQMcxfAk{Fo9$4{2p?BepyocSk=uk1hn#;kZ{@A>%2 zx+Q^Wev`{9B=9Bv^y>lY*K&GCPxoJoOZ*SP3`Sfb{z1w%gnU-&-yVm~t^Y?DM*7qdm zNT_fX=kCp>G$l&UjAt$)pXE#87m;^!>t4`ks`0XNv^&m|Jx-P;b>?`eo-D;5m!>-1 zJ1KgL-a!InS2CT$20zO%k~@mEx}oFLIng_RLHqsY!@hA1T<6cyu0mZ5g6}n_oNl`4 zF2pQ<3O5oCTS1p3a6O_=c0QRq!n!AhEvoF6Y+Vd_Eo^J77(OLfTt2KJ`eaXi&KkB> zUmN)PF1a~YhH#oi)sjLWS3cI#C+O|nFj>bVZZacuoE^elaS5DkZFCDyq%(I#?>G-t z;nZ{WpzlyEKAqOqJ~!wr>(4_F)pUQ3l-L%-u(aof%^2*ig;hc~d8ORmmfyLzW?Ib_ zNx}>-2|FbT+XRuD^^lUcf7ZWK{Z)KRo$_aQObDR60cgI|E3w&YQ`*qKz5nV^Y0rk6 zyM3cZ2fa;RZ?Kl;i^Zn8Ofw$qh1QBOb_6*a3Z%ehz3Ibn8Tur`+4c*0!CqWI`!e=I z9gAbadhfI;9^eUJaWr<=jUCI-zBaZTWnVDHk6QFenfv>h*7`DFrOrGZd73V+y$4T1 zWmja}jf0DfcgK%TPZgj|acs$#7p@U(1wipj7QQ=gjP~7m?`;_p#zJNbD>D7Oo(Yv0 z@Zca_U$a{FpY@|_-K`MUx@632H!nA(wJ}TiOnSQ`qEx}XAMR*%f1m~K2v2#SehWj` z_o?5Gf%bZ>nxW&4ct|?CCUwda?k2jE{{C60mDXP~>+YhQ+kREpRoTC~GLwFr&liq1 zQI{6cfw3*_(-X{=m74s^l5rk7;u$VX8(~|k-AkYDz^+gyw%ku-*5}I{ufZ@qMSTp@ z^XgkbhIvO4U2BD(JpMyMxnQYi%ADI7lB@o%rFHH4yKO(l2v2`JXwbdc!ETJzh7Stx zRu*BEhPAL5FIee@JtqM>sZ+(+xTRV7G#`NaH0Lt)Qa?R@zYl4as#`go`$WHafnrxr z)@1-I-6R#WZwJTgNGD)33#No1jx-QNawvD2U`TYmGl7iI8t6Z}gS@7)H+O80#;2L- zVEK993cKV(`FS|~y~^w`SNDX4FDgznw_4$g`N>E_J#KVsa?IlE4&|hOoVcNk1nM^! z@xpd)UebEMg3~3~hdj%;(x3NFWZn^|@K51KOj9C=x+%1dfvXOYEC0AkpPR-#G z?@y4t*m9ZUAm5c7q8eK5P;ogRF94)Xz&yU)#+p^`PtWYc74(*+;ERx7Qz~?EyoRq; z?t4SOFvOU#l&ce3|Y=chB)Ay7lVT zWZM}C8Gq3INLqebtgkIv)yq*h=nUn2BQ_Qmt%DM zOO*e{_41u8lpDs~9;I@#;tvFxG3{Af)CuXJ-0$>Ji|CVzAgyuZts#rJKksZ$PPh_l#zJ#)3Wx@E#aG6InCH}GZa`W}8_Zk>dMsf_aS3SO#t)x1<+8{(2LRamp^&HFS@|5KQ?W(za25Lw#sF54uQ==zCdcMn1LMuP5bT#*aD9bb^6r zY7XIuA*hIT1uC867QU>H6^H60Cc7(TG1)Jv1vV;WPW>>erX9&G|1dISpCP-=J`+Fg z@EetEzdy#0JaaD%>B}B|afgwIOQCex6XQ>y_!t`CZah|`MekHZ@uIs(aIp%=eG|n* zV+l6M5TVy@$a^IBr4R4I085%RF-3J_tsn=U5K^;|3K!2E_R)@3Mr6G!Vakub?52`s zQ5sqo6LYJ4kH}C?Y*9&8Mb8u4J}uIx_oMY69>fB>gS>G|ozf-JM8{uFtCO?gH|qnw z)wUWeMQy=Syn-k{6K#g)nJSC9!mvJ2CtEs2-u2V0%} zmZbHlTw!1B&IAFH6)`vDj^g5ZxFBpeBF;Ow$3#N zY%9B+TpeV}2O}!uJ|CI!>c_hCrx@YWAQrFwTIfDRbYDVy&^Auf8|-f={3{JX6swk= zl}693>j8^j%l&%H*6?UCik1qQ+ICVm;A98+$iK3=x@9zzB~8pYtz%dX!T6l zAw|>qfj1;4T1U76W4)%*r)NQZWA1O|3J>{PUHBTcXAV(-1WVbPwA==YD&EByDFP1 z$W>j0EB8t^`z(o%c_Vs95o4E44#I}BRzg0Mdd!FR{ZyfiY3{wr#&GeW{yPRY@6SBD z9p#wX>v(~1cGmre@*RKcPNE~?b$56IzGKW=l1Bkl>VsZ##au|=e zA0TPZ!UzODO-Phasuc8{>vQ?8(MIFS%LRV@k7+1@U=9a_Ove_UHDt+mg+cJ zfkl)w-{=Bf@93OWakP8aniPIwDWQNR1Hb4`7H*2DT(DFW+ZwXVn6kZF$!ztqLdz2O z6N2E%q84UxS5DKnquirO>)I74WaCR~q2^EK1>{qq$vRAwB=h)Fa zHcfxZ$ao#{n;VpG0P(Nv)oQo@(;{d|^P{|XKbvTLcuU%SiTIkz`>C{B{4vFzc1!A% zhuv-%gEG%mm9Iae`qI40n7hE&Kb<-$&gD(z%~I{leQor^$J?H!x=@Z2DUdrtoDpto?XaD8bpk`FaQO)OlG1X^wP@ zCs^~|#^CsfQv*-#1&EdgpLq?VlRMDb*1~18>~DM^T)mv>?YlTaO}*U=!gOz!H>7*J zGxy_pUB{Uh`;hfTB5kxW*)vIMc{l~7)BdxpyTqrx6yL7KELi#wufM*;1cP{pI-aYZ zykKPC?*)U)y~=eDM@BHTpoeN;$4_(PmYHxIYMG}{IM%r9yP9yo=#}mP-StSW=1R?* z_VS@vBa~x_*N<|Kd~z5BfNPp0hXTztPT?8#K3u z-07Gm=6w%R0e}^Ddc2JkN4kC<;HK4ZY5GJceTOG^um_h)j}%u68o7Ccww_Wm`u6SQ zhPCbx51ya~{Rw>|;lX70%M0meoXnnPnkW#-+S%%kI@|}sIx;$5cd8nGHC4if^Ibu^ zw!TP{G)?s{IM0LvzmX|Ceq-4&JIan}bvF(L=ew-^3;rP^FH{c=i|C5P=;<*alGTxk!$R+t`L&v)o zb8J@C;I)=$@EXU1-uWhWKdN}Ik00zf!t55uo#yL&lfg;mu&L}HuEK96K%Y+-_=NI& zPEa!Ut7>;Q#v?9qA~y2yw-kk1)pp-Xh@bIpzt+lr5YV;qUuD%hDtiDo9{v8Z_?~4g zqo~1YRln=gw^N#4%6D(AypHnSRKB(HipR64K{R@oR(24UF55*U@%3oxFdMP_NY^|L zO?02eO_D!+0dWgs6w7#aS>t6{730r-kKY_Cl~aGcaW}!TjZ=Q(N)fB(CoS8pg_IvO z^>0rP<8_WP@Lw(CAUM3gszdwqo%XdHxUcWD=Vad=H`7x%O%#T1X|X6g|70kKERgpJ z`f|Jw)IB9n&OHq6%>yCL4fJ*UsP3JjK9%QIQg=vO-A&)2?qiv{m#Xd?aE(hUqScS^ z5Z}QSIGjwc;B&Km z&%zlc()hed%nDpqZ`Ks=YS}M2=A+Pw`67 zzThtZvnE*oXvx+@uS7LsX|j&68L#waguC$jX6f^!-Xq*QyL7DBR{vwtJ>+nqvU0dU z9Oj-n$yo5G6|g|z6F7Vu&#nR1#2JxqYSzUD@%gQt+0!?_m3A$sl-kw6UtmOS_pDlS z>aRGx3EJm=pg{Oa&Bey(s4rekZ$!ngbTE)!c~y9%(d&6|w-3>`YOnixtEiB>pcw{G zBN_Vg*J@}q^WfQb@FC{f#@w!P)_@O|(}0%*IF|eq(!44N|4R#-aEKOj` z#qL61?>yBLMrazTdRO>*gnVvHo$`o#wtcOU?kHdDFxC2@uk~3IwMJ2^zBBtBL1`^n zX!Rg`rMt06wu=GZaqApUt6brBai7+>aoo6R^JD(%O{pvY{?ie*YGdF9#;=T-O8)Mr1jgW}kkcg@i zhzhaoN{NDs(=g4y*{oCnOEn6Lu;b!XCx4~Xoo^co%L}~Q(_bQ?uJtK9%0J=?to(@6 zePqglmX;tm1-PeY;BLYu3GO2g+p^9(m6F%Epm)bER^53wWq?i(fo?g?K750WLw=`< zD*>350eD{saHavAhuP(}DuBKGnfAt19F+mqH3W7i!0fiq2OG55spGJ{506PDeD-1= zLw6g0L)JcihDkyD{L2}e()pL)zUcEWzr|Ijp$CQY&Eb&RcK>LmABoh08j9Lxn%-q- zFHfak#`lkx)A+`O_{Ma^_snaA`j%re+Bje+z6zh0?~OCOf2x`7Z~pK>#+&UZ-;al- z?0{6+{lVq4SxTuh&!X-rxwr%uvbqJB5OLn{>f+_hkF>tXB$EVaTO@dnP&%6_I2uJYUjsvVLSIM<2vGLQ0i$ zbEx|#0}5m6S+eM>C6uYWb7j%rXV__Hv<`FQ#>l1c7xKqL&D|yK1#7{SPo9_f76Sep1$qq`7tf_vZQ}Q`;g|h zf`ysP@z&Erd6t>rY$|kb;fA!4n2yaA1GoIlEAy}5+oYgx{HcQ?-H~{k*;cPBtwGPO@qDnkM^QnG!jYX<-MpTP}nfdoZZm$M0+R z{*7p~|K7aU?@9PWnePdOxV4hg?oRXp;hNKouQ7yn1^i~kS+m*U58Y1(d4@IMMU~h7 zvUom>vmN2eLMC;(W9h=yd5TmY`?j~a=d#Aqui5yLb>L*JgA<4N(Q&)BvMy))}RBnlGwYhdq~qKI5ijDMP6U%{}R@D zZ9M2LfA#i(s=Z6elOOKfBGcaw?>2 z2z1%%?=mC)?{X?{<#Ra{O$m-?UqiIIC(t-=7l2=^Bc1C3ZKEW2dg6vKb(c9=$wQGF zPhIuDJ7pkC19xSi(@j*Of2WjEAv(1QFi+}@ddOhmfN^h~5O)nLBe1ztN73$7OqY0D zD6gL&QphHzMBJD;+-JtuXhD-r5;;%a$Xe;1=AC9Rtgv*^ZfdULSJCR*foJE(u5>@7 zNW9L`IA9GyniSHBovD$B#p`Hl?PsM{lH0*BE8qy+Z$Bj3=SNqD}@2>mQzg?nB(GxxCcK* zHs!)QcQ5b*r)%>{T=G~m&!3|0@zfa?(UW`Re%|?< z21W>H7Q%_@%pq6L+Su!*MkP|C5w5CG^MbAPMdh*XotR;`&oIo;^4Yxmh2lLhn+sW9 z9Hw5zf}{Cb6sIi4abdXTcYa7al!RO5wjwGThpMj6?-X75xkR6B`%Fut)$j8|v8RG_ z0o(pOYUayba%=+5{4eU~e~Hu$yPLlU*!cXC(#i=Og^X0MaTjcryQ(-?v|5`c>T|jf{i<;)A%Ua|obED?j>x0HrHe6}(`3ZF!) z6}w5+Vj2yQ<%`~dSvXYJw=Ns=N%W5W73)eBWNqJp@U3!(^KnwJR02>^&Qj~^H7d^0 zus%zYp@H6ah`aR|WAlhc#@PkJ!g=XDyW7QnTLhIo|7Mn0NjFlb-0#-F{^qWb54H$o z%C?W0wY$}g@__!i3_w5jfLeHV;{c=qJ2Qhx3Bpp9fFrY3vu5bCkw(K~s(O#F`nak_ z!m61G%IT_FO9|KHtK6U}=Ch{qZc&xBqQaBC{3giOVk0dvDx@YEq3`)>C#zb8$239J zenho;WxSv?b;<*-8O)p)r?rJo-l}y~!rooFq}_Pr{eiBNy?>G_cue>I$*p_)>y|(A-`_bU{rv$d+xI2@ zdq;nvD1kL8%p8d3H@H5UuAFy1mE(a^&NDGn3lmJ;4s+LyfCD<#1E=f$=RuIl8_pkh zD;%>KV)HEo9iDoa*10Y3BVDy!ilwNBxf7{LrHd$CKf(kf??cINnQGd-d*i7IycwW& zYtC$24dFTq>9N#lsYPn1U2VK=P6+xHjHY2}B4mnG8$$Ta-jU&LvVk4~6BD_=r% z8csJ_vhXM%rKX*LNCM??F7x1@gSNF;uzSt3uV!vOm+7+o}Y5pRJID{9fccs;k;7<$$VPd6oFZg7#UF|9FsntmqtTeQE#%xb;5~pC>Ss(2OFO z!PwR{H8U$2(Z*NsCrY?w>#lbBvj+AgYXLwyf5uF;$@O@^*tyWQetq{SSgxxAnmHa> z{Ol@ef{8ug7yWtblwg1M^;8a|!+Il#?!YtDVNFJZa#@@>y71jP(f5=NS&1eHg=Rrc zZIb-cne@lvL`mn0KJAFoMrljxO$xYbh`gS=@qSN{g(to^5{kYiiWV?%LDATdq8ss$ z)vdbHaZ+%gCKjUVmIkP*nbBq(Wi+9R)ONnx{;q~AZ;*e*d$s@7UWTpOpY?b-VzY*| zCd=&YyhM8a)sqMv!-3XmJl&&2B{UlttU>uUFtnQmqHo_O#B1Ci zc*Tf22Z@d2=g#71LWA=0v~5zLgt@;XmJx}SeB3ly!nmZp&hC@prbh?D^!i&wI^%$v zYWz{y5GGsTr2J^JJKz7C*7m&Mp8cAZ@ibpA7=Hvty-tj8K8|h7?&tb>s(v1-pZDnJ zZ2jzK*ORPvZ$8LW>t>I51IX&{<12_q3UM_Z1I{+fy&l=2sSh;!rY`MCK1B=b-3cDT zJ%Vtzhw%O)Ae^kORc;*WR0(4?^3FTQ9( zWLSRaTEH4&sksf_Iix7?Y6fwQ2qJ4xWXOhbM5Z2 z>rrNwy*&7!3~QXqd+ZrSx_7%@o|aw$f|Y&w2x$BRG-7K1OwUv94*s||Xp^_kuhAkF z_R0jCY%J zKjxeJWT@%DMtE5N2{gmc--w@Is1fpUV1(Cyx?Fuyuby1(o@GQ;MpH2U=waL~7?y!e ze zB8$s3Ux8tBqdndMl&@dmX@3tXc5&e~AK)aZc`wyk#&?8R-)Ul_iVaXPIf%`LD%Nrs zKNnN1IV#|<>Sqf-TbkTjo~istYSq8t5iJyiO@b^RwRwObJnD;mN5wY#VqaG=@uyx6 zWb;Qd2;cU_W~e=7I;246It+%Ug(e6`ri=% zal_)K;BhUJW-_3l&Dtdj325!}T=5u9JXFVkS~x{vx^C`CVpJ_XC{RfOmt%*77QCp* zF@-;6F&t37lYufTgtC?3$xt?%Vh(ROr3wsg!D+8l{0N9wmBytCIW&PI`dZ# zL7fa??mh!_ZgHufGHNC%v!=!GZT@C@8?9a1<`SjWOs*SZTBEsLDOOA&6Qu$4JLyh) zNAxh8+#V19<;LfFJC%c#kda#LM#`3mN34QYCV3%3jcQgLRX%!FezbZnKeaj_DHy40 zzm|^lPN_Q!5HcFyrbNqSro?Ns>bR48Ze80Htru_N!K)gl8@p@hzGb*io<1d=6-;1v z1l&rM)+K}$7F9Meo0BDd6^IIb+{!12Mx$>OFf{sjWY2OGwhmg`-rYg(e9)SGF=G5E z|F>4s5cp7WnCo_k337=<&yM>_<$e4#9UVOs(NhAwxsR$B9i~HgWrr98))!lyE~?|V zdgd)soh`ufW58A_T3;(onAE0ub_(&FOx6;O2||w5M$)~~{GM2JlZX2lu;mly*I=fd5{q4G$#;k!P2=M5MUF_G@>#?q=eAGMUtvJOdQ<)3;^l_LUUg7 z+~+@#XXhS1Btmz+3N>4{YR0zOMfQ^x*&_ZW;lX)!d6}|F9A2JQYkwYGcySk#dUwu= zCg_|^(sN8^Va_z0?q8i_7Y2L^mM>@`x`2shzvZOBaXF~_b<(@E8b7CuKD6Rnu63|A zcPoXJsN{%*ynpfRx~aMMx8v)XFgmo@Z~rxIvESsW178<~FW_t1Vo$-yF+TiVy!4~| z(@ygW^FhQeV39UAmR^@%K6*&y39bei@U8}W6nIou z2-S_A$m@mb9-&gO!LC}4{|&Ops9Bm7J531M7oUAV(4p4vrAkV;*h&VUcYh<1p2 zkjpSNm^#wL_){88S{DT@Rhg6%S(}`_&hpuZG<7=v5Gu>){>cqn=^g5zKgt8Jf#r#_B?u&D8nFy95m@LL#aJ|L=V8PN^h^8N@ zEbJGryW40lsFJWy_Z;eiCti1-)wfLM#e8!o+Xt-0EYX%Ap{x^KGDjI*9@f7YIytH* z^{wnA2izosRndhPLJD-B-B>`rn4OE-wTKNn)EDl{@cfz|F=W-#V4`y81al;kv z=LZ3F5hYr_NBh9|Jy6A;`WR>G^iIz1o{XG=Zwqo) zn^1p5vPN`dfAcwrw1VLaZ$d(wC#vZ_9Xwd*>J)%*J5LgZ2qW$xPpH)ehw{h#tTyhN zdgF=71tUoG@t-Nkb30vLfEuZVmmbWVMhibPeeut~z{J-fPzt4$nH)=z&3VEl`R%t3 zENW$TUZkx9;zkv9v{NAdR3jBgh?L?9KzZvTFQV5P&AF1&v7vm*A@?#`wKzL1r&o_R zIhBC!Et<`jFzm(a%m@FuoVnei4Ea+Pjbbl(u&t z@YKQHtqotavz4$Mw>>Fr#+Pv%cQ|*8Iqe1+p z`8mhaG;Qr?r{-37cV{N|;VyxVSqfI$!q*er=mV@(9|DG50_6yGE06AE8f)!I?-KYP ztz0lQ;+gr|n{TO*rgB=hvfh3X3}Lm(0u`nsImkNiCNX@%c&2H*7^93w?NH5UYOl|6 z-=&GRcK_xYTemNgh-V}<#VwWJdsaK@U3`$Wd$)RXmN2C9x~k!m;0FyiV`_7jAHs>2 zZ@Hen{0f!-nlHam#Pk>clts$!eNnrp?Kf1b#BCX9SngG=>Au!Os`a*@S*_Q;*{;@b zYQ^4-nWA*6^Fe@Jf8}qg;7w|4ca0}0Y!X+4fG$cqDc+tIb7L@DW@9GRO1OSe)c+?nd*#ZMmV zTf#YU(hPKF~liok>_9ohBpiFPJlJcV1PRjt{VDzS98f+Bm>c(@ViMRbac*;fPOWS?Jg3 zXhi|ENex7{ubCBMCbMKXbVm&7F89$MTg-gt@6{uue~53<&vg4`vZUHKubA-~ckoFv zlR9k9hKq92oSHj4AvULO%4uN{TESGSvc`Qf&dMI956OTPnlHOSVfkvxgM`gbH-dP~ z_M3y2G4AO8)}T35Pj7a=nP+#r8fu%YvPaBDSTCcpPBFNZrna1D(6v8rLb7U1r^-_2 z3JuKR0uze-aRRd)@bwy|#hz0FS4wrLJzHJOyzq|`?0f@ObFf+k&Pa6`tzb@j=Ixb_ z@bYroF==_}k(QU)K%=bxev$v~PYWsNL^sh}Wq)BlD$%OBrfrRrKYw(TFV9K}JG~c@ z>HW2ge|bwahh0JFn~UzGO{86S?iJ8fKg7aZ@_Ek4CES8Zyn52NJD)iIPNXH?lTd+<-6Q5b|_B zH)kHHqP#@R8WsJ3#LU;d_|<-XUnD$}+vwYBDBIKb^$zq+3+W>x(#cKlNZ+ylhQ8$g zkiH^Q>hR>3-;N0R#|?NN!m^d0c|EZ)K}#(;p0KrbC?hLLXCDt|{{k`%Cl%zniLjhT zlvO_d#(KB|nPIaej@8M#J74pDda*i_tkQKmT3h-gBkSy);^{Ls0)`_li@3mT>tpTv#UIiB>tF=!`!&z*L)vW{ z*G&8GaVPiFff*JKk787GB`n4upT~BA>M59v*p_Bn864RX4{m;~ll!zreuBaZ6=(Y} z6lfqv@*<856)7)S-EA;Y&XO= z9;Fu&H7-_$(oJlH(NgM+FSov4+NOZ_$7Z1?zI0s z8fj?%`>DNt_s5pDeV4syztmsjt($vfs5IHbhh;p0t!f3!H2sMO{tRi)ytnq-_wr)00PniqVN-RV)kSUd|4Br9 z^5ek<_mRoXCTP3*_XSvnGBqBgH__YPcUzUfEq>-k-`<-5!_J$+P8H=;8Alagyn^B) z{ob(Lbd?LH7wX;ocRn{>ouqfEg7~w(UoH)c4z;4a)tG)|si~dA)(qgaTC<-%>l7Kk zM+U4-ze{61FvNOb2ukT3h41h-2kx*T?y7MAg5KhWWYbz8+?IjxF+#4M#mCyr{Y*mW zb0~~>tK71Gc*+%0h4R~<@s$4|EcvYv9j@nNpP=o#ZvLU|N{Uu%F%5VQ%;0&z<8c*X z)tIkJ7wvF!s4K+JQYn2t6!g+P8{LdunGt2b7nw*kxo@mtm6b9-P{g@-^wZdPgl2%S`lTtJ*{K<=(@wAh_?gC}P1NeUlUyvkho8bIV&^)RpJ~<^xZGp4UsQ=)Ae6 zffbhk?vxC;t-tpiddQbKUAwJS=Pm=K9ohwFgkWx=NV|o;p3j<@siV~I4;)4>`kOFy z>x0Qf%SO6;9sh6C{$n3o=%aG#ZQBcew(SM4I6Y~5_gSMAuRGM!|1X;Ab`F;$%CXe( zw|ti4dd?Et8_s3~_J*66JUgEoJ6%63{fg7anT#lEY&C9Q(%;9_%*(B_Jmv^6=^VG` zR@&@Ob~veH`h8$H{`}kg`-9hs+0liips>?!{x%9uH&^g8w%q$CWDnTtul@AV*2;6j z{dKn+TKrc(vumIBZ@-r4%L)IZLWFBT;}MP(!ibv4`JQ3(j$$T3^UiVyc|3UV7W!(B z=f7&--{zVyUFcDrEL4hGg6i4d$%L$QOO7&BH@PPyJ+%`Gh3bNito-*)I>&HS9I4>K z^X`E6yz_k=&Uf3viO7Ifa!!*%m{@p%G;M0>{&d%@oKAl$=h;1&V=|wFI2`>{-b^0c zZ}u|@3(pGryt{ed4?iaQSGy}mSq$O6P`Weu-nRMpIfG5AS&q@#G(w*p$DVQU&Tncp3-*d5HZFB78=*|_42YG+}W!l2OX7q3e!qrNx^hO^O0gK>I z&vECl(%X-=@}(*`aWbp2mtRWv_@4`C#2QyZ5uja~f%fYV+TZ2~ni=;rxE}4mv7f0u zxC=sX%`CVF+<*+YIU%??9$bDq>Yk-+nmT+--O`t)u2%@|#~$3uU!>bQIs|vH2ZyVf zY3#QsYs?D$i!Vnde0*kEk#!33nOz8@(Z}9iFd!jAo87E-@tL6#j30C;zg7gK@+#Bi z>%LU}q7LPYB<#e0(&cNuRDM*4@^gIof^_+_zEr+zhw^KE`G5R8q<`p_%5OZVeS1ep z&r^ASNtfSse!KRTsJ*}P<;#Mm^!YdC!Qy1_BDL<{{5k8FDFmyCLHYRA+z`HPMbMIk zu<*B3c)v_xjgM#e!-eV|!REMez8*f@$AdCH+M^$e{B8wY#bxsUh8xNNLC?V%LzH|4a+1rM#h>v-J_3Y6p zYw_TDKQ=)e$w-sS24B^Z$fT-e5iSO4U6vg4 z$<6mBuqelNMA&)mfaqVd$3SA$lFk>^CVEVZKAC+KKWh>_PA`jXQGY=1Mdh>C`|)Xf zs>?x;cgu|A>?Kcm!kZYSvgVdRPrU9ZD47&#;0Vi&d_@6>qjP-?T+BYtwe+fS|UQ%ONP{Ai7^$$V{gez%Tse10|w#Oa!%!t zKZsuN?oFfLiA28EV1-g@H$I-D-Ix} zrqdsv{HZ2-nymHsp|;!Mzg@nwm9FnHhIiNhMuXHEx9hTs`qxjCxgAW(3vvcj9 zV1}x1uktNP?2SW9NuMxZTlj7U`dJz1zrW8z|2?J4fPOU4_l)%Kek=$+>xB%5hPPwt zs~tz$;=y7{VcPdQZlEzF_}W>?)QyF#7wKVJTze|r4b zY$IgXmY2ef8exBST(293(r5WvHW}Z>IXt$Ls0pqG@%)ohJr<2=x;D}}ft!UJYfsG& zPCctUHMfxaP!GuB9qaEdPFA&+UOV8FRF^DFVd=H`lOn6#F~vPQWz9RwHXS@&sva1& znfF|*<@)i-cQi*q$~l|0?WI=QA9htd+Oumi(!!q!`N?6Q=`Xjq_MCuY^+vLxg%v(q zDv&&KL9Dk~?S@b}+3>ciP+H4YdlGV~op%=BkskNx5LhC=ER^_tZN@bHPv>Vk$a`5~ zDDUScQ`Zdg%b=EZiS0w)V_x1TfKKwROr6R5l8@TSdsygT3Q1N6hVniEdEclP10?Sg zOy2v~OfY#bteIf)-mhkY$$Q_L2`29aH4{wU`_xQ0$$cFpX?Z^vX47Kw!6QR?Z*YY* z-MolTG*Qo~nb^5zYDUfrYbKh!=hsX`-X+%)yVgwY<|SQ~CnE6@@QD(4eePZ}HJ8sl z^pnr_m(O|O=lyG@M$v+NNq=F@RQsD>GqqJp_c{jY*5)FOzuFjBppmy~ z*NEss-4qzN-CG!VS3@zyRkbkuqUcrGn|{n#N5HcvZoPF;bfaa_Rz`ag+0;KH+!?+~ zwcHS8y742Du9QF}aH@aD%TR8{W35=JPSx?n%pS0&SU?~Unr zZ%oIVF>M@g!sA+qixNmZSAD6IA((%L@uE` z*7bihh`fHnhJ7jt89*CEE(Dt?iETcW7u9hIxlSDK_}^aslQ>dD2Dk{?-1eT0Fe~bA$hQCAjJC?tL`FkRN59aSU z{uc4~B)4?*20yaYUU!Lx(zh?Xwe$W`dr)IJsH@MDYwqLWhSy$Bs zQC~I^77Yil@ttcXM}ny~W);?q567Q~QKp?Jr*o!moX6Cie@b7KUH# zFJJqIUkB7o9vDm=6n?e8d_5ridSK1ugPOk!8`Jrv|I?b@thrLVM$v=T`}??Z0a4IoMy>j3uG{&-0ceRqFlw zLq~1+FZ}!YzE($5?fv_rHvh$}^r=O`sTifXL%sjP?EEYIm(y{KWt|s5++P0u@qFrF zn&%()zhRokQ+Z$hOWHIq?-!cpfA8P_zt}&8ZT-`?hxL!my?)bSd`{MB_&x6@Pp@oT z@Dde9@W1x5)M+?A;_x4T!`33#X;l7N*4f|VSAMcigY%|;9bLe$!epJs=!*}HUCghd zWSxfU+fRAoPJRtd)@j7fJE{k3ZsQ}8bsD%2Nd9Faze-|@_*XN@WbJ~rAT>7m{hRrU zU33`K&&>7or!Jl5cXhD<#Abufh}xAuA_x)^jp21j*Xd zO10=F{@i?3O7$38K5V-tL}OmRHqQ;fm(F@ngtS~VC0ORV^VqN17J)@!yjHw_xC-)*2qa zeg_XXeT5=}w`SqC>N2CjdyUuWct=@xuW-SiL>zO#X@0DZFY7Xjv3l90sy%ZwR*Sqz zsUD-I3|q!n9S1pKN9}+J)|4@5yAvTbZr*cSsezPYoGtauubFTw<%5aPwg!e0dzhym z7FW2%KQR@&nbqTZSyVIOrtooS&4e2PGofa}4g8r{GvRvvBx@#I7feigKy&>Q0gg)l z1fU9P>ob6^4Icq?4OLIAnQ%3Krq)cD<8HeZ4$FmKN5nR`U4m-^{_nGGz>ijclMtpn z`|6v`7buM`e1wvm!<8h=(%?#JShcB#5jEpkg|DZfHRC(`r=pti;a3gf{vAVNwtr%{ z)j)3hTSHjmbNnZO?dP8W#_5p)3oug1dIDGv{{*l+{{%3N>{>p8z(hX7cd> zBh(S{EPMjkX#WmioO7YC02||<05;Y?0gPLC^c7&^%#77cKB@TxB#`~!|5xOsS^o!! zT-dQkH(#K+1Cs~M|NgH@LG1r0{Tp)epyq)#rzrjZi+;?+5U)r!G?&y&4xdKUOvWVZ z9X{>0qMGRgYbFmc_Ov^pPciw95y)g+&hlqIGMC-_wNlBT{IxN^UQsO<9*-&~SvPFg zy?f-z^9z6NgHZ>ZFNdCA_-ikI`<>s(ujd#3+Cf*08z%RjU-)a6KO6r{UOvC@*KRm? zUT-=3{Q4??E%g7hygQQi|KGXpzw-Zmt>l-yIvu^?y}BNFbxrc>a0&>m*G`p_fm1gz z8JJs!LznE}(0OmJ9DldHH#e5w|JIv34uZeJn;W1{U*XOD9lz9jbN@xC(gHEbx}Q&( z(ZA{V6Yuc;wt`sJe;Z$Vwf3SPy?HIXrvJYEK! zktr|Tbm_1wqx_=(POe?r<=U&>zK&n?U(=`qE_-C*Pfp?&{r9uGH-7JT@AT@)udnLA zWZm$c!#=(N>bNA@mrXOWbkdFWiyUw?R%JR1=4%0- z<-gMO`%HM4A1w7SlEI_mw}lZt1dvS(b@~_+KLOK{urrej8n*IW9(uHs0nX74EZ(cCFn>1`sdFs!;!YU$_2${gcB!0SJ-GWU9~c?y+v*t^KW0_n&hd?IXBfF&{kc zb7N=lwf{CBI0_0n&ZTUd*ewGg;4`}&7=5Uq| zBu{AhzyV=CaG;{L?;+>)rErY=_qqI`i&nc&`?Sx0*F@z=`+Oj&J4=11Q-U>9yVysI zsPeI^rSZaqV9nGV`{+~Oni#c92i8pOVILJwZ7#Hr`+HxcEh9+Ek4&KQ;xqG=7oXXi z9H7sOcN~NF(I5Mi&xdwfr|c`f_5V0OcTKk9Tl>t<&E%8sD2v6fcJpB{@uiT}|HIV7 zc=gUc^4ID7Tyqyh_&>|8DdUF+(Bm`wRe!;!-d?iG>LE~YEl6;7etGbg7SY!TCu^?e z^EbGbz#8c04|F)CL(NBd4nQ};;e?PIf>jRK+UkZcUK&c z_Oh4S!_RG=0lmv0U~6Gn(2%<;5nF6U3d&-Osg#H;<7Y*2pR&jjkTo>*v9Ihb+H4K7 zmv4Hg{R}_L@)}#fWNn%L5xI zV7t;?bU-d&b68&+6Z;01MRcfimw4>Oh-?)Y+8A-5F(O~YhOIrQVMU>}HL~6}Gl3+K8&(d`tImX zUayozUX2Hvpd5z4jecTNY)j4nw5MTZA!nIFMbKapAESrg?mlEmSuU#6 zkO;P9|LBHqe@*flc|L;qS{z#<+9PXKYH=cWOFXtXc*P2-OtqF;Uzl7rr#5k)lOL1mwiq z6R=F!BWuAAbJS?CcoIZRusMUJV;=!Vr5!9Xy ziDJ%6%5;RR!ha$m9$ETj3i|Jhg2KHh=-sX(;723e_bdn+c0vP85HGg%&85HB`u_M? z%jR#)aJLU=Dpx;&A#t`v8SG}T=bOJpQY4m+S0qcg|>V(wYRv=ge$`Dzu=>#kR zS!5~AHe?cqopj6qF9x}35i~LI3XqWmRWN$`?_BE%@q+MHck8D}Q<{Wc9Y_Fwt^{Hk zdbXmU;qh3-10giE2niA&g3XaewcS`?&4vfP!5FqXKuMt)9mrh-O4yM53K|wRTFMYC zQlppmgbo-0dZCgkq63HkETA(y2V|eELn70p!+nD9E7hA|8m>BFHP_&NL)u^_hX+g%iexfxh)IWBd@z5?p}y>E^2_ zj4$xb7w=`-w)GuihLJW)QjGm(hGY)l_Ym14tBNl|?U-LbF%;QIL1RYvRn#~TTAvOaz!2`m zfqq}jfwWd3gT{oyG!uk0@_fh&_z>~{;qMo6K+VUjEe;s~D}q<(0viW#4CH~B4G0xb zG>eXXbi?xozLx3p;|?5x-Od?!o}$JraNy z0fZ*Wo3xV7(05*WJLn~#0|W4vG7P|BmlT}(#q>wPA1sk*<9p;%AG?c`VFAK^NL8tn z`eLyRVLw?5Nu?LW9&MeVj&DP+N{F98LsG8v0P-+Iv@OI8Js$J&fnXLz67RK?=p!}E zjDp@hrQZb;GQezxBeq!Hg}5Mwn`FWUbw?`rD)dO=m#`P^h24h0t=+vNBEGpbiK}Ax%>LQwMY@4zXsK-=`z<5ozo2 z(EN)U(*SrLQj;qafGT2y8bJ*KUjEalBP&F!L{MFi1W2#V3Ki05yAfCxxu7g)rqkoN z^?3Wi?)c7^c`VEQG`?WbJHgMVC1SgUJiee&EGWxu)^?dLWx+qReTI!sFC}u{DvNxU zAX<<_lWcIx<(A^yZLvggA`yHN$%^mX$iWnY7AzLLc*B~)2xI7HWw|?tr%~Cz*Q@kr9-DMj8^i>qIkyJbR?BlXIVq%vIn zHW6%7SP@egqL#o2^NOAjg>$hu&Zv=b*P&9DLkQJr%)CQ#f^}_7@%jpOzzz>lBR*+1 z^xumO4BQeNJm>$G4a?G4=@n>&qQdq}2)(v878HokCQe zm-}Mb-aXNuLB`ZEWJZygj}Sl;*o+x)UFLGpzPNyQjt#Xz0t!qg(#^+>_%eR4nR^p4 zz=+rv8~Su)1CG4Bn6F?1qewexFfR1oCl@d~84^AkH|I(^q`*kfU@OCuY@g`qey*nOD*_HVRN;Mp#f z%EiqH(L+d@0vs=7fi^cRXHXFvgdFAY$Tga75-svyyt4=;`1D>Qt=Xcd*Uq(?QJFH} zyWmTEuihhu6KEQ4zct>J!3Is}Fxx;3PTVL8k&2{nPM0U~Ml1Jvs^jg=DMtDFm6(Nxbm($UMid5(EN~ zp=ri9w-K2>QBS1qX`XxKja~+bv~=u;qBI{=#w?=@a%4SrOjaq~5pu3G9if2|MyLid z=tE6({}6c$o)Mw`dd$WW?~2R6Unv@}sETk&GHj6S;42up<|}x!2rbeDh%sj&KaHDl zl7L*;GcpSy1?m^iEv97_Fgc{L8BpPmd za`x(u4ssdlh3DFK5u*^b@gjFOCd#`j`V2`yqm3cUWw1;V=nTd8UyL|YYm`&)2?BcteTU?qT ziW>o0b6+C3a@HeT6lRaDm+=A6v_$TTGEu#muyDL#1vGKE0Fy7AhI2*3CPak(ZCDBO zHWADPM=qv!OH5H?1&1RK__R#!I)#TLo63SE1d<6LD?kh)A97w-mW$8br?@QgB1w!y z43@6wW4KnRv62DmxxUl^Jee4!w1Q0vQO6J>&Z$k%3?vtfP!yM}tmG&W22~2ZSQcBa z)&L$&p;wSjjUXBq93p}YD?3E)M99nxt4+kunMi|4j3XW%7_!(V;X`oJ_`rl|6eB<@ zlo@=?5IjC13UL~~IG_T}*g#3o3M=CTU7g0N_Ia$nm1Cs)EjyzomzW#exkM~D<`50fAf~V;c}K1tY4zzDCcNR+VwixU_RiI+>dFATXqRP zq~8mc-o+md09Bs6P8i(}wuG7RMLOC;dm?Y2K#KP?RB#fjX&x}bl>ruj;8HTbPx$*r zbiM|!$bFs_oK~p(jZl?Sa=w3E9-Kygn0ug<8lI!nFlA>1rwtNkrjePMrEHQ;syjD& zPy*^&o5=LAxuCju5fGGo$s+l}-)UX=FfE^dX7%BpO9}(+cRp)S!&`+g9UmO!@Z*Ka6#El!4ZOTgh~%r84{(2dKlR> zJ{;+hG4t22qcTvA_E1K8WJ>N%8<9bFOr}`O7dwt(WE{aZNMJ^(cnO7g7ot0!M|~P? z_>?M4=;sL;NMk&t6Fov@?x&5-ARLz|c2e$I5`Cp$>JqSCfZYDeu?Tlb4cUL>lMP~QCx6IZgY!8QhDe8JXM zuI5o{du!KVaYIuy=7KK8B)?AMT{}i#tKFt^3%bG#FY9OClayku)8o3 z`w(`(=p4Cb^iTq?UF#8CXSk<^2B082d?2l8*v2UY4YU+KQ8~w&Nv3>TXZQnW)PXs2 zDS}0CbpiG_s}szFPsUw=ebeTA!BS(e*k@c?n*UExwZb=x=ljQl4&GEOnH8n2{k z!ApseGC?tt?%gsxQWtpfA@e|L+2Q#HZv-1867d*<_s{)eaLFM!Ww~$ovvDG8BQL|0 z;0w6%ZXTk6yybooY(st!5@u|%ZE%H!I3ZWG?m>*}9}1N*Nm3>5mhqKg5Y^$Y=%3}r@0f#(8{6TSlz~)K_PQSaJa3Q(M98#If{tAbThEA!OMw}eONZJ0dI64W(fBdUZGxP!E2HtZUIM{{;?mt zLfcG^UPHH75%C3bg8=1zVe!{sn;23g=3G%c0=~dKF~OwDB&vtLAxAw!Ekl63o}pqP zi#lpqk9}zw=JtPA%Tf!E{zc8`Hr`+Wj5o!hk`-O!EIC~E6~X+tMz z(s{~l|GsOj zZ4oQ2TDiAq?y}2&{=j>m7u^Q8@(qDC!i;YvXo~Db#3WOaE=ihrDPHp{3DA{RDdir! zL>yI(z#&nAo$gTy5UTQNj9KJJ?%4|>*flhkJjI%)eeQ`x@~F@uXB4pdegc-48LNM% z0)~mhTj-LpU-4CZomk|c;h#HXVPT#-up|6atKzE$W8>+lF>E*vW2|9A>~Ma77dTAf6;HWZjJmv@}_bc1DZ4gOl6KB5gY zYJqpC1)$~C5C}grBAMOg$(byWL<1gyZY}Z1bMg~PlDFajzSF6Q1Rw1bk)DT0NZi4T z-5v27p2u1$Xeh|B-e@R%KPY6)5?+#sMBT8Zkd#!phGNVj2cZ!Zig^^$T8voOL7YY| z_JmDdsc{=cO(?|mJNr6}j2M*ld`8nnn4`mUt1LHNDPc3zg1*oS>4BdxT-*4=uIzV6 zzq|sOc)I6eW|wcmeL59=V4`P4p99bbITI5-gQoybPJ})?7>iReQBqb*N_-#(b^9Dt z?a`;Z$U$&?KMv~dBWVn)h{I+0yVL-SW>#fu&}-l`dE=syJV&duEos6=0Q z?A3NjoJd2aca=f(wtM7)DoN3lwF#dq+UPDLVE=;$meif2n06hF^4QEOJoa z=xpC8%Sm3?VJXyD#yr>@m}e)XX%h3u#@^8wQz1a)*2Y?>Lo+Q5DvS+&^BlwsiIn7C}00x_d{Y+NQo26nsEn0Nx%YR{=I4_47R1Rwa=k)u*Yb&L-D zx|Qc69R{G(nNO14bh7I+bv_>)aQO z=E^;H0mO-NcX?coqxd`?kLpPj+u!Bcdenv-MZU{XgtJP{v{1gQX@3xAGsbI=yhYI8 z-Dvuqnq)y%e<$1lWgtpWnU1H7YYjyDYaHmOYF;!Bl)N46KXNC^G?{p#7`s!Daxs+P zJ)=b=nui?{JDGtK+rU>u>_!Qhu>MRUR$azGYX)PWwQ5zpA+qJ7>M|~p@}YiU2Y*_| z=}Qw_#QWEH)Xd(0|JT0p-TrJOAbH$6qwP$X?}djV7!jKBu4T@~;Sd=C!*@*LTPZw~ zSBcMP97{aclaR;rEs-XifDNMJ+tsXDu6uIMv|J$~*FCI3~ONt3Uk5-4;wj=L05*)u5q- z(=gYrk~rel7?BiYTx2qfFK6Ep`j>PNqx7@iTP ztnI^Fk`7`DgX9Whf{JGV3eE(e9GgDv-;Gf;tcR*F8Z7JqD8%cJi)a(!w~}!*EH^+X z4eB%yz7%skRnA=4Qx7M21=h0ORbS>h4a8*K1<3?4gM0?5FOwCJ5$!`Ok4$HWGxfn! ziq53xq-U2O`2OF0wxqQzQed24U`q0?2qe_8{Dj?7#sm+F#~^+(aTNL@vWBxf@Tp1G z@mZ7>mNBxkjF-lMJApT08r_o~FByA>+A5hm%S$b=Eyhp65mpRS0-u8DXwMXu5(U!0 zkj!QW0H2ft@sk7cJ%b+jWJOSH)lUi~eVj)244ox?)`bX`xey9t#zbrI*l`Mc@QJVu zMp2C8isCal5xRR8L zdsHHFB|e3;{pL%g?F|U^n~{;DHNS$D>&0<4jdJ3wY@v0QjE7*-C@0GCr?+hjH40v` zX~lQ(rb<4kl|Awpo==LJH;QW9b~Ck7{URpv@^SqwB7Oi2h4c~Yfv><)!ZQVY;*6G1 zO<{C4uVUSWxWxNbIqNXnqZS6ozXB6e;A1!&v)Lza5Q~6JoG!7_7mUIO^r0xLsZQrR zoIwgF;cmqu`;EE+eKES~RvCs}iUX-)H(tXyGD3z*$~(()8XKr?wkXgeD3TkYa&CcA zzfw5(TnSGQcOg)X63QsZrm=}}7o5=MGNXaV6&J!p)|Ds&ql|(N`s6xWcr(~X5MgnV z3sJ!moheIagF#OYi7P!Zlp%~9j7MIGMXtn`_!kqc3eRM!Du^%ORCdKz@WVtB3N-`* z%X_L(&aUL6f?TPHiKmY1rY;K=Cb@%H2ZqN>;FJMh#zeN`oFZ)|Q1tOAMbM|fJB?e~ zRH78I;8_5{P5mfk1QD0$jFd9!N)Eh@mk~L1n8*fdsptTol5EV9}h7+;~Lz^-Tr#Z;#GWs+#!cFR`ae5SI% z=Jwz!`B)9&D&khyie?nS&vp1z1KCQ#S0a$fepV}ZJ|qiaGJ1GaIH8LF@IR?A;2(Ja zsxg2dUJ}@SO64hLK@C+(nhF&RvMN;MXTXoR`m!o8`s3mS3W_Y+AO*8`m<6+xppn;J z)2G+~Ra+#NWYwa7JV)eWjf8clC08*=gPyA{BbUj68Y#4RRuFO#nEU8pcEvaF!3NT+ zD2D0`RS1~KBB-UrC?>;jJ&YCE!7E$EUhZy{3(4D(C)#8@Ey*ZFPsSY;5DIHOj;^xi zXNV_Y0%ponHg1rlabV+r>gfMAuXrHBOk zv5&&&a|C2bG#dJ%S!a%;Z8Fg?O`lps-zxqi-j)dE!-5u@!7H`JQ8gs4kkNt2On+&# zNEW!CU&^7+zDF4;u9)*a67hx>-hH8RG{J^{>4n2KS&Dzy<_T zsS22CbYm$N1YI~|EZ7gdG8jXUAOn?trkMG(GM8Qc2^^>r#DJ@bSADD06A{i2OdwrE z83Zo`CHLV|n!zT|40 zb_EH+`%6VsR{ZXeWkAtWN7Wxz5DwAWA8gmYm*@y`f~y5%9ih4dw82Q=c7Q%yc>=*2 zgEfQ=#vrgkBrM@stBrfrFAg;Ns?O&v&yny`&!?2W{s5N28R|UlIz8ZL!=s|AQpJXh zq3EUL7uiB;vtL*AQmua)OdMn2J>x2v;KtP53y*o+=PM8`!m^SJFIr(iaU9B0U>HH; zW0?$?*m9!bHc&kr2s5wB2e3?lh;BavfK?>d8SuVfKd@o1nuo*~VLTnVj72amg9&dC zJIPv$a$XSw85BiME+?F{(>Mpl#ggz{tzM4Ft{|g$*+5SVBe=fY(;}y36VlXJnd++N zhvR<2S_%nGja4Jw7Gck(BEhs6qrpqvbwZQ#Lr_`9FnW%AxoK2Tp-NDqB58G1!kj({ z?N?W!dExk?({7qfUIX`1K@*6(iKW-ctd1#0(5M9?fW%lLjDjiS1QXY1my-#+T6hd* zpR=s%h!&H}?zyNQHrfIA5tUaHNA?#-RU3)Bj>u!cEj=PhEO8eV`nY~YU1o3x{8-qE zp_9&nP+r-LPpC4KRKcoB_JohRTlMWAlQa5d>n#dpvJ+gPLcRQ@CNaLt5=y03CPCN_ zXyD=^jku&7Wyr1|AIQuWNWvhIGBLWHgu4O%?idWcGLB4t!NUQ7DkuEXETJ+du#_^6 zZke(&xH=1HngB;K2!0BsikOv6s+P@ZFuLmM0lI3hIPdHe^+x#4E>VAaq;ENS!DA&$ zh<+}!gh*$NrpAbON?3as>h}{mTRXGY!>=g5@+Gefzk1rouM7)Oa-~!b1;gG%7+6WQ zMNb?42H=t}M}@JC$BkR%Px;7g8inw^4PZ2ir7>pb%(@D3H0r9T+KXPO(OtxQWC#yX z=N#xl;^a5*2Rrw;kwYRw<5e-6i<-z1YSkwc#2vsS9pQ%2;;>zTBffs(HWIK>PJ(Al z*$faM*BH^O!!r7ciJCzndM0u%RvDG6DY{$hfeRkucP2eGNU_WbfiteO>j3d97R&UP zzUAclHW}$N=Fj>Gs1b|2lR>r6afzR(Gag{{F!#Wrd7)O4yS(wMaKx3Wd2wXKuZ_`^ z1(0V?B^e^&sJ$*p+I+DA7T_j;`HiC>2LRUV0x~#9ZfYyl!~)udM3tjha+<-D5iFs>CKkl$7>CzI z0h$jwv`TML(+^a$9`acv#%DI8m&!C)KitYp)Ej`soMP%8p>q+7LDtIXRhqh2^cR%8 zF=8hLZ-e6op$e@&Tm=cU%S~+-eXBDB>}v+$7b}G#8F>kk$t3CzUaa>r&w+LMYJd*A zSY}HF$I?hhBROr+LCkg-W;4u>K-N4%0U$P(rKtiYjWpU!fY>BXlQXa$fYcfy>(q_g zmR+GLC^f6^^ow#+V>sPZ%u{y48!2rPjx9g1Yqb#+NG&gZzY6q07S0sE;L+ zNrYtuwVN8K%qRUOSAan?rY=94nf#~9 zkV5McF$`cPVyIAOATi1VbVCdVLI#$R@KhlbsD}bb^?~6&PfB`GN`@ZBV>t+nrm?{z z(u&jyIE{D%>Wc{SiR4x?dBH1$={qE}qAw|mxhnLB%~e4Pupg0vc+irQ=(}%PiZ)qnWW*kTAYF~_?!t^CXqp22Do3| za9F0W!vQH&aWJ4seY~8Kd}#6yp%P(*grP(VTUN)YTzzU*FvB2PXw+g}dLGdtBIXq3 z2uArEe^g@A$Mx##z5Ajfp)j7i)Q6IU(BVxn%V7mPNQr=V!=VkQCW)qw^if@qcU3g46q7O2u^Q%{scgChifAH_d>O(gsY}{~7sWU9lq#tR zoMn}=#msYG`2?3L%BOre0D3=DgO~_}z#-eA*9kDG*hG8Yfxuz%PB&g#0n+Q+5|X`xxSAB`%xK1==7wSmUy^cvbGuB{jQg zP>fkzG1srU#T?3Ns$0r>XySOTUlCiZUpQ@m(wG-c`{@b-CL@bw8AIN(##qQW>)n{i zT&*5djkGY-9cD|u)&Ud}M)9#f1QAwuaYt_FYyR+intv4s4sMX#bSy*$6o5~{@~ zRAif_Of1S;8&D*y)rk0eb#$CbTac#ZnG*wm!P{8BAjTSyuI47dE;yghU7%&-$pE4N zalParK&0)ggb%N=1_J+%@#aPvOs}K@cV}1F#4V{=7Pha#w6N>~OaG`~EjaFJ&u@$P zmGe(1kYrsO)}kR*$h;0?;-(Dtt%>MXKKG(;mfE|z56>y%8Z7#XG-yDP z>C(L_9+Zre{J}qzGYnx`OdZJ(`UNCm7IHFa;teLkPAX`Gs!U2BXC$sc-)hA=+&WiM zNyP-q6~b$CLAEkc*5cX5PqVa=#Q0H>Zhn}RiPpMnkWd!qfuVW?olVygGh8=E&vqi~ zwe-FgxnLn7?wFH_j^@WC95|9$M0U{@zO%y=r*G1kgyyTv<=UGvQTD5}3%HmiYCiC= zU7}`zmZ({rWI>uGJXq`9Xtfx}wTsAT!J2QI?{=LTZELRub6BwEhy1ZSrJrJdogLq@ z`|EsdK6|Y;C0*?^q;1iiLO0vQw|wP&c3X6ImHk-KY>U40dvz5NwgB46PC2pc)XMy^ zRfR%ve;x0lf9E0=25I|%-L{2Y(Y^h3-e1~Z=Y8J(I*s1`I^(?kb>8dkuXDM#zYZIw zUX%Y5Uh;4&one2S`TQ~a>-_b!pK^bocfSAi zck52M|202ZM)URun!B=4F#7`;R(YHI1C8V6!S)B5&(>scZ~l?*&^Zy@ZW)H?!rWjj zT06>Yacl=c^zpWOj?VITH~#N`W(X5Go?ZM*>Z&>x=WBQOB6OW!cCPwzb;s?FyVc2# zyu9Jkiu`xl-bBidXpgU1+MBJ_ZPH3mPSRamonSBKyZ+|If_tKU`SFfGH1lC?lh!)v znb5Rn+L!;j;}R}#<~^C;z3xSxv4u^V6Yit=IvSo-BU6P!=au=5UpZPxW{3UVfHbINRqmQcpefE>P{Xx_B)Kx(9Cmf?_I%hdkTa5zuuz4cQ@rD2q`1G3mOP!`?e@~MiZn8aF z$#MQQdR*4CYZucq-HUEv$jum<2WWXO+D~?8=Bnx3pa0RHnxC zPGcN5B{@4+bMheKyvr`F=*CF1O>Tv>eK`O9$qXfHgZ;%C8k<@>{Zo>me)8k(2iRuc z1Ptf62iXKLf8oI+G;O!o;8Hvm)BB$M=8wEwSl-piw#ysy^YTXuk*-4*GRhC@o!Y3o zz#BdG^!Lyk*uO#ev-?lZhCg2#3o+lE(w{%)S9=WFBK~~pug=V$Eo;j8bHQKt;m_s{ zGl~--=fgj-qj*Fwjxf4qqqvMgg+FiRC-KEA-#=^qERFA$tUta@gN|=Q`S>0i(|>$( zt%HoO*&pnGv-jN08*W4a%#Pl;O4=xYt9_T_4!zWEs&FD}#XxhCnDQ=uZg=;|%J*=n z-PKqQ&KPp{2`vRT*KuERCT-}rrQLlskvdTqy6?y4y1bM7P0+c09ozq%DDL0e?yhy* z?T{o|Ky3|k#s?B^TXoVs?u=(!@6`G_C$)ypZz?-?v`;$O@!4poZWx-f>JTDbs9X3c z?eACi*a!7IIG)`~^+d-#&%u3h5|Jt=!(M=_HkF7>txjav^80%G_>5k&rY@10#$R6Z zU(WJEXjvy4<%!1VF*YOYcCvRgUTZ|Cz4=v^uuC)_*0+X4YW)zyz=`H(bQ$Nux-H>- zX;}qjE4(kQyk|(?_9gL8veQl`o3|$LQR0zDlFi$blQxG^|IBR;@ragen>Fk$HdU*f z;1tryz*~;X+c&4D7aU!;#JdiL7#(P1AExt9nro}m*Phhq6!C`aa9wEmdAj&Y-MHxeiRM?Y%hrY-t}_(b8hVe~&gPrJ z@##t@o2YbB2P-?#CzhAwNy11;RCnaj{6}3lKecv#^wZIsQR254)nxRa;osGamdC%V z8hB{_AHHEE#VnSXaCe(+>kQADbrabk^rd$6bLx${gW@cPY1op@+J7!M!VXv>m9OkPJfQDy)P3dr z5(N&y1@&-&#uN3y_JQq_4t5MjjE5k`agAz2`Isg#MGZ4&8)bB(-Q0Lj+6<<`hX-jy zySvqoEYLkk?f2U2Ubg(nj`xS&)5>O}g^sb5<~LU&e*1| z(@FOMFARC0aS6{8?^+e5eGcbFo=m!jHA)Q$^hyF1hQ?ysQp_gnZr;SYn}HJvb`ouV z*~#q0d><2C?#7UQZh=8Ipv&i`Cl*ER+DBEqmouUg^n~yRoo_A-iJogy7|q)4{8p z)Zxm`gPF^qdlS-xEZtlZCM2pv|Jl(SFb1va!j1Qv5s)OgM-?|(ZQmPpTk!S5G~z=J z6@owHS{S`!3{F>JBjm61$$ws=u)ffpIuPo7MmIP-;vp{nFLAu<)F!iwYm+=c;i%Ra zUBcg3_KP*4M=}qXF_)-@?%U331(Of)SC`g>-oy9pW=~r7@D4hYwm6}wTLK%{&eF{# zoA)}CRwqMK_G5-Q!s(8MrsNzJ^T;goIB9LPu#IsNTe-PVPc&1t{E^NkKsI-M!rdi) z3az{ryZuLnKrTImP$`<~Ds&$5ZtU)=BL^NFDC*on0BY;!2begOO&(S z_d5s4zUD6uOFWj;+d+>Mzs%loLXql-dmvhApNo2 zi?ncEp|iJWU){}x?y~V8@1zbf{u%&{VW#B}Zh4DdzJ#wZMJr5kOZ4UfZYtl1n{o@ho88!a#@bnB;9JcpXr)LcJkE_x% zs{P|(=^0i2@zC^)Vg7M2J!7bU97xXy`o}}kGXnl`WqQUCbDW-0$=`}mYm9BsKbD_8 zbrPnJ`EM*Ms*^O|Q72Z7B;9>dBVRqgdl=(YfEHmZAld{O;ge-r!VQepdrMkIRx&!F zwlPsyJ3z~5xU6>hB}dXOP3V(y_0sOXEcK$ziJM=sibYxll_HZhKN;97mASZ&y|AIh zW5_!~v1sDMA)f87Y2NMxsQnKVR*Ngj?G?H|Qtf2;lWq0vm3Y-Q&Km5s4mAGL9T#ZbE zA@%mtDo*Q~h7a~Q?lTU%l^cg```&hB%LX6W2aHO2Z}0-Sj;+UcU)t5UByD9hzmYA^ z>EP&QcXMiA)ha!%ImcTzhyKs%CHtyyxp1Ef-Hl7O161>FBsEj zT4)+>_{eq;;>@>}uf(m7K5FRmJzk=~s{uP`HSmt5hB!&exnM+euoc*Z+bfF9HyrGv zYkSn)1y1uzF%Nh%dh9*Rc&JE0#vf<#GE+^*p4rh=)#miA1dW7gPhmQo0`VVaV!OCt zftUhTFfW$*Lr0(;{5BWmOU5G1lky+*n##*d@@3lmQq+A90(L>PyQ)mWZjn2evJfG? zE|WC%7Bu0G#)iL8{Z=GW-5BzU*r9L22tUR&4J#L zmLl&LMJ|UT7x@$ktz3;TdIU+2zCvEl6AIV94J9m1zGG-|0J0=RNa7sCFqE9Fs^Z z4}~(*Pb5;km7RNSj3A1vHxzlHvhzE7A#8>}Q$~@Fa2Yjr6vxBUH>1aUy(D@VeTAXO zbJ5Iu#HLMhxaZ1WYVh=r;V@7Cw9ZzbFxzooST&b^jtm=jtHPr6nOzbrJhd=>mwhJ>I&Bm+nH~u=czlws0 z6M^Kso_00{xGFv;wCrCsVqKv>xsAWk)N9qD`)<-vHd;u|+mh<4bLRCVvZF6`vdNJ+ zEPL)8>15+uaB4!SiCmY+20!jh+I{D6XVR`v>b>^N1n+aC33qLaQ(h5BRAmG1myDb{JXV!=l=Fjk#?X7cn>vlfewTDNn zv5&YdWbc2aR`+|ip6A_qA~9)g=z&ifm1}#QfTEK&hO*m48~P@CDxe8oMV7#6ekR$x z$GEB0lhd^o>DqcsWMx7gQg83~xP{FgG+whfwBvQHj3AsBpf_e~>yz2LwR&#@w;Vp?ibj_DS7$?cnK+p{uJG&OgL(>gjNS3K<6Q zjec#P_Y$fxF>gb%8HW|-(W`rId(eAdwG#jo$nlnYYKQQSdx8wtPQCE9$)TOW>cpf? zcRik%w=FSg``tj4+>F!Pe8N7aOMjf^-Rg*;Y+wWNC`$0EbR}_2Wjc5X_uchtnWyRG zz)fsvCC=?h?X7BFoqG+z+vDyAd^~S*s4h0PD>Q1D8B$>+V{`6Cbn2|JU8v2jZTq7S z%LK+gsQsZg$c(2iGC%Xm)!Xv!#^|=a`XxG|%iO&t-BxLCBhZ2&EUy`?+dHgwQideUvf2EXNzbX(P+w`@qaRhQl3^+S8RZ=grXv76Fu zMC6d7e~%tbw~Z*fv5W|hrQ2!-y=8N{O}yA? zPPYNewdV!+#J`GKPOY7*NaRyRX9FGHI+M86f;_p!R&}So+5!rx&=e$~PGF-msV8**ZoYtsgznp{0}Oww`=577HnD$>+>Yr^racUl|4{?n zWVnh(<6>-dH_7LSUC~-tpL#yjxi^{pf95*byIYCC!G8*Wv4E!>s`k&yILt}9ZzNI& zj&#(wyPMk;SlTP+b7gzrRggpR@f-!tjqWkxfIjleYh!=d6|Qo!_kxh2nO-yroCrck zD>Js$coeP09@{j5-~U#byBn;B{otLRty{W8eRcOJ%xq}~t#y~CIg=2apCCu^x&bm1 zfk&KG>^xAA!8c?Zi!Yp*^hoHw(HzJzn-h=x#u&hu`?JM*CP=Wn4C|+6u4{>T8;HcN z`e)IXeMj`H>~*bj|C`#0wkJB-nR5%@6y0JObCK~i3E4f5MV1^IBIOpf4c0T&cIz5)K{)hYxjpF@RL|s~TyAyNg!H$m>+hJePt7hn@qRV1_$6loI$P`LZiLU;OsdNp7|a%^4tJUO51xK+1xZuOpesCxNt zLd&1xBK0v&vWt!vzNvxNqNUKv#0l9ca}%kPbqlYEzwCdBSDyz9sc}BHy5eQzfMifBPHmD6U3Bq-=9y|v^rw0RIH!HO zbZE;jy11mB4rXW85e!5NICX2On+o-0rjW#`aw1d6l?`*;sRWYUb$lgt*v9dCi*>Gb zQsnn4JO3t0c&69M3G<_nc0?z&??`Bwq^a19Vgn2bzHB;^a9{M%*s`XZ7C!jfv~JK= zF|waXk{BQ;GMz4{;D=s|XXe#D=yLb=)Iy`&V#{6O=tR!$!Fmpw1D{z2> z1ZW{zo^{3Wv>+V)FDq~lcmfBW+2S5{GG9mDZb#mL*zEi53wjlM>X)Lpy;vr0$P9bR zJl649WACMOQFUJpU~XY8zOaQmH}w&=?~ATR*fy1fE#|)JsUavg z*O9C>#d*)TezL}ts!diJ%I@$*?VE;cl|?U#nrPJOAa5wl++jqn+lXA?NEu#Z#Y{~S z=em#C=OYUyzK^cz;;~o+Qjvvk83-e~be%c3bgkqQ?cqG=M6A^ zQ)(~4tJNAEHp^oN`9#ts_~@o>L0`zp^&oLFL4p@bZ;b^G^D0ly?V|)f5fL_%+dtls zl!&zQSm}krH)TJf2!;mw_F9db?{8XpS#jP z+PlCPmvVb0dGYNPo^YZ?h93b6_Yoi?I@kO5D*pd+}Zv<9nIddA4msSTD9qO&(x$?WZQjxR}K?|w$h2+;;7*NYJ4 ztlctMN%-0t5`iWy;6v9gBCpq=ZC4N7M3*ZWFh zY9+-pWPhe?i!rivpxl@_zStoZp=Ezgj|@dRY`;qO%iv07U6B1s2tnQ0zqyGB$*|0z z%{6&xl92;#sxsQG<+c=wCm{3s0253xrpO${X*!+ctWow(0rCRBKbi`YOb^DlhP6QR$A+m+q^GUjc+`|rld zb6<0E&jk{>=L593HG4}avMu%O5hwd6CJ-X&9oQUeUY~ywFVj7idL!H!LA%-C0BCNU z3&Pi0_$!4Uk>iIhPW@C~VMPad=ovUgIeuEe2_}$audj1Lk0nB|p1GZA`XAuoFIOC@>9#fn6>!`Bt;si4NX1zs?0#WfhV1O=PUgEt z8D-n27j`*re7cj(&eheS9w);$H$KN6&dFEcC4e_UCvJ0>o2zJR*ouR3_6Vy#?G*Nw z+GqTgA|&x)+b%`L*)QXxe=e-dOy+aM)JKzpsm31V+x$IxTW_}iW0X^gr1bv#goKClf#N-5VA z$Dwp9v>Cb}>=|p>|4JCLwk?Z{~j<(0rPIjn`&$p7cAtua3QB+YT)eilK2bwCP z$Ge7fT+igAi@5IlH*cXbcjV_kxupy|lR(GwU-O(xS9*<$<-#@Yf*;O8%%cE-GvQKB%g2>HnqDiwsVyE{G4`| ztKF0Bk=NQYpGW`iZO?qIB^lY5a8Eiq_u1)*%-4{Cr=7^|cK27w$eu*zlk?j%pIp$6 z6^v~0+`+W^nRL_YB+W=>mI!A`MCkbR#Yx(kc~Br-BJxrq((7b?B=eYv07j@pEAmn@ z^P`72lZ-%%AIdkNJ;}@}fvB{Fh9ojSGytk(kv2GPE|K|mo}bC~wTji8L}p2szVl0@ z)oG7xFfFi2W^;V7)&M1O{i+le0v%^WxqXYpSQw)-q0->vVPg2 ze}Qjnn7bj$;;HsQe|DoDOMCT_k>C7`9vdU8VIJ#S0F$pz8HL@4Q9VO7*1pJbKL>;C zUNRi=yq5HreLXhi|#$(0GpPm%Mbc{Lyvg zkFMs?6Snj4^bHq2JWP+hev}_?P*+H%GqB$KF4+4*;GV+jaJ44$6uJP}Rgn06(rtrG zH!!5v*I5!pwsCdmF9f@UO+~z{0TiVwfKj2O-t!mgZ24eW0oz~B^|boXbZB%p zrA~wvH2~HIwi_H|<&f6&1S-ZVothpew~yG9D#_l^$|)gEte+C1%J#925ylZRDSRjO zR^7tIj{Ay}dy(qs^`znRW%!Y40do&69BXPd3O!3=_0^S~L9$!NB=Qvh&a6wYb}ov z1TQbFpAf5UqP*vdaO{#g%=x6p7Cvw80uSPyJeKTzqY6exdnPDbdqJ#ub!1z<{quDe zQZ9DFHra2Vnx!I|hIBv>qn`=r9QB=;HYwMqZ8Q5g%k_dU6-YTId_n0EnOX>C09F~<=Z;9 z9IA#g0L20lHD85-D4a~vXqy4XTg4k65N{Og0mL8U4S&p0`Byl0mCqlNOTb3v^r(!n zu#>E^&X~tSrMg8ISyqXGC@*O>{zEy7Oovwa6*u`Ta`h*REJ9INC7yOe()|p|8oeOz{YV!WVyK5V?5BN%b&h`9Pwws+7}ATvhdz5hm%``z2imX+!rd zp_fVbt%L&P+qbB z61)W6FSgkrwL-`)>e8$MP14P&x2T#K&E45}0jMh*#6&1}L$$%ABX<(Y@+CQ`E0i)G zMK*YePE&iaCX{+wLXvu`HFTene@T@MJjR$^)85<@eYk;BM&D7Z@TJ(*;b?a9k<{we zV^QiQ-V?g9hmwg{FwEC`Yd^*kIVz*5H>dBdWzB`v-p_r`QX@j)MXR~g{_fwm-=PH<}Ppwwr1TW+c$|h>VlwD5BEqwOS*wa!6MUlO?9x5)n zyo}#OU(|Ov9UN~-{DQ9X^>uwwUtetX^>^{6bwOWtFvAYl=x07PpcB04E8num!zN@gsDFh5)WYjlHP7s|Nz5R2mxA(@=!?a8uNDln) zW@ym|SPmf(*lFz_@)}EjaDcofvbQuSu$Hh!*SATFZ}zSFawDzCu_vugWuPRj&Q$?l zT5r~MrXpuSJ0|?klprX)NygV zPp9uIeSLpnnZ6%Rj80D02qY$e<7YWexR3e$N4>9}9FC1g{XHX7^j6Y+p588e&ZLAA z0*j0X=58%8ZAN%BT4cI{_npdKxi3=$kI+^~Xr~p3zOun9oNN+fOIgpPUI{HQiQpS{+~usLlnDc;mRsdwR@87YPv(M5euq zMiuE%MBfzeCc@>?ulgN}a|YF<=DkSyB|kfl>*MbBC^eJO<|k0ri)#Etdc&viv0e`> z1VqYV`C8IZES8SK>F98K)Rc~nutyE)Xw9K&T2QSPM3+4K%UC)Q;xfgg7$V)`!_1C z<2677dB?c03PZ~uXzNdJDAu38In!5uKc3+!zxWZyy%_;|4etZ}ra2^wynx|Sgb3J> z2(sFgdQx_nB(?nz&7l5tOSEu9ed_Kx6`|$TTzGsKFq0EO&Jss^z1Gtavo?YrCDu&*X>=P zq@W1#o@n7>q$1uG>EciOUL$Dt@)OSMM_Gyo{?0me)SAjkbhqLwQrX&;j*aZ%$8_z- zlan?sd|G!>P3qOB>v3E3ZoQPZ_>bgGK($+(NSqhL?D5?kg5XXC;jsh|zqcO|yH|^* zDT>FGqq-SoQR?u6P6X(xy(?)tqF2lY7>f7sM*9XBKy$EEkl4OE!83VThIhL0oW{haAhH2j96L1m8)7rI29p6w0S>qDeK?Py>u?_jQp)ysw6)SuQ z8^J{8W&18+F#`#j)OQ%fZ&$wI_RUQ9?x2WI6MFOC|NLgn_y(&beDLDBFQ^g3bHyo~ ztus}gHkaq*Uz+YW@E@-)HqcT2<{^G=moR+Gq;hb_TaR~Fg_d6km*Zs~aXxXlP@p<{ zsJ>%5NhcKQIwvHNbh<-@%_Al+BzKj@wwP*x?42j1%UaRhiOjJ4%bz1Zak+d6j|7Uh z94^XV8|0yrj)ayQ&qke%uHqCgzVQCNmoP8p$qu@>J^x<1i<8``VD=+8(V>+$HBOXs zmwUFlX1C6Mw0QI}j+~m^PBwbPLES}3znoCTcMCvyB3pZzs$sJiRujJFH_|X3dzqo4 zx&|p7art{iF3aUAa}2~reZWQH{fHLjb`6%kgzzFhfpX8i$#|^%_tzWx&yl11>0*g$EA+O&(*jX^ ztS(|AqC0f^bw!Hvg8wiRnglzE%w(=qiqyp&?b*duREwTS5V9xSLV}v;Paw`P_unuI z?$FUs!*W0s^NH3whPXpS!|SqRpd&$N44Tkm#)QKwg-FZLK?-|V&Ebd1%vE<@lgPGL z=l?~Hx9m9>4r;Vp&=GFN-*Osq<61I;kXjM@d|P6fnAhE_=!+lnUo@9>1IoD@^Z%VM zjDYL0INwff>QhKYnSNy8WmYy?zd z4I_}^56RZJu+(dSUp*k&I$M6&StP}C4qmd+;j*}hJns6(ffL#(K|Bp8)-uu#t=+6bzJ_!9C z78wBNS>R+leUU8r*Kb$utn^a$TrR!jVP!K48yyy6NF5$j9uW#8T?62lQfCbSeWHg> zrkcL_BsXy3MIxlCgZs#$2(Eb35WJP%<^SYbpWrd4NboQLB|K`Dr@+d9m6%E8FFDyc zgmu3P-LDyBzJC&V1U5Rprm~Z1F2YBht@%Rkhm{?#q6bmHS$tWnWN4Y0>EYh6z=@E( z;*ZO8sPS!!nfH$Ka{XdW3IpJ-3yqTakEf?nYz?b=UUy04yss|HwRh zV}9CaH=D}-G6!8eU+pDZe&l%1({wG|WFnGK-L=p-Q5UM4+z=WSZQy&D?_s{T^1YSs z)A>G~?{oP+m%k7ux*$~djU~J^G%92M)ZO=>`L@*jsr$x5_BZ_@0n`yBX;>%Fl!HXQ zllt16ijKJBUW=!&kxNJe1Tp8I*?mbxe$4fUNp(&oGv3u%BX$nMx1=tT?i4IgkK@jq zlPGj0m;{`!k{hclEN#tYhM$%Hln$B8v-3Zj>UDbPm*Yj2M%ttERVYbLf%<-fa_<*$ zvsZ>GcL^;EFkDXRs|{4-pWrE4DQz9B++lJsTl1YKa47O!HC!ZS{!d-)&YVxp{X<-x zbg!#dF))YXQ4}e&f~U-p(;_Xd94+>UR69&81ZHM~;mB$<&#c8SYMY0V4iN=>AV3M3Dmahr&L0Gs&OI&hrM!_s0Cck|Z-E z`Fr!aIw$f?O9uPLb*i0+tKK*n^9OkkQqn)AUTGIe98Hz~rv8)*d#fndT9}Du;}@JD z9%CMCdK57Pa>lz4>B)ZobRl;+%x_}NPS(VcQc-VKe2m`orcIF1`&L;n;OWCY{PXp= z&p+d*oSJ|38kP7q`De*+k61q$z(44lGx5)6kAEJ2oBZ==iGMcde}PdOjDP-l+S})! ze~$DI!UeADue`6GLwVKuBHhRNL)TC^KeVpzd) zkmZL&qz68OA&J?=8AiIqW`;)!Bz^5GU@g|IMDRSGDr2Bvqqx*?&_~2UD=Y`SQO-d& zf8I95FbxY9Ay7@dKY_}gf;akDULR)fE*4n#=4xGNZ!iU0M^&)(BYK^1_u$XuoAHsO zt7K#o-ECnaO@&qyw-aAxoge29Ifo00Oq&#DXqoU23HkIy_J$VDRs%n_=!BFH-y0H{ z%MzKdkOaM_zM$!Rw*a@bIbDaUbm8$QALjmwCC}cUe+AnT4c~GjryX79m|qg^J#)Ag zSNQmox@t35g+Cqge!G4SV3h+TU4F^G^tq&sOXk4aj;=Y5+FIPeb9i2U*}&@>xURv! zF6>=*)4=P(To?AQYxS<1Xs5W zFZ&<4#*_W{5gU2z)*@c16X%8QSL!Cg9A&`KR&pc5TOb|pV)miF+>=YkiDndyY$i%t`TU1#%)rL7 z&K@J67g5=0$G@L^g3KjCNliq0-OT>mfH35??fn^Qsv??h4SnzlN(5(~$Jy0t7E@tK zn{Q_FCO_)zOf#+1{=%v<{IZ%~Msm{>%>wN*H*M1|n%=2XGiyrE%9}f=PpQ!jBL?1} zQ!|GTa>H=lP(APlotmkE@mgDaLzQk|<+x&#)E<4GIg~~Wa>G#F5G=dF>w`|s3=DEZ zKsT_cRoNS&+wx2aRwucK6(UfG=Em3vf^{>AIAGc-FRyyrL7GH@4b@o&nYYf2E5c^| zhCQa#C@N_rbr`x&i>M^BiGq>WK#vnxot)I8ndKWoDMf?!{2Fsoli*WN=p<9MrI(RF zoCM%Edbu^w^YpcO!ztjrwcyDsZ zk3u(Y(S`aaS;@cm&KlC?U9p#Qvnu(Q>p&>&k9(7ob}syZ=_^oO^}?1zsH*qyijT^RHkxn=lylradq{sG ze`W+aGQ(kNlJPzxON|weM5hDRV-X1Mj6Wm0%n_iAG0A#}%GWW;4VdJ#9>#GK@%LzZ zDM95)99Jv*RBP=t&&vPD?6P`lFY2mO>tUtE$h^Nsi{!mQn1fBbWG8tY{Av?S1@1&1 z>Q0g)$}#@&93dp!4}2=i0dheg76zAGIK^ouZ#VRN8wt@^JudpwFRP)c{cozC#BHAg z$Q@STmjBRX!W%-H^ZGp}LzOj70Yx=HYf1N6Gif*pzLh(`@*@XI)(?49mBEmiCyS$6oy^TmwnsM)(j(}B zYeMP07c_qTd5HOYBh z$-w#tLn}uR{v@>W*p!`=dyy~ZdkxD@ob{RL_{52G^O!f!$z#yBXVIscp40W4K4D$Y z;xVTu7LS3V=i)K7=jJgK=%_XA*+k>p7~z3@LC21qn-;yCUS6)Nljq;{M7jKV*FQ_7Yp#!dPYyOWd@rd5 zOjW0fvw4?+gz#~^Y;V`$pv$J>!P{+^(@=Zzno{! zs-~xAL&DucY{QBHbSMtoQkDM%tvoa||CdA! z!k$jO#yY=F^j1kXYpt_N`cQpm@$+Hn>&OatSz1vL{cuNPy;<4H)D{YBX+;U-r+w7Z zp3CgaefJ6ax0s&w@^=9k4-0PQo~LwXYiK2$60M|fx&3tSb#{rUi`5|J(INa{wJTW% zz?buJ<2lK#UmYgOWEY%>)f|zDZsPP%LmL>Sij%-L>0fh`mZg>(+5PJ7?8NoVk2Hpc zjDn2EgQ1nPd0;!j7w7GD&=^ARgV1piT6B&F%)dOlj=dLZdW6z&7SDryvZ`x(IEL6x zYF%|SvI%liRf_S-Z?D!2R6s#y2x|A0MiLF_0AG}1m{MsDAf|RT&@Z@7IuM!7f#@7d ze?1UOFM`->fP4?bwbv77(sK1c$vtEKct=y}^i z?)*H}*z5lAzY5Mgb|71}^r5xUibNn+zzJc!o?%no9Z*1ozsp1oroD{Oe{bC6;X zv2S}Yw6c@eF~Ib{l0*%0l|&RSt~ruBP~;n42H)sk@lDMM45(omQ5mj=WANM7Rl~Q9 z`Qh{cacfYCSv0bltx$~Mv0X|!z{Gl&O#}j#X*>ZO;<9h0SVn)1VDi@p=1jvYHc|IS z@Jg(>CWvJg8T~NDq;Sh_x&sH`M{c7J9L6i@o9WAe`kE6)1zQ<7LFY_&)Ns?CBeYxH zk&*%Sr|tBwG2e=ZO(z;y(~Ai()N{fPuwp#2-U;ksoy{uVTy^J7u;WLs{x8x%EEKV9 zX_wEAq&KJ$=U=nga&_sj&K}Zb`+NEVE>hR+HI@jhZCRh5Nr(CWxGkqtV6S}00+vU5 z-RWNQ8U%^Do7i4~jYDz=>%d2unN!b#AuP&PZ8iqh$!FMJg*T09j-~5jX{R!lUQ9__ zYao45G@Wd$jHf#q2~p%VLfj=#QQo7Ek*@iRT(ly?=Wae<;q!SuxA6HRKG*TNgzkp; z4CPb7=lGgv#UVa>`8>fV=3X01y4zxr;g|sylhQ6L`8w2P7hmXdbZM6=!$K>2s6DA) znyY|$(D%8iZtOm1sAlBF1F=7M;*r=l9FFeeXmV>jBK5)(dUzI(8mdPyd%QmC&brUh zFM(O#Ao+#w&{KRQSMjuHgkSiX%OZcoZa-|gLYp2L{5iS7o|7B+oR(OG4S;_8_DmeC zJzk$gEYn4Gt-N1@v?qLy+H>V#?J1-4+0v)!9JQzM9ks^{xg9ib+}Q>3oQ&6)chsJN z{8N99+QY_G=Y*f@25XNmTc_f~LF9`qtjQNqZ2Rf$b?{i?dZv zi19gT4{GHdv}d4tLd~6%_Mmp(L3;+u3})b*v=cGNj5d+&( z#)qd;Pm^NyW%N3mQv1=MAT&s42wd1DYSxu%DhQD=ta_SKmn zN?!s@bKuWVVxR>aOe+THI_t&eJNU6f-t&U|KfF#{$ANMDqs)uLdtvFWsg>5}OHXC@ ziD?0@=62h>5KTrcni<2~H&s0uOjZkq zmlod!aS?x1518Nf5AXAUilH}+E8^I#swVr9hTq+<<)Bw_XyzbOt^pIpBgYkUhDl>w ztWm9uyBj#3s)Wb1VP<2^n=9CO8#n_NQKDt)khr@C7K!GbB_7?)PdW*Vvpbfi>{eff z3c>+_)^U~lI(HtZt9dO(;K8JeH3}DTCn!t&xNwB(So)^MNh)K!n)^S&-#=_k-_>}H zCXhX2+D)vSY<`~Tp_>Pq`L>0}n7a5G0#}Pte2BS^F~|id<(4YE?9IGvlF*J;f@q zMn;giswS_HI^}dKe?1G5MjoF1&*RL{$J{@rjEW`TN10ZzOwR5or2+2i?+fuCD^$lK zTS&Q3XT)~y%wSWqB5OiF>4`=5Ao#J!R&(DFZhBvY|F}FGRI;eTzaDsK&HD<>S?2^y zzy(ovDzZ8=EE^n7VI0?H+JgBnUV_H)s&Y(?_|2T4F+wRxbWG!0 z%xzO_=U%im&#U#I$d&-D?NS?gXP5U*c1W$(E4$cx-fLr76V281h$n-Hnr`LjmU`8b z>kX=nq66AzUl8RT>B$VsTo1vNJ1;{st$fuPD6m|}8lXcy`d&{D+qI^J-D!655`F^_ z1Ox=}giV8uNKprYc4#GApK~JF$i}75BSuH8#Kanb<^<^QTdXkv@Z=v`{O^Q0KMdJn zTxwn`frm%Y^AcnsIYI}2!(U?+`a*<#>Zyefw!462?G%Q=(?SU?ET~3Ue9%B&78`-! zI}JoQm+xRJkLw}>5pt0bAM8S8Gm8IK$=}@kzh0pcq*NBrPiWz-K1GalM+{JCVZk9j zP-rnk;2wZNNe4ioIRFr<0x<-o_R+#tG^2JtkW856;tfo=2gKkMFyYX@`=AdKE?Kr) zFkx2_CbXca5BaG}_ShnzIxfP52B_|f4tfCN7TqS8aHps+OS@G(CSm|W8G1nC{NFV7 zBgs1_MelEfb9g|hM*OHh;;d57?go%@T{$Xj=9k6E*D^E$`k1;Te2-Q!=nSR-^vt*$ zd{5)0Ic*( zA8|K8pGF#4K3LCK1KFg(_`Dt&C_bR^)&hN@<>ljDM2XoYzzq9-x(*kU8Kh6~O2f=| zli%Kkb@&3XA3Z?4_{sE7P@g2rfR$FP@^r&=&=ag)L#7xe@K)o$Xglb+FqS$Qk8A?? z6Z{w010F3D`qSh?uW2f>*AIO5@~}Lxaqq~&eMWnka|Z4+;FrC|9D10bAsi@a`Z}!G zt1J>6Pfx^#8SCM0&h^$Y2Re5UY|lgbHi7g3@v#d7Coxu_dCA5hajaJ$j^zwSIX6@= zAI?;)5khO?fE)>xK$@M@ZeDZSgTLGnt@uBD{*ljj`Fx8{nh#6DS1janA$=Rcr?4wp z@iL#oe4gX;B%iH(Y-P#d^(F2MwCZa_*~Z3jd^8%#85_j5#K!ud!;N@Jm9QM(Zp>nJ|+I&)4-jLxRknF;CDLl$1SV@9gEy(f3W!FXR&V`;7`}=wfV2 z7>hh1C&JwrX{${_gr1<9=C`KUymQ#7M6UNzI;(~a-l(>^$P?@>&Hs_>N1KI@de~Pw zsJ1Y%1Zs&?hEDX`CxPj(nq4B*==&II&J@WcvYInRG6|tIXG&zU1U96CM21u*{nAGG z|3sXLz@}YeXqOtrEIhAWY7}i#do+YJ%?!=&zFiF^YBj#2R%sLlrIa|%bjxG2w?nO_ za%x@qj@o4z{uFI{r|k+yo`AE=7*2c_TjdL`&sP$HGTs6jDDl?S?_#^uj{a>cYgcQD zTCsPdRef~BDJ9V{N^2v+h=xegE~L=c5Js6=`Lnaoin9K@m&EBMYR!5#sD%uiS#MoG z$56|v_?zB=iuc*0WOIs^=pEagwz(xz-THe&sJ3B>7B8wo+^LHlp)e!$T{hg)~ zwXS>@c}qm=&tGLeYePA;8sAa7`f7-xyYpMdk0ol2c}J~!n@0TXI3DP|6nTt(NA2oM zEi*D_pp-v)>XEM@& zkU?R9+(rP>GeH3*ui7VEKO~2syFZdMcwiKHf)~1L1WK(jpcILcK$o&DNU5akTLgLe=1-s@~!&^;$k}4 z2Nu(bKGBIz3;@L{x%wNZaIx^eRpK-^qhUx(AHVeNMmt&`go%yV)_=u2epdwRwip5 zzhfGmm8=a8Xno%Uw2T3^fEKyGQy^NWqTV^z<_pUG_TLNY!C@sEd`cY4Bhb6zryzx; z*yi^_3ei+08vWLqsw9PCuXpAZpv_A(`n}NRSiF)AJ{@Lt4rQ&MZIQMpYN@w@R-MBZ zonD*cIhAO1I;84cwCJpKC*I}hFedqxK|;p2>`M5Z&?}ac$L9ROqY^giRdQc?(E+NfN zO>0yijA*Go*pzu!pQ$+5jQ60$!HxOjJIsU`ZwUY@f+?M4-v7*?2HUR-rtGsmq zzqINgmg)Ruy!l|Jb4`BDHe=f2*=dEywnU(y^&3*JRo(fu#5@)#cwkv=jkMIGg?(`K zRHi3vj?z5ukj}+w5M6U#)zHN+=IBOUZYD8!7npe-{>7T}VUA;w_?nt6k=eiG?TNrM zhc2*(I?Y$pm`{3*xzcY8JZ`4o_@(U3#_>zpIkXE}*i|kh;-@Q$cjKFROX@^J=Lj@} zd$jjrG#X3Pb=JhF8F!ELY8L|7;f zivfWE$P{ZnS(cLZ|z_0pESI-)G)ZBBd-)}lQYb09;@w}J)-*l5s%^LZN_e1GLFPEJ^UVeiv zoi*}RbHnknma*kv=V7<=SbWmqQ0m95_|$s?yv1H+g-l#q%*8Z2|r)Y5s7e_<1#1r!vG2H9p=}0v9qU?Dz zy(q{Lf5<~yeH%|NVj}|7E!VQp6zeoG#ql$Tumnrj$||rqHyiaV8#cLOF`qm5e3s7~ zKG*U2Lp~Gu1gj=jyw2Yve4gjCm(LD98~FT^&;Dw@^XcL9b3Q-j^FR4~o6iG$mW`NP z@l`%wnOyhVpt94&IDLo*wxw3OLU<7U)sVAB}fLA#n+e(j^iV+v~uAR7{} z^`@OQUF}Vpu4B%$ew)Z7Qq7t&v!~69W?W(BOqHY?-r^6h}9$TNFz==twkGL%Oc79~b(*0VB*4@D55zW5e%Fp}H zk4CokInU)hWNWXUVWxoQ0*~ksJzDH2^2pMCcHZeDyqvV@pjYzpiVBpxMVIc=R?F(uo@mXU_u*NFlG#uE`=4J@@nGui6KJ5_?i(E;rZrzmQAX~- zrMW{x4%P7W54PrW2mWB|A!az&yb)dctZrO-K>sq&IO;yBK6J6_7Ms)UyN0S1?FOzr z#CzTck5}5sk4;;G8c0$v@b7 z*itZ7^NdGJce|w^rOIkA^Ru9!`^K4Qc&tRlzC=7T4H-ARa&M)|`36vtk<`cygNo47 zqoPJeWQU9wmdMDIUXP5FWEiSJPA+}>bmX?o_0KM}?=5{^9O&+HpZ2M@*;23jjQnRf!muAlW!$IpXJEdamTvB*fnh7S(RtMQecbu2oD~=Q2{lDy;4}4U`wfF-G5J+I71PqEAHEJ|!qgO46 zw%M>3HjrpkP<*1&r?psVOKYN7LBRygdb5fZtG2Y-*0%bzRa*)n{%Hb8g8UU!K&|5c ziBXCF5b)3bzUR!n%O*fYi|uRQj}JFHckaxYGv}O{Idf*_%sbuN`!sJv)THsglhu;- zg0^;F@Hkdi^LUO5bQ7(fM)ER3*IM=@zJ8Z7iPYB9i;B{2xynuY4ce{9B>j@KTOuVW zl*9TDCyp$-7X#J%~69L&6svO=e9Hi$BH#?H`$E=t4C%HzKucon!gqq$pMQ2BeUwY5xZISx`T@M+w}Mw z*Psam+U`rV-3>r)Ubb)Z69 zb4DloA)^TXayNT}(m3g!Q`b$L5^6|(!VFnN%1;=V*%IU@oMD6fgnQT^KVf{VO9Fnv zIPjKWFG`Z}tE>N$mwl_*uKb@o59xO4|3vN>_5GjROOPSqv~H0&4lMDq$>aM#A%p`I zIqNQ=bU8V!p`-(pUJN~I7nAS)j1d2%DLzo%TWp<%$f!Np_kn`0WPPBBGZY=qtHdjW zc&_Yy0`|A`2& z`ar2zZGOB^ELIf99!?J!SooOXk9}%~QglKt80%!geOm({@Qw!Z>fB9uK%q{iZtPpu z|49#XTnPUsCr1-4iADI}0WshI3FN~42`6nAx^=xMN#xvCNCe#$AyRG2V64pJ@c ziS)LL2X`^PmWAB)=7E;au20oi04na+HTw9pCuY60LL0_ zmwmJnQDm=eeZh2zWFm9BlssdxV3EAnQsxr!Pv;Y<{>HN`ny@8hQt=) zQ;iYHeyQ%%URy!7V;tD7vZ6R zNeVuzCW+6gNd;5HHa9_h7fmNYsP+>{R`g!zKzY^fZXv%A?lhc0tl-yn<8q(zWIAcv zZ|}S>w=9&byXelJiq#j?0zDeHNzIB^p`8tf=2`LDMb}=d8IkH_?`}aUrKKq-scp~S zONIaMckunCgBO1v(!u`|Yy2FuoUg9NpWE~IquPP!h%}5#4g(X^HJ0^?g-X`cR?_7`?EpMaO(P?>)%xFjlF>75zHLlQTJ)net-)#F8;kD93R`OJT~^P z&2Oe-cy1|=P2=K3cU^4k?{W8A61wSD6nsRcL^OsdPEjx_&nZ|7oi#5* z)B}kmRp}EqJ|(J2Xh`kJVnitMwTBH6Ztl4D9VT01ITmxWw1`mcnN0g!@3ruZS1EY< zv_9d)@^H=aE#buC1(_sZ;@a@aqls|Q@>s>47te|mJrSFB8-vGhurlAqCC01pjDlB` z*m*xUIWNOX_xG6p%F{cXHE6n#cqMlSVq3a;IQrzoL&U_qD)ADd%ZNl-0`DRl^T1HU zI$AYte`EMdzS-belEpfY3vw{;OlHsA{(@oa=VEETts?#1vh;Vw(kwxV=2a0oTM()X z5Q>6}czVhcA84{pH67_PVk0{EEl2H+It$77dZ`ddhy(ywd&1x@DWcj0LYXw}Aj(u5B zCgDcvLhYJD^R_j=p^nCz{oh6UOF_?Zld_Eu=NYMc8>PM5$MQ!#&7!H2n!}WEa~;_G;%w zwvh_>4TwgTd?QG^yxL}YqjQ!mow6j~xM~0_5O5Y%ypO})i*1_%fzJwiiLm#4+Y3Y> zrpTw)qO$sT<=*%5?;=RHWgz(k&=t{I7i*iL2@uE;X&04}aGuKl>)v_y&3sO^OBH&N zf06n~-Ly9%b>D8^wdnUib7#=2U9qF&i|q2Giaw(3afOx$8`7z=k35q|1qXI9=>_$8vV>`P2%(f5`iyhu8_xBCVyKwz#h;5y4n|IME#{pW2YacAl8 zB=xiaBtA=+?MuH%U9ts;B-&QsOuMZty(8j$`{yc*cxoGP-QO57yk@Wd+SWiEwOx7vf_5 zT;VWt*4u+wFW_0r)5`NG&jUQa;<=UQ()~-*zQuDkPX*6No|Acw#sn^THWx@&x?Jk~eGGwPaZzBw6$yI0lc+O&?it|vpYf8EY z)+XpqxJH6|QslimHh5XBz^z~=!&__l zW!#C4*6gc^I2Bovn_3E_2Z$7u*;yW;Q91{tjgKiP=e2_0(_}XL3bhhdA8($>LRCSr zPGi4a;jPq3R)x2i*{qqc!QXo!;AQj0PQWu?5%-;=Z9!6oopureE1lv-3QkKru6QdR zzAMkDPG!HDI+eXbbxplx0RnIZ7xUR>x2~TGC)c&9#vW#NWD6t2d{(p!JC}vtGP>8n zfVxwe({jCBOq{nel@qc2(Q0^%=-x%$S)sAl(E2{u0_j-3+}_{!`YM$NeA`7mTvpcQ z&`Xo2u1TtAmj(P&v$jHX{>cz96mc5 zzaK6q5)G>XVS3uqqh60kmizKPvkAJ$g`%;FDdEN(Udm(f>HLI;tsx{+#|m#fA<>E> zp;IMNT0TE_@uQAx9#p$VC!tE2HVN-hq4t2JEHMEtkpuDem(WBL7Phoq7(#GLV<2WjLMy)#xvhpn1= z7o``3PVWAr(-kpjuwW5iZDc@od@Z0McAZoU8|Kcxc**8vy8WAu4 z2tS@Cjd(MKwBD_A?nL<`$aQ;ms6Q^DWFIt36KxTS>4X zmR;b*@8%nudenC8yIK_!OtFOBtoK}Jt`^Mi94UCDGxvT$h~GJa5b+iPZwbBLW|}{c zIkqj1OM^h3_Nx(~GUdZk?s|_X%xJvF5zjoD7~##mT|m-*cz4f{+C<}hbNJvqGDC`V z9(l-CIT3a~3p<~9Ef_g6Eqn@F74d5C(EPZ2%+u9427BbJ$MUBiO?Z#gX=ZPsr>z0+ zhJPVi2|PQXw6qP4nL_{)Un}7F{fX2N(%&FR;j~oD`VJljpQMw|mJSR=zXP;V?~yws zX?c9`Uw{DqCsaz=wLg`zN5!-MAhAyEv9=zyj=-an9^$mH0r^H-S`&SHws;4PpVFVq z+yXels~>8a{!GNfx25wGBwoVU!Oh^gGXt)su)a-7EB6n_ zQ=2=r)Fq`({Ygq>7A=ZdAZ7t6llqJg&0CG$#e}g|Glrd79}w?KhT0((nOX~oagO1# zijoVpPzs}v>jgB05AlD82{KN3L8f}X&GepxW6emWx-=z>lnMf_H%CjQDkGga4@hQy zua^Q(^=sfdFGvlGS>9E|TxWxLtHkt`Co9Tw;VRmX!Yz*yri zREr`EHRbXB|3DHk!4)Ep3Xy8uVyjy32?kWBMlymvE(9=7%Kb*pDhAllymu8?hqf^( zM*?|zbTAd5k~!Yv!!;sWb+(AwLIDl4ZdFVd;p($Io*Nh8h`IHoZXq>usoNzpbZOw# zsc(?Xf=3>6aHoEzMa`X%q^AzN}ajK2_BY;!glQ-Y#?vAH%H+`yp6(fWN41U z1E(7$7YO}Spo|d2_!UIhhru0z@oeQ~#5tMju84< zt&c*Zovjv`2I6dignZWfkZT1OARa8gv^X8cfauiEl@u{|iwI&gK3F@r;a;td2xK@& zK7-OB0#N+c(p^7pLG^__au}9fmf?&JBMMZH-lko{wKa5`c$h zP_B?s@m)$sFWr{c%qVGv3bmh#vY-_4mTIr1G{Y*bB1Ki}CF@9UcD)c{q%&JVyUy&{ zg82w%_961iK@h+oTw@Ay5UVGwejJ*&MRciv4-(3gSpu7k2J~3xMVL)%-8!G|yfc<<3;b*PXMSk1%Le75sp&{Jt+b6dpAE`Zq0 z2%sIbT5zjUyi&TfI|Z;;tNpxFJJgb%U#U^;Nh(hcmZlPKk$fdBW4#VucyRIR=i3B} z;ofcXG3-2E>dn?zhSk4HRLqsj=<;M-(rPlGN;S2sYlQ+)@YF^Hoqw@{u5q@-Wws8y zR5^pH77I|a0d&5A34lAK0#hjB#j_LM$O4={Pidx0dfZ8)IW9MVyyNFec)>9C0p!!`@L4mL!* z4U|lY_0y#;D3I)LdoxFTd%T$!bH@jI6GO|R((SNkgXVC`=4Fp2=oVDLh`AS)dRAUy z?gS80rnC5+K}E-rN|g%2lQI18`FfR!NWmmNDNE5kmD4f|k?bNgpcYY7frTCgR)Nrx zK}Cl|6BRBMiMi8lCjwlO@@Xn%s7%M)T9Lb;Qv%78r0OxZj_49PI~9aL6;pjlB!Rmh zmeb>)Z@_?vCs(D?a>LDU=UJLVHY^U>-CFGo<>2)vgdX(|2nqmFz!acL8|ABX$K2a- zHcyY1R9=8CbAXLj{TkuTRuzSkRYh_u!x)rUh;KrYREc4GaVu)X!&d(5e zkeu9F#*c2@|Ad1e4GfLzA_3t`sgQwI3O-g;^RH;Z$VFE!qArE)y@*MVr~cH6rBAD zUxe#G4+aQYT_$;^=$CGm;%|-exz4)BWHjD$`AAbLRxD)p2Uaon6R6chC-w)Cb)htE zPsUQO_Bvari0X|}R?MX{tu40MGDY+l_f=6P`jis^k0-kREx-7sDBe}KQ^hDxWL=;= z>vto8QsmKplVABfTTKyk(N-sNo|d+c1eH)VRf_=SR&s%jEZoZ2$+=!;X97yQH-*X6 zMAM@CtB%S5XB9W^epMQg6pmU=W_dWOB~dcdgM7h&sS2f`!)<^G+J!}&!37M;2MKBH z6hR~nV?_Lv5s#}-sD=`WRo=O(`&<+%-fFZSF=9Jk4F7dvjN<1SBrKi+d!^L>ctKIORU z9rt<1-RQWlCcmHTv0@h+UIL0aV36s!Z#iy<<9gp)&>O3%%8+&sq}?6~=kTaf%d#&Zk#KF)KGa@=Ca zJ>GGLIPS^G@8dnUgzpo;2^IWt&|>bh*jbcJaFORmNHCFM&~c*?e7eD%FaG(9GKpZ(n z_#bee{kKa>)6U_k;2FVl63;O_2lMR5(^guV_9D;IJga$@@I1`(AkY8s$YKvW{;K3W z9X@tz8mH57qJEs5K{C^tEf*YQ8Y3i=t-l zv{oR4sj+o?trVcRU@9F~gxzw~_+22>sa|6Ogm$c#A|y4d+y$UcH7gGQ?N~Fx>5S;^ z){8n(g%YWrUpML!food7-RIcJ0YW?0%;(sU&#jk$2Bm>;q*1T*Pm&%k`fe1k2ku&O0_e*lTiCzqBr`epeIiD z_u5VG$a`3+Ne&Cc8-090oSoI`S?|m*)aFy##r9fp%Q>zx7dpc~zZ3FC zM*?(qR;!ZT-wn$`L2 z=;a*1W%*{Zt~2-tjO55@H;Kq3z@_2p0iw!J!Oh}gu;z=NE0QE!`Fffhh5CD^Mo(mO zTiYtCA%}{-y6XIX>z=F5=bjikRyOSI)>%=J5gqSR&WqZ^q8Ih zdr;W#y)4&mHxSfqhq@KQ=&@0`2cBc1DiQdnCOk5Om(#e?8YBOCtoMn#j8^MBV`O)i z{cRgF@sPki-1U4?Q6VTBRfot+4^EXbBD}LY-E9CsBo*iYm(0uxl zY`K*Jy+zOvQ~O%lU&Lzx*bw57F+x&yO1ZKD_hj9=P2d#8gupjAJqjAbWUKHu{Y|$+ zj_b$y(c`0uCHDO2+rjx!p&JKCG0iXHFlahuBK5XB6?@rnP9Q@|kww$yP008)J>9ws zXbK~HxOF3Y+0&y~%*DW$@mo0f`Nu~CeP@#IAH{cqdGXyo|MfJ!oEh~N7-jc{sCRFN zgl0BXePc;&=4!&-q6zlIZppc9-{_2Hi3m63NRsr{@}eeZjT!X-XLs0?7QaP4a;DUc zhjS8aimPeT_h*PoJl(j(ew2QV@4li z9WMOr9o9|WtV@>ewLQrGWZC-N6p77{0x4JO5}G$^AJPq!O@gfi1_Xgz4aB^~Hqm~3 z+c)?&Co+;qt5M6{)5Bd_w0qql=uei~XpY)om638}xDVzo>6_0xb~DgJD1=YIdMea=0!5eRH=F86+AIrpaQokzyT1WbBN zm{eZ0Ihww*Y}gAwI*7aBxLwv%IdV4t4*t3Vcdm&;Csa5t3o(7e;} zJp}t-!W9vn4g+bJvxw3I5lXi|J@5dO9FAnoQceey`eV{+-hB^6*Jh%T@Kr~gx^x|H za0Vs6T-X8(6*{ET{UM&oxhQPFbrO`M+f z7YAT+O1pvsRS$Q=iAE%TTDOp#f2WVQBmB{}NYS%$lZuAf%uWaV06TBFS(x4POL2z7 z#(<*M_BHOzrQ!Gt0T2$AHHTwq-tf$i)`#Xdg<~Zd-tded%wp=9*+HSv)I$HU@=CI6 zKFh2+$Q!;TTEk(MSV>M|i8nl#KyF!0Q(nzyy+ieV8Na-W4A0F>YB+f!3i&ZN!<#AX zEmo1~#iez|X6oO#M2g(xEVBI>Jwmtg_!*hyc>EA{$GVF^gtMAr-T4&mZX-)GLwPa^wDq=d@)Y2;vu3`yi*_9Vtj^R53n*W+}>YS;U(Pw>do{8DfHo`|24jlJEOUxNL zep)W6!NQ z;3PI$v#DEX=Bd(l=IV*Ca&NZ!8<3_`So7Hy>p~;Gb9caftACeVf9V+iPhWpIob#xA zYAx#jufJG#!vEImFR%Y5x&D%Ko-dC78S5{vol}~&foBEJ5}rn$Kl1#V=jS|^(E2Xm z8Ou}2GlFLrPchGtJifjVtiQ;q#r%lZr`&ti8|reR^@nzf;JpwDJBBo=qpRB!S#9QMQJsD2FDx)kuI>YtO&E{kJIfNF4<}VR2DS2Bp zFJ@0sZzS&%ZqYJS3#Kg&n{wu__rlpM&A6cl7D+BPwn&LM2cX0zUTmPfw`}1lYI2Jf zc|Xhnn9~yRUI?c*k(2`0yBx&>S+?lUe@=6-FHELhQsA?Zq8B1X>#@VS9NTeP!rsRm z8F4;lG+N}HlZ(qRAgo4r5eN%`z@{S#?+oEN@0@(%(yzoO8)hV)&-uz_19EcTR!EvHm1CPFj3Zb1l_esRW7?E%Sa@2#tW`y#T`L&19pNRB|t& zu~f0ho)Kx!@SZJtp=f<1eVOY#8DVSZ$6@EWu(L%gcNCt}y6|KD&MP-WD_1P()60&h ze(FKIbNVDb7va6P&Bs zUC!MxosLNBH^nk<>TWadj#|x1Yy5&O@1Z))_zyR}JLKf%?sD;t+x?0znC0h6kIBKr z-Dc+u#CRdi^)7R;@vD0(Mb9# z&Mq^SFqG`Yu^k;qiddJVH)~H17p>80ZP98q-HUe4q;UQsW>`5)MVZsFtFWg4&1!XH zr)G$EfczArfsFrM{6Q|5rL!o#$^=&l;Zz4>GoQP1-*8Jt0rLX&XgNXcDd&edcaK*H zhUif3S8MH`!Zi1^qG6b}~hj3bA{ta-n8VF`f_zto>8{6#qJF z|L#=hoXvZ#I(yjK&wUiuH=Vi&v$p;p-{?=mdlc8F+WM`5U#$AR*&o4@Iea1Je>MAK zvlf#+BGxzD;^J17wUn9Yn!8*85Z_?ZA^yu20iL69aiW&G2+(B#V9p2s?h62x#^QEE z7Xm)6hrKn6D}!ylNl$Us0J$^!W8kww>{}c!-f%v*rHAHSi9JpZYy2>~%rjv;4j>0O zSQ4KCB<#aIA`(fAjlf^HzKQ9JTSQzBcU|Frt`nW2UI;jF?YL9rq)7*50C*To*2S(bNf$+dpw+LX-bue@sJ$V{*q-c9O(%lp^$)}Z0( z8Wqif5F+Uk`5XE3M4)`oL6dz3jzIo(a>eA&Le zD|3d}>YV&<${gFL(SB^VR%~l?{C@~@3T<_c`Zr}xmu@ZJ)`rcL{}C-G&sJx!GDqw< zfr`RD{#_{qfr4k1Jyr7lmy9_%wl=x{rpyUcH3z+1v^5keQ3$gCGg?lXtxd+ijyYoD zDMX)^O$khrW$hxV3oy%2jkd0;AS=xFv=A>IBArPa1vx60S?=+r^v}t_1z{xJT}@p%OV9mlixFwpL@%`oGKh)S{Qu+1iZ%4`I#( zTb+xPIsf+4$%(c$oK*X_oa=X;PENMfsrt`oIa6$HrvB@g^M7|b$^LPCtFdM+`^N2} zbs>wm=J6lsqBV<$Z0*0K8>^GOWQmg7H3#u~P6o@A;(7Upy;*e&&HGlL=9e>LwFT43 z8qRu#mvGioTn<7Y>u;Ps%hZcP*rZOrFe`P7fZ3B{XyPA^n5?YTY|oHT$j!o)BwnPz zDmxOtVdQnK-;(@pdMjtqCP#qgJt>+VE;4@|9+c*C#r6HV4I7Ak!<5Hlf0is|MzYp{ zZ#H+4{Frp&L5{79o5Ibnv4Z+`BzCe~4RmEcd3Uq?XrpVIId0L@VoR9urWVe`S2ow9 zz(kzd8@4ZwHp>-yQ#6kCy@-=>tz8(jYAE-_azLU-qC~DOZ4GeJMK&Db4S0k2&fu^P z0o{j$PpQdnER1Wq9*+uyRvfnuE`ThPLu`uV&SSg;vkx;ixBy(G3gHwQXsRN!xLQkZE@>=}6>B8QpRL@xrin%en z^Iwi#jW3uYq7lF0_~Rn|Fct{f&S#;e;>y(*)DyOTV^A9R{7K{BypYsf*3P*W_)W>euO;>2g?f_j()^ED%EoDG`Yn&4{ zP*i>ZDFERUJ~bDvwy~0BV%@{3t7Iw&hgL?M4jhS12TS5YD;y(EXEWXSjVoGnhDzrW zNnaW9gt~T@LZpZ;KpL`qmx@?iDgG9_*`d};5g_2)aq~ex+Fk|EF5G9-Pz5k34DzK` z2b@!2K<=kC#@4-t%gM=jl=lLyQCei!dC_&AkFfW+2t&z}U?wH%zOrci=rt$PP-vc< z6B6+d)Fq(X3*fMtFkxcK_JU?Ne$%ms41X1z0V*}r@7jy7Z=wt7T{;kUEbj~uh%*XU ztO5`;&sEPqvR}keNS!beNce-GxSc{1wElaPHoMNjbIb^PWg>L z%?nSGnra^v00DJIvF$_zKsgouiIC4$ICTIFdrt{pskaVXHnX^#)w(PuGZQ?US<^tO z2s_=Rm+{-RBn-`4T;aW*3Pe^+VE5oi(PzLILn{e6$FX~Tt~UMfjFwmK`1uvIR*8iW zY@oV*Xv!Fuq@*I}S0DJD+s%#pUwl!W?j#L*EPtQQ&f5)>yPd5euoFlLsNl8HcWEpl z0po+bmV~KzAa^G%Z_QCW*3tAi7P_trELnKaDzyl#3BcHOy;?fumGl=yik^XhQizYL zZQrr}} z4BBSEH5v1ET@mRtw#%JlpUPIk!eGVcf-ZXrWk;dCkL$3DR6Uo|G`%H9+iS1s1zCk{ z_3ILyF7Rp?LVGitFVyth*gP?FLk0zLuu&H|~+C3X6-(#+lUBQM&**J)LM!KF1#QI9OR}knedj`XO z{MDXtRuJf$wVwEXWYIuK16-WrR8Do)InQ|N3u^>7H4mA-9&h|X_se9al*pkHiC+ZO zjHMBGiC6#ntC_Trn9F}iob_aADJPFPg%xgIb^!TW2S%Lr^4pJJI?Hf394PbKn={Vp z@`dyEK`32Ae8+i>;CRLqXB`fwlStYkwj=pcDw29#it2GdNkP69Bw79QQJ<|?MzYY7 z!yKFDK=aZAWUE2zK)t&FH1U`Jgce>U{_Wp&p81L~kg_cvsTfGvTRm!j#^jx0ARD9u zI;7TB;&z_~6l?1a5w;hul(F9Zxvha7X%tqcRS~W!2=r3z&I8SkuI0Ar8^k?!?M-(* zeu>VcL?h9h6UnI`mR=$WuD@%A{H}MowB(Be!<0u6DUibKzI0Y9Fj4h`F3Z>XGk1bn z06}!703Y4#1eT*F1i*atdv~fC0Nf62y{$QB)GtXh++^)JnqiyXCCxfjQ~G!r9d^#m z9ieQ&X9P5>3}|N62tRi!GwhI)DjGWi^J&Jqz?Y<1bWhSOvLk{?IqO8T?L*_vTELD_ ze463iZ4U^oPcv*LUy^1+_9V@Y-?6rPlxD>N%{npQiwdnzv!eo=9&i`P^4`f>MhHwmy0 zk87sw7P=9>?=~(?mKgaIY`_~4?7thq_B;Ejk8T=d=iLY#_5g{^eIxp6NWCKE$R<7O z6^Rf1+`98aVk}~2)@3>q_;>5%FCsY~xn{yYYd(_Gsj>X;oQ`DtE1Q$F=>G-Nk?eo{ zbc8NH+P7J$V*VwkBj}u8l4hKj*>f}-vb!|B!_x8rDB|IwH2zfAMr=%2%vEeeNv4 znscZA|M|#n%}4OnDwhaxp{U$I=5OtiU{@CW9y|GP>NY$!{_qTn#rZp{Nd4(JT;~O@-*lZtBl(oMC(0Efvc$w?>lEm$)zYB( z6O@Kqz129^;~vqGu`!2dCv659g~5`GznGK(FS@RcX`HN!Aq6a>N(tQ2zE;>Pigi18w26)vMtvIV7(XE#g8=>*;YyLm-_$2jd_{yg2OfB^VzRv`tj z>vaG)4DRe>a-H`%aTxYk9b;qS9xFqnzqLQi;689?Vc2OJ9;-S$XLu}fIDXLk_C97% z+VI$|xiRf9L9Ya?~rs zF)qu`XBBPoSDj0I-|@9U3Vfn3ttx2{??oM<=595n+cn2&KK30Jn@^A0ln6H*Ck4j` zOgNgYLio~NZw8jXld#+Cih+-Rc8i+^tzVtsuf=CzP@0d=Pm7cIoN4{Ge-KfO%~9o> zaMZP4-0P1FHw>}`zd=73jz>Q-FN}I8A)j(uaN!M3v2jvAyo!e#2HT{Mkknafsz;L$ zkMpO1zk_rBq~~#6pY~}m-Ij@8_(;5DYdqRP9jB7tTp`6+Bt}qSTbQ}|o0}4py>~Qr z6-FrCTo}~er(U{Hk45&;nPxE*_X+1MYtOX!$sGU#_LUNz))JtwMQ*#TpYs zIb(K0k99>pJyw=|9zE_SDfIZZmbc6t4O*S(Vfk~pEiEZ8*PR&f$9_Mn%lDo`gYO-Q zZp!;W0B!oix};xn%ZI-F+3!8Oe4qD?03P+Pgp=mgQY*nY+{za(Y5CC>ws-L*&79L+ znt`}?5*973$~5~7-Uh!G!RE@Y4(0=T&i3JX8zjrY(V8nKq*d(~i2aP|02byQ0tqIV zkAD3=%sZSo_;tgPBK6BuhT8TQf^V0mV86$SKJ=MOt4}b43g1nz@Aki;eB;j%Q=0Y& zV3>oBcsJoXO^w~VWs5W)WhNi_u4P6c!W0(QbOdO2_I^QMNS_P)P5E6eGl+UmM7?ch zPsV40U`PM`lFwLBABZ>#xmE|u$u&P-Hu(?wSN?2uVI?*qPWk>23Ia&LHE zG>&|fdnG)IvhxLj883G$Op?15s`PG!;(!i8e^t)rn7mXU zaUvP!tP-CI@0D|jgx5P>c@ub>)4-w3!}Pq-+&vFuXFeBgsV!Jf4*7=y_sqinI9%%} z^WKhz-1dr@uZC)KMS8{WV3q{%2-iwdxf9}>a7?P&hpIXWZ~e@slF;lHs>gMz^$JvL zM^ixOD)W|eu}G-DRIsX7TP9-WJO?W50D87tM%jD#N&_q~O&TTV&sc4zE(j4?>c#25d$^m$?0AojV6N!CJ ziVI)9{M1Jiys1BxH?Qu!EfMyvDg0<%%^TeS+8YvvYJV%maCMWiAT;x*yn36+Kk)ED zX*C~qo0%vNxrUV0IW$CXtzgj(7E!OmTv(v3_Nl{YwG(ZtokiGOdg!}+f23fwfR6WA ze$+tj1PLLD(NF~G+ssdgnJ2;sU5C)_ODRjn&iJj_-7+B>%MumdiUmhWexZ-K@-Ttu z(*(#O0PV%*H$@Pym9hXnz0Ed4Azv zd^PJ7Uy6T}g9|%45{A9KBi_4oa=$%vP}%~an#qzDEFCK%x=qmVR-Pc`WK@$;pHKk&h-4tuKgdh_Bw`=b*#EY%^3r}5u?-qqZe!)8 zy@c2%jXlxE%1ir^#I|Z|zKxZa_FQ6DYiu7ID=%It8q2~QC^hpXX>UFes{0U{C5fvJ zA*4uF4I(7Cq*a9oDKb@bWQ*Fbiq>3}I(*ekCy@+a2cUaQFhk~~bkEBU(eBw?So%)F zTz!zr*gE1GH<5>-={~~dx`S25!tu(g_^1Z64pD5+4L2OGNe0xB1RdfaARu>k7)f4F z#J1R|3@G9A7j0`OP1|QdY1;8Tr}KQDrI0ikQpt>0zF|Io zkfuaWkxgGHBVyYVeYYh7^|EkLFkUUTIdI8nhTi#pqA?_>(tAGQXJ^#ll1qV*e{S2? z2W$t?=OYvJ`_Mf_>$8qgePpua3lw>C`4bO)<3i4YcsfxU^U_nALO+R~?KF zyWnK0y>R)d!#+}!Z2H%SXnj)CkJj|lg7jlb-qG|s=u7tnS+{U)m+70=5isBgVbh93 zbi~}>DoCQ%b=Hd79w9+^!AOb$$8`ru+kw9;yCyr-N7tv{i9w;;>-Tf=h8NTX_}=}^ zUEuri*Zrz8d2SUMf#2^rsC7;8v%8rU#iH3tZ(MzfY1&^~?-4+bpDi=SuM;v)9H4DC zep*3e0S73|zWF*lbgmbyUuK$)0~jJYP+l&a^fr*G{}$8wH5sIPO6=Pbv{}(0yXcC- z&>iSK%;GOdFLl;93A1l1%6%=$zsnbt$AEGzA+t{xl)rP}u24SDQGOjCdyXb-XNrZ)U=YK5N=A4u~}Ub%02d>YPJG znyxuW%RgFXBa^wsh+%(-DlQEFuD66&n)EZOvxq*rv5;0hMf(BgxpEI{*~<8t-AtRH zt5B2cIN-| zk|gs#K5AQ{%nEb9(7Mr;ydc|Xl(npp2sUCWh(kD zso40a*R9+u$*Z7*0<(UQ%D|JrZ~VO?-glamwQ=8f6OEIIXg@WaSS@|R7<0c(`&&tS zpG|wZq@62izbk1EHgz`53`z4Fo91XqGfUFQY!vkp&GJz5B3x4IKw+{E560Uuj>Xt} zR)&`o&G8myTwrEfZFR$7V4e)jlu7QP#tUFF@KV+4lcU}_Lu8C}Oh=y9vrJ&@ZDHIh zFtz|281XZI5FdT08I=NHb2ztK_2EpG3q|I8F~%oWx9@F;f`2K4vNQ@qS=-zQrtKy}rK zpyO-Jo878@D1W|Hv#ndz>EI=3_AmFwAbE9QfJwCp+zTF8B_OmftrG<_jLOYv5`f$T& zGMit1U1Lj#y;Nh%CAN;(aKotzeZZN-OXqPJk%8J6FdGV4eqUD{v_I@Mmkd-^Tua7A z@sJKH`Vlri1ocj$+yu@(%@IK{qa^J$L4WBRZ4R^WowvixuDoq1k0MuxmN8~LCo*YA z^uCWB%77i8Ho0vn#Xic1wAf^LdDW1#s=kkXpV#=+p|(E=N;4BxReUH(t2)sv7@+vR zIS72;l#lVg=My%~)WeF-_v54Ho4vvIvB?T#VEd)vhIcgS0EeV9a4hw}lkS=>^aPQ)V(l9ahB3vqZ-6_|#76BKDvK*f(KDP_Q|`5vp&<+B%nx&wj*Vc~ z_^}eF??A!yO3?4b_f}B%`R>cl2wOhI1F0>O%-Z<)6SThqn}Qj(Os^l?hjA}jX#S}3 zD`R5S=_b5IXgnNRHdT){uk=@J?k8pAJ{Frg!loT81)C6}qNF96NumeoJ^7hNq2tYZY5f)31}WEtLIeW`bJB z7$in#CeAED!L{9i6|tmht0D(?cc$zn>vNVxDqi`fIadm?BTc5%D4Lj1D8K%Qxr2VZ zpI;wljT_93v(#{_7@NHmU1@>UIlkbhV71J2yOG4hdQ}hD1>Vcdi*W@fcEgdVcAf0I z$iC3o$7g&0R1C4qbwx_#GTOgPXWMj)NJmuSl`oqse-)51RJ%z?8!PsDQDbf^Ia|y+ zWhXqEsA>A7X3M2loR3Y1gLG-Dmz8o@xqkZn{95CV*j*A?<@~prjotNKCXHo=KoGX)LL}iH;~Qt?EL4^3zb4YOX3ys~W4lQ`M>b&@qnW zCz@7;h32Ztw5p-zCll%5V#68MnyM%?t32NK&h9#`Yvo6-~Hpmp8Jll?FY7QH3x_Yd97C7esyQS*PY4RDs!_Z@|L~}c~j$b)Ef>>b|z41$F5+wSPhVJ=B&rpNzG*HQFV|^#Uioy6V4h*7xh+{fz#g?!}#ToN$=PG1I7uK z81m%>`Hj)<>9x+wOh0Wv+8>XileG&e8?F)1%gBFh8H*@CzDZ%_`QMkBK{GU>mj%AJ zWLjn-HJZshqIjK_WBPwb)@DFoW(B(9FdhRAq7**=g7bBto1kNgeYeEpuN~iBKiuzq z7uqYNqxdC}KFXSJCcYl5mig`5XZ?dgu4m<{Ya#Y~=Kf#U?&>1O{6uAO*zZf0K}pkb zo#3pscZG&&iu*FN9zhVg>cxptx$j&HahJlJTbmg?mH#?2r*usEuAj74$zfZ@=L`Hb z-W(slnxTwH8>;%r{qxb9X1dRzY1Nx+uFSlqdf%vbx;PIyWp5eR%5uUB+F+WQm-`XJ zk5zUC9HiftnVXMh{FE^$Iav|;i-&tfn@xHU7i|%)v*;1VMtyotOE~iyUW2cs2fuTD z{3ajfQyqnI9bii@cP0?Y^p;}oyA$f@8W)^9s3U5)?l937WRorBr zE`K`_@iw+SD+tsKWA&n1$Qd6nXO*qte`yJ0e=mlpiU-VZ??fh1@dVH>8O~;IrVg|2 z5<&gABIJG$_C9jGH_E+fcXG!(D`PYJDF$O-H0SPR2|rN=LC^gw9J#*StH2ap@nX~) zYuRK@=x0-v+Em24^IciKR8o2fRotB)@hV_0G8N(Ejkg?V4=9t(6@R8tCXN}j_4=c@3KURC>^0zsx<)+d^1PBcxY zo7fa;>^QJyOP?#~DIjiqz{5-Wr!l0QguYFQGv)Sl?U>ur2}L}_FFtlYq7zO$qbLot zD77CJjh~rkDspT+|4Yc@xwmQS89sz;s3_7vkj+6tYg^beeWlsUZGEQy5wvix0(1v7 zX{=bSq-mM0h5F?-zWh$VNQ0FIXI|us05$XKW%5KdR z+IrxOm!QNoGnx~LYtjyBt=T#$G*i~Q%#j|j5Si)$D$mvZtnl^Xhk4}Q7(_&z?|xgv zxvIL%gUicI55~Z@ha~%@y|lUKf@z~JpT_%kWYgX+%e3>3zINWx+bryj&G7^?%%*>p zG>!KHK<0Onet6gPKauo3%)>FM>N0c7HW_tSIM11(ZwV?_AFA!$Vs{uFkc>dzw}}#q zOfHFrt)IHFeAxHaRk2B6g(+=&hl$YJJ}1g4Gu*INY7jd-$%zv+_9=aJE$C3|V=z zRr$2PmPdULu~pfhstgLguP}e8m#SRTOKoTE`z7&wI^E*=H-5p>U#cq>O>c-y8cL*o zV!GI2KA07tx?WZkKGjv2R>lrf`k{0)t!C7Q_mKQ)dyBr;Nz-0bE?Zm_@l_@_#tuC8 zK+UwN8tLrF&HOQR>Jw_<@HMb5^S@xf@mXPCXPmmfQm)K-z`yesP&AjfAkt?93#?&x5^Ai18CFO$f`Qh<=US+Pb zu-Qbi!h{5NtY`ZY=ehQU(bzGvtIS>$+6jwd zBFM(-Nl!v;--D!zHbTF`TzG@UJapq&;(gV4l^GArw&6*dL{pLONRDvpnDQtdWIkDk&N0g&{O5d zmzB!>R90kSIp7xQb7ksKon^&T`gPSpM=}ha10dyxC+DIq~)Sm^U;(M2c$xbcy%q_|Wqb}%{dy91S zetQkt>ObqOf78FldZzZT?0*{A`90RB^ZTG)o!`$H(D{8s|IY76WOjbPw+s9uFrOty z6!19$BW3FQ2IfPl?=dv@)b~pm+Ed>*ggU=3=<>a+%l9Mtbxwa}m-?R5Y5a-zxCFaz zYI#?7q2Ik-=+is3{{H+oPo<$|YkD`TFVib?c1P}#9e%Ilp_<9*s800N*8zTBERvpntPsj&xhPHypSH38G(EkYM{=IE;P4I zQ7ROh@2`0)iG!U7Q~n^PYpL|#kSY(hKG*Hz)3G*FdNUA#eY;Fv*FVVdCfP!K4ANT z%yu4uZ&!I=&`G}Gex~35tRARXm&t0%nySO2-bpoWeX71z)7Gu3kNi17NXyo?)2YEK zbMPZ##kl%-%Of31weKm5mtkmJXSy%a@3~PAv-m3W%A?F#d}};Y8Tu>R2X$G00Nz76B3zB$Zd%E^~>4)BQ&=ON8o^04A?1JM-O&OC%@*=kzSyd?)hjbNRPPglxm zzb%=Bek}Vbr`R=ULirMkM(WB7t`b8Qv+Fc|3;bU(>86>5?|dZYka0=YYXcCbV)?+> zsYbc!lCo}q-`Do|Mt|RSz?yfUA--#dpufq&fEehii%r?b9kQRflwDx)vl;yRj*~58 zXMWNlqhtKEV;XzPwv*p{+L35`1@KYta`bh^%vI&yh)k39S0Qt#R<^{60z*?~+B1f; z1*cCJ-70jWY~q{wcBpoyWp@zR&UdSm$LJx@l5#`@B25xW<3Z|G`rQV zjF0+@If9be#K+=*P_~$zGv)=Ndm{Tc=npbTA1&I*VtA&RxLI2mQoCAPdfOY1y&o)+h@|&oQL7{x z>n;o25*|_(ORKm(ToKy_LEg zV7mX|hfy^iT{2F{IZifbN6E-mV8m4dY!5!J!b>x!H;R^bO)saZ?RKIYb+=$_PJzs( zpim@U%K3{U;B8YV)=r%43o)OtODwRYTu-EF-=a(&&sL^JN30F;zWK7P>HV#6C=1C_ zPDhV1rLat<2G9OTR10unSBJI2bg-vLbgt=xWGGl^?m<-(bu&PvUh5}ZdS`FTrMoB@ z4&|45mleXL3%Jw1gyp4WS_kTxkHQA1RVF@Lr1zS`O~j)47m8{eYSFxsuqhWbj{(iL zF`8wWIZ5$bWzMiwudUR0)@PJ^(vI8536|Z#GKymPU6{=;L@}pn@U#+XCrWs2*&>Ni z*+f*x>Lod~pEj@j%C??&)ifo$xnm`O{7s3PEd#5LH}}(a=$!t>#-7Fl;40$tl58!S`%%zGu#aM)=>eMposvZiS#z!0 z6!l7E>8_IjS?-75?rUG<+ME*<-6Pa5*e~$WJuI3x3Yx2}_?#qY_O)onD~?eiGUp*?w5NMWQa<#GlIr8kGNy%8aE#=9 z+U87?oNIyDC|#!ZVE39s$k}$D^{|CCYt$<9T|`t0e~9aj!^Bd6<){Au{gxX;>VIBuG7TRO3W$yqop9; zw2oo{I-alLhJ<1|V7+W6x-VB`6`*|m246XDAhi==FV>xT)PR*Hgw#x~e_JrSNxp|0 zy4%j>7Tr9w(i}42okZKGU}St`8DPgN_d-$Ha;UAa&^Sq_P!#QFUaLu z8u>lT-1lcO9nhRd&rDpikEFijR<%A?p{BQ*Nez6)s)2nQt;<_$9zIhfv}%94uOa5M zhc>}2_L8oqVs1Q~Fy*(S2=uU9x>RSx7y%Ad^sn?37wmXGYgmB#IVEa3fuCswvMR95 zn8EGagHubEHN9N z0@aSG4K>5$i|p#45}o2V78cU<7F=lUDM%Zhskln-EqTajafGwh~pq*@CUEm<_hHb}M zvr+$b?<6X`l`?awkWPjcy3(9adK&LAh8xxhI@anM0anTpnX-jIWvwNgLup#$O0guO zYstw8S$M~YcmdY-_E)x7AAD6mW`}QJGXHL-(t`a84!HF;qaLuj#>uAS9c@ZK#6A;0 z`v5eJD+rlUo3tUt&z{6w$js@m?MQo#?MGwEyzirPyj|U2+E|xwtUD>Oh76sOBRk?& zn0>T0RAiz^&|MarUQ`syRA577F^`?mDPplBQmae{t1^&lLkhXD*Cq9%2I+oS5AsE)$GaIx z?dUGPlzZRGlqR`VW*-ye+y}oyBHm_x$|VeEp5>>Qr_zj(B|~qS3}llriZsS@hNJKa?_zft9kV!t7}eVU}ui{+qaZ8r($Z0pH&QNCJ{0Zylq)?>M@P^ zGDl6oz_#aUo8=4!EO|Vls(=jFGgM?+&Cx77nYnPMqlLz=QIs8uJiVQkkcjr7ds4?Q2dktJ}3wSLV|3o+b#!``${}tf#WJ>;86p z)KYTNfT}xlAUVhg9wrTh z%Dv5Pdx1~r#sV2Sbh;d$trM~ecE*qlGMH!93lTTd>)+_9He#owA`KJTWaFw?jFh8q zeNPZL%OVgXY?gzVFmNGpiokvrfwo(KQ^w2!I~0}_6It}05cPO-l?7BFfWBh^l?b33 z3kahE8|19h$eg?qm8`gNF99a}G_CWL zfkREmmeqiPwo!J_Lbay|n|*wwWu~l1U+kCm0*WhiuwcS4K?o#NsTPeEJ(pKeTE~fa z(pA479qLq-~+A@;Ela)%itu6)p~WhDu}5_zHhcZCg_E394s)2A6MqRP&V|$ z>LX>6h;5;#OS6rgRwzf&hDbqu7z-+87-`Qo%jxafdz9-~?wws29X6(5T-6yC;o>H( zcSOW)=4{e4g9*(PeKSf@xVH{VBs=lK3+^D!+}uY7IA*%#F-MCWX^S)yDZ@69rgAS! zW~3l5O+->pu)6Nui?yu(Huo77j4^-?4mV6DZ2sKVsgYzr^0u#03G-u{;SkAitKb&z z`%TGkZ8F24~Pu40r;~!Q_hmEVYfq<`&dRnVV}3tg zDprNF7*+BktOXahBVO8He?~JfCoFs`F_eC~ibLZxSVlhcoBo>j5@M7wKh2@<|#Lov~PkDwYt> z3y<$|X-8mRsFHNn9;aG%%@nqq_SLNvRVYz3l{C}zvh)d~8KQkV-6qtL)WMOkn$mk? zm?Kq5@uHe7-KvAPLRsne_kY>aYKEpUm27)Wxptfoa5;5?YcH_mV%~i{;M&yqs6Uxf z=&2?QImd|~72n=hm|_^r?_wC-ad{#|KT|VDQah_k^ppC_!Nd1pKO%`gq68ajmc1mE zX3ynDQ`}Ro2x(={To&>&LA?Dwqm*-cHFgdnjPg0r2sq~{% ztcO%AkBT*33q@5j?l%*WAUpS%Aj;9iKv@%JEh_U)WoUfL975sNa9Dk)nfI!a>Mz5lfdDJb$v&j$-EZ39J%*l{WM=aZ++Wkmn?pq+TC_QEM z;pTh`_dtOgw{XuCxEBLg$GA2*AmT67tTc%S-$O?|l_9K&#ZK8mkuO^6mgU;Pa&-(7 ze3y<-Pn1>gZ5^NKK=RGl6_TXt`_T)>aN0~qlXUrLCOx4a#>)JAawMH$CPD^OA}T{I z$}VhTLs?a}nfnSD{R|Y_kB362N$bq9XNX3!%(h`uLoY7?M>o7Bv-GxKU{NzyORihV zMY}pl2ovvnnQY#vN z`3Bt0;;gW}ibB*l1EHiNpZx!5`y2SEitGOa4}?GzVWSw0^(iXV*r-hfH5k;a1lWZQ zpeWL6l}c4CZKawZR8;5&HNCFV)>f;vK2)u?YPGc*qtyfuB1m{r1g(m;>cmt*R08<0 z|M%z2-OYwVzyIIs|N8rq?7j1F=FFKhXU?2Cb8a}PjC?sV>%aEX(?1V~3=iThXzgsw zZdhX5j~{41t<71xoB5)))7W2ziQ-4;Pq7Z)&Z`M6%iJ&O4`IKqF2OO^Ve{*RN$sU$ zKXULIu$PzE>OjW{KxIdF2rc3Db^9)@2CikJamzh)vH4)>xTyhu=WN%tA)=aZr~f8T zZgC}Wk8N#2GY-obz4s0=8F}BZ!@8Lq26JqPq^cz_U@8V=Hs&dIC1RZVSP+40Z+OA_ zf4sLRMA&}KYzxf^k%ncoD=R|ZVg0Y}-AK10?6D?MgDp7hFrGb-8|?ucY5TYF+P|Fu z0PF=3K2Ioq8n2DnVZPEEZ0{qf`z?KJ5f^Fq@U^SV-%M5n=K5z#L7*r#=1ZtPbBZow zvD_36E6S`@Du(T$eKB}!o3qS&2I`_jXsQ6@8a_3LxAf@OyZyF@Otpvm{4Q;$_phrt

zFq(;TLL=_Xg_EJH=)&r^k z#t2QQw^*h&ekrYwqUpgBP@*6~kv}A*iu@s2MfPD;t3MD`Dh5NuN_u&A={Fr&?2}6^ zMFN@bFIgwL6BPKVN1_gXl9(e&lFjo8Q)8C2{&JV3%@-s&g*<~UBF^ZF>a6eyo=nu0pU8dY?<}-1EDUm#MgIe7*^e~SDYLSyJ_d9{|LSFZ@hXcZ2Xu5>2^zvDXUqvAO zx{ffNxt`xJ^Luy+dKibKGdEb=ZWm|k;pxm~i+f%?SKTuR5UE}}Y{B{w0d!t!kjg&C*O>%_L1=FFcA$8=2iZW7dERBTjkMWaF5`@x+5mMp*dtpFMA%c~!nK+bz>d7Inx6%Fn!Ae`k;90kT89%*tsm=a zwof;mJ<9TL%)VAhti}tkr(rQ&3F~hO)&iZB*UUQVP12Zkd&z6%lte)}O3X-mN>!w? zQXlB-o5BZ%o|w`ekK8hN2rZXp&%cfzN1oZ?HfE?e1htLT)EeJ6!aI3mc6e`iTPiD# z%WJY!M;JM~=#JXl+cY!+>1~NmyWtX3@6$GNu$6T4WHJ^cdgJM=s7oD>0>WCzRJ&Nw zmskm8Vr{~UyrM9%63pBVD_Iqpwzl4a^)Ujs7MmE#*Q7G%D!M--GN&>U%gm>V%FL%p zE;G9$iQGh9P%~fY{dV_!DkGsxW>K2VlFA^hjeuhiWDX>g$=pYP#UWs0MuZ}>}zkq)6P<5KhS2? zFlA3ti4sruh?lqn-WaLOIPZRTFT%O&i{lFCMf3J8oS%2X`IqS)F}_I!FAtDPB0-D; zb{xow^xrmh2(pP@95QX^R1!j^@kpWu^w8~csNV(B;5@H3}g zHvYU=JiM&MS@)Nn3z8&{QjK$I|ML{n9yZR4hs#=KfcE!gNyg$|EQl2h}!&srkR;GD4S+Z8JB?`>!C;zz6b`E zWo4(j;d~gZKsNqP+M(4VHLPccmXBQ9W|3}GzmiBY+QwzV4I183cuIleP@q)~YUNYK z4Sk&kXt+*b9SS+7_a02t+b`}LD6_%u=!jh4+-nygh=FW+-aBuGmJZ?(}9PleS-|2Pa){bSBQZV6<^9J$4O(a6+(gR7~#wwv1H0<}BTFEdM5s@~P3zCCxFqaeCc!<9afYvq5U}7*M@r;cZ<(djQ znM5=zA@vEJs?JE5$nZ-ZYWvk0T}x7U8&DD?G4xv%@}OzY8}CiDiB3Ip9|p~$s;7AYMQ1~>3b-1G!dX#MPAJW>f81O$@>z`HK<;VwxQU@AD> zB}q+Cjy6C#n+G5Uz_GfI60oGSnt)whaS$|tQ`}n`JE{sMMy9zwcV8Q;p;te%XOEL} zuY^%sIgR`hMs4|&GN>xCV#|$G8v*TOMheW98m{BaPvv#-5ZPW?tNxFMfQd}Wl?(;) zzY`B-=GM>NB>ARA?cbh+4~x#HU=J=nE)0nN7h96Uu#E=H^hcTQ@TvN(pCJ2Do%-aN zTTh!2-sa^~S1p?n79Y<>gk1ZA%Hfa%Sne}Tw#-{H&ldUUZj6h)4616zlro}H-b^We zsAOZL{0|;i=hg_SKtZQ)|G#4UaXEdjW8QMXP)(VT{AT8cx>*U z&L5YC-#BY54R>@uS0JGq$yQ8Vo;Ri_BV-Fj`EhRksYkV4B?bj6*VDPY7FP2vR+zEl zPJezcuC3?yg4!6r^J`nsxL0rqJwURyliwA!-Qv%>&Ca_)-3_(9g2$cXWl(RMMpP%a z;YCl94d427ISPnc(@689zPP9>o&l@-9uM|;E)An9QR>C7)iG-IjZ$|;t7=c#Xtm70 z$1B+W@(l?_gWDVaB-;ZC4?a1ETgQ;|j`%Cm{8E1{uP!~GKl2r7&_4Em9Nhj{qGEnv zBI%>s3jI?;%k@t^sekU7H-@0kfAmkX{jUf=SB-7{3$tI5=Kt~d`J`8-L9Y%!m&;pm zZEk+-6(P_cqdlfSR{q)lH|;U{Y(C=^XwTmFyJ=Rou;0z^q8Qz&rUg$n4@|Kau+n*n%;oXr?KVnSA+=Y;J5Au}s}HH{mZ&8R1=RRUjK@ zE0mtQ;Ah$avR)~wZ%(E659A5b!6O1TW*#Tt=*un(vbzbi_e*84WyFGkY67Z1T|r%g z9;5CNPZPl`_gKSxO#_b{r+ZJ+@)y`E^chwMWvt8@6FRS%I3)Lth zpm0H%!-1U&VMb7BfPu76!C_*@RMotUmCk1}s=!K@ab893fKWAR6{mI#8W2xFg;^Fj zKgJws0fHHPJz5>q=4#d9piUr0hh0Dn%~TJFAIRk~%k9eu@|pw+pQ9a}ihM=cb!4;A ztD6r&uN1*sjF6dfc2#Wqq!|~LpKCMFa=@G&RF4_s0LvCPl_=@IO zWZGOVL$_)&ySpHsYPgWe;C4E>mvF1p4lm*EL0*vAqF7<+S^zaxTe@vmDP+6k=jGWx z1nXKh2&3lI>u?B)egZ8G#qFcB;dRx3b^2Ffx4xf3KF221h-))t=G^5wFY$hpy z7~Et*&o%{hJ;oyG><$+>;v!oJaPX?%0c~?hu=gf0^-gBUB`I_cOB-Fp@w*kKv$`>k zxzcKCri~R2l8Y<6@9GPDNZbdcqS>J`LN=GXN7;CHx&=L4P9u^FJ>b^Y{R&t2X|C>3 zTgqdnr<%aN8Py%yG>m9gUoGI$;~}jlMEbXDks-kfv%8KMge16*c z`D!|&Z-?&oJKMCA$V~p$53Fmc)^x2_g6S$GQ_;1Qp8NFhzPlFUTU`tBHN^tw1Gw0k zBu+=gUJa0lHjAv{Y6+^*?j+&j`p;Ub!_k`rlU3#7Z_Qha;*Xx7eiaEg{tLo-)VnGL zV&TB@EK6If&*caBw%ds_1g(AF4Xp2`=e`Hb-$5?Ulk<;z$tdn6*%7TMx48}h(F+v* zAwL5>#X*1ju9qlbRy~l;sSj3^&b*vDDb2NZhJpKzQ|D2q&ZAD9kM}{?Qr-HrBXLQ} z^xkPWOZx&L^X-xV%(s6Eh%4(G!uumDj#moDwe`JBYuWjHoiDyKvf>4e$;Lll-0{I2 zr98OvZr=_sT_~?aaiwlIX0{Wu1ra_u;N|_RaFs_i1*CwBd z>lQJR*o*KbjUkEBUe9!^!~mJe-|w%~FK<^>Dmy_pU&zh91Gk;bI8Q{yWL-b74VC*+ zDy99PQ&lQcE9wUx|B>LGO7E>3->r)fc%?o(kz+<}k+4S7!-4!2U_U~wF)AAP&MZ}A9P+X>CkfS6p^C#Z!dNX~@ zxI6sa&?8)a!HxX+>O8k2QEo<5r05=shCz(%QMXq)>ibZ3mD1`m-4^H~0$-=B>chK( z7G!TBaQBL&tzH}yrtC2L4SgYPUqGYXK|k$;2fN9Q0&``%O%u9Ak7WxwI1BXX>L7)x0{EE6M42HhSfU1XXgv)UvE(CUhcnmzn%AHF&G(M zAtVr^>SS1fUOJ51$<%d`Y#c4T$H})s58l7Ri=t=o*{4nJ zI;$XZ7N6dbdLWT$o|5Z7oKs`V2gEHLRef%8ExatC{2(A?6I({=3g|0Mpm^B`SMVaM)Q*{W&Eca>;S0>(t6kW8 z>LzF!?)Q+lf+>lqw{imc$BC&wL1((2lHHG<;yg|)n>7y0Ps4{GZV|Y^xs9S#ChiX| zNrsEC`sQHuwPW?k!N$U9JhiZkU0;{6FiYjgwu=ew9Xysza3{kL*~|VKgo-jsD#8YY zMn0*{33D!?V!gI8!B?mFEq1-xw;FNa6R2b3EMTc;s?=2h5gupl;Z@ojkO+U6QovSw zVKBT({Tj$|_EoEa;;E~83DSY&L3q`5_G}X3s&Dh0Kf!LDeiqq;t0s2bveu6kiJL4u zD3}?!=;=Lsq&UP6lEmu>$C#0l{UCIQrTL4a7mT0v-}#Y(0Eti|(ah6AzOL@Td3(*>#?vFBvy^H#EsG zpSzJ4@~0^&bM&>}K2^J1FC}n3qb7e&o)%u>JaPAc42mNcpXDAVcb!q}*(Y1KeqhpQ zw_ePO(LVb0$<$_5V)@O{GCpcwHFkYy^gMI12kyJ*drum#Xg^0&;a@i;O0jxm`jn-q zdilPd)vQC;)h4oUk;7g5!(MOq%*)@d8Ek|yVvA09>l^29wT@Bv1?mymIOe*@;b=y$*vV6BMe}`Cr(|R@-S7^%##j$iqW-7L&5blHoVTV{y{h2Zn~3YZYww1c>7^&*9S7Gc@!IIl zKVP+9-&?@<*6hdk(o1K?(-)pBA3-O|B~NpBvw7v=s)N_+27cANIc$7~?z&gaPpM_oo~@A;Um_}*zF2+ju}H85|Ezh*WU*WQ$1+D@%9^u1 zx^+HeS`NwjQja_p-&ORQD;BcJpQllc$+BQoE-$xfRunU6L|xs=Zm zIBoFE`9;4w73a5GQ2>ScY^}-LrJ0dBySkqP*}baiR@;&W*15An2eLJG$IMh~F}Z|P zW_J{syYxR^)U^P&5Tzp(CkRi~cKH&+lo|(hE2wjW-r_8xC`L||#SZA01-1o}&E9SH zLXY)_y6gzF#PYS?!VnUOk=&90Vk5bPtF6d2%@Q)(c$dm48xz|~&!vAPaqUvl1H)v% zhTCC*&30qx<@A<2R>~;KQOiz^0(DRZ8_KKnDR<=?2Un*XWOLhOF`8klD3U8;36k<9 z{+s6T`KItr3`A{6OlOsl{|%o?1%Gev+s!c=T-oObgaxXWAmD>77HRw9DOCKxcRMW0 z+9d>ROuW=4keEN%08E8t)tk$`dbQqtCw1>3g`+qV=j5W_2Tk9hjuM% zPezvAh?hGC%Ztny#}KcvBp{zb0v1=dTcR$DEn5FA-+b-w6zumHYxhqv=6g%lI2MLq(ncaeztrpu< z+v*!H)QEh=P8xNPD(ov;aiCP28BXLiBX?oD+=o9@zK_9iL$3bqIjWQ~RtfLRA1){5 znYrs`Z`x$l`fcumhp~6@sm*5{W$ih264-Mk`!9LHf;-Q~CjV;@y)?^Qertg4D` zzlBwn{T5e$u)Ll`t(>9tQk4~@RQQGuB$nUYTE;T_+~2g1`jxMrs}{LqC-S|@^;YLF zaR=`gbQ4Ob1yD+;;8wXp4-JZvUJsr1L& z9ikFh8`3Uuig51^=p{-zL|+RBwC$UYpusdsy_W!`zRn<EP3wrdPmPjm^i)d_aLj$!ynH@xdvk?XODN;?+R&}5b z2f40nXC+v|BV(9ZqHpzQw7ET%K?Vp=ZBm(~0ybt;C${u!p_1}cHOlK&+O&ljSMzEZ zZ(v*?9FY%&*4pDwEKPV>!rHJelA~AdOqion+$$_>sPlBXjdu2D6e$LNYhT zwp_KAkL!?}=2JklIuu?&7u*D=%mQ{suwCB)*2Q0mQ+7wb_E|l+WgI@9n6abG3XTNV zDmIf5esfjltI4){fO)kdpf~I{>N7$;Z;dFZGc*7R*+9YukPruCi1WJ*ib}i2rS-a; z?@=%3^y(CwJI%IW*kd0pWZ#Qs?L*O?ReHS+4O7>= zi@ZE9s3xy{s!lWB?mN>O-ZQE~Hd65kpD{2BdHMdIb!zfQhr9nUBN8-9m*_Ou>3U#A z2cqOYSzj(Z(=Ph#W0`h&gYsb)Q-=O{>~l|g6x-{M#}Rwr(H+iU@L|Z!-->D|&X(yI zPZYFN@+g>yf{7@Yh=K|D5cX|_jXTJ?gx6u`t5SS{^?>*AnAJDKIkA+nVtaV)cZkS; zkzr0EbM)e?ZM4u#;Kl?Geq3XMlKB}4-O;(3a#3yw`NUgG=3$Jrk=qsXFPihRQ9@zr z#YS-uHjyDF_qM+?Z`s2{OzN6zuAi00V0uI$qi6N>B(8^Zz#2C1QdlxlzQQ;w2TTmz3V^Vb#aR-WGa?pE$>JADdr`=wf%PCSzJ6b&RVM znaR7Zm7z(!DWWj`e4U;dwYE@<+8dMePi4rx@&8I8`IPjU+E(Sj2Wy*!&by^5)~O1V zwAOk?v9-=Gx~4;h^(Cf-Rx3a6Ss!8YpwHfS(<07I&=nA*DSSZQkA>Q%@MdAn-lz71 zLIm>z;$Dq-2Ng2n?ehrg_2ICEOimE0)w>AgCwG=Py>+y`t6yzQf*tuAZPa8ysRQFL zZ!ArISA_%P*DyKveP+mhVQN-lQ)G_{%OJLIWjC&esD!Uoo6B2|qDvtrivjW@YX0=N22 z0?jk-XqtLQGQ8g5BIVnP-3M+@fSA_imDXMuyY3pt*lMB}dlR7>O;<3sGUQH&Q}&0k zhgDM;w!qjUz+&W83Te?U5AT(+VQ1s74t-T@D5MyBLKd;7x=+kP>Px6u!#0J>FRz`& zpyOP9VPd}EZD*e5EmbScyv7Jcerp92LaMzyg4SEO(#`RauGK5C%OLSPTUEla$Vv%= zsu?+iJWVMLDx?I^Xm9jd`sl2mN>E8PC0{D7iN#Y+p$45+&Na2&g!*ob_mqE?mFsGR z7HMMyIt8!I)tD~RRUdnga`YbQXqI^lN!@!gZ_EMrw8j?PfjSdMg1&4?x5L>l#O#*M=^@+?;rBP(hITna$2E}L6bJ6;fNj?E-rPl8!14tdPAq-XraMAkpv7umQ!DYSh(SUSHAJA*2p(^CkH~cQ5q+$Uj|o=cf?I%5IMFn+pV#UU>mNuU ze%U>tiX(fmzf^IMXBCIZtqd=K<>jQjfhyo~A^+!hE^?#gP5wp-WRLzkPat*$`(BRAW)?gA`gD;hiaurwN6zd@gkDx@)I3P(qk6zb%_7evMW3=Q68sv# zL{@I)Q3%L_FpC5`m0$vmF5Z#ksWZtE6;fzrZ8vG7(#Ts=a7L#}rAED^TYpeUy!Afb zlQ=Yj(TyX z5?hq(ocs?^P)(>hv{+O4izc*Ks$qX+tuqb_-p(a0TK$ig zoeE!L@<_mmMM28qVGH#wuUJu>B1$Dv^Vk2u)Yb#trnWW_IJGrrc5$J~&k0tnSEUXY zVXv?4RxOxY+BMn2>sr$-OHZ%aissjXdBJXjf=&YD{2CCG2+iL)b(hKYCO%D7+bD_2PGw^?qnaT1f3K62 zcNY*adDx+E^=I9+C0`V<(QZ>?Zm<)Gg^eW^^mHq&I!Gy~v+cv~;>$iFW{E3AD&4=?W` z7`J^&&)v;s&!g?j9ANtf5i_oR*SCCs8T}Ud0!=N$X?=Ia2sZWOI;G zk?k85*))l~M8%|yugn}8ICAVH@>N0sQ;%fj4bhz$Md1%(tg^_Au?CZ>imc0s%FH7R zneft}ixeX;k9>#H!k$ZjFok-AX6BK9rl5a7*k%$~ZX=of6$XIrchF5hOvI^dCXZ{x zl5FUu7$9*p?4m-MN^St+J@@*6-lMQjC^8&4mjFIBI^x31UI=y*Fqc+E8dHQ~dZv=a z^jvRf*M_Bfnt_-~oGT3Xp*omn5*2fUUu%YMyby74Q$dSby`XB^E9U?^?vTPDJFyjm4WdS?m?5;Of zcSSS64UR3=i%wk1t=}G_|ImXqiK#b1G~t{zZGN%FH_Rif_oPNmDNYc zQtKcAOE3EEu`APDS+H{U4kDqWZphJrm0i?O=LTZXFdqJ4=#eQ&+l5!1|8EWl`Ca`7 z{Y&|;Qg|~vJ6{cmV<^T%6-*PABgMV26Mht~q?7Iph>ik#Y^akPjD- zRD{raE*Orpo6c{Rg9kbI|JW{497ri}qEZqAA?M z?N;C`!Ak@Z&2-{ULzbN)Vt+lT|?WglwV$bo_AL_G2{~-*8w?73n__DgkM=z`F z9@FD@W)WCP(DS zP#fJ;s_%r{Vny3&W)olcK5G43n% z72_tFtxa3V!>W$2=B~qVvVjy*)o!% zL)KB@gG5W{E(2)nW+G&4iiAk;1QXW@?MwfS9zr?VRzmI<)42ZbzZ8eJNg^0ZKc5Vr z@Pfg1;VXK~$r`am?%!W{SQ{|+`ROtjfA+}^K3TrrYtf&jFgL&Y934Z-Hy@{76E}ih zmIRsp7nKrZ+_7Ob)yi$mn(`_!gHX3+3U)wdkm{2n6hlZ6fO4l`ccWl+w=SD*5fU9> zlEA6ppjF5Y?Pv#jbcv;{t+LE^wyZ*rZoc;gQ9!4^PNP&?#*Vt-Or6}VL|ZS3nl z@&NTYsMjiXscB$zQnz9`&}M<3B}Wr zZqCx3k(jZD=dQZO5N0V331hmWB*mBkg5-v0Y`Qupc7WZP4IKtU~PAkpgKl z6y1OUENP@bT#Ql?jT$L1q;sN?BhLu5Lf54)h$@K2t0~)y#zeqLnPy=6l&F-|bkIe#`WP&b!usGHrjlR2{8rB?VYmcf z)#49R`E7hTclRB?){!g|$uA*=qq|>P3P*y+F_TRJJfw$F1#sVMPyqj_xV^zbqVe+^6e61xV(Lo_GR3)8#e%iKL*FB-`pxPvIV zgzqj=1VFyKEOC&!3pu-iO7))lrP~?QGRh!@DbH^`bV#9RcD<#XMZ78~T;(m{ha`|F z0$H;hWO}V^?pt4$Og*3>_GiCXiJlpIMbCyz5k1t~(32hzUWyYT`@qDnZBe0Y{y%$j z5fdDFm_wpWyX zjtj0~Amc^m0t}bqBGK^TIkHVm#r#1ec!677VC5 zPw+x2^C7X|#>`^?Y!5ye2-%uYU~^b9(%>42_Odxe-9WPo4__DmR&KtA9tU1_3k=mk z#$@;l=r2J>>m&;E3&cg^juu~9H8ImUpeeSo1H^(JH3ansQp@8GDn@v_y#;mOk9b8_Y?Y2glohhvXq`U7|yVw@X7-$O% z>t%fe{_^@8c!ZR?geDbi5U|ngORT_tmn3dY*@1uZ$v7@va&Km$yX2m_h?sm>)3-p~ z?t{A>RPCTD@I=}s2TcKDT5X`l#cII8`}Ho?4$v`1NC1XCEy`k-;%n!hXT4M~SHMO$ z*a!n1N2T;BuJl$18Cx+ra*)`HZ*(}wvsI^qjMq462LwBIyGXGdFQhDT?J5@;b)~F! zP>q9n9W)(?6Bq!P^}L)4u2;fxo33T()2srwHckOA3Tu2g%ZDurw=`ZdWlLix>9&(D zk!jB5w%_)fJ$aoX@tW*Fg%r4xjG|4#%s~@Xk5pCmZESk?*Lbn=CXqW6Q-4w+Nv1W{v%iO}o!WqT8GC-(YuNh}l~B+o&Sfq1n#)=_huDz_ z@0CA~)SSiP!p?YVUg1^{_yiJj?7+56=zJl~wDW~7v>g_}w&jA*wqS7PMLRRf4w133 zLM_nrz-mIe*E$8G(*u2ge({fm2J-NJFIy3%0_gBjfSc zV?UZOe|^*yP{Cik^yI@Y zr-A#tPk6uaKf&R6?7*vh(Ca%9<8{?<4j9D;x4z@>_wOG%;JTH~cfL~meeR!9{U*qt zy}v$SoE}_yQ{Rd3=dK6;MCv;Zf1Z2bb$eC#^M+p?Fzyb1{U*qtRR><@KMH@g{Lca7 z_(1B5tzhcC4(mX7AhhWYgidf*DoWH|? zCz)lpJy~w=5w-1s18v24_pyET(fzg$#*q&vA9$VqX#KDIzYiFX2g1+$W$*s_mj_(8 zgOAT~=pFwPuitg|{|Vs_nN=|`2);Mrfx&&hu#rWD(2KhQCL;9yfdUR}=rr#Ak$aUF z2S?uh;_)%^ZpVEG+JJ*3?~vK!PrUEN580c>w&9oqZ^ME1=ke(=mKUG>_X+djoO=(H z5(iCxj-&rw{U_2DzP{s+UjO~p|2xO@hiyMU&{iD0{xJR)v%T0bM~rR5VF%uZ1MLrc z*S}+V>Y;y|uub`qpFxei?YY|vLY~f#A?lMqJy4>S+@3Y&K9+<{`zLEz9%7Pg^fKHd zh}Y$}TAi5rSR%98&cP-!9J?2KOYbMc&FX!*4}QolZqW+Oq^?tST3E|7I>%l`2|A8G z#lq{{3EcjbwF`jr$MaKOo(@oINk#`8>ouPX9P_Z2Lj>1*SW7>G^;KQZqEG2Kc(sMx zuW9)T*R=R+TR1Q|;@=-8OmJYb{DRar#d6kNsmV;7TT+)?qLprU5?oE|Pzp`!v~aT> znAV*%-N3UW)ra#xr<$L6HT-a~6iw+>75Q|Zh3>Ru;S^<4dd}&(h2ob=12fvG>lU81 z!q)xlT2mv3SJ%X$fvYY)M3>wQ_rg`)o2yT$oB+!gl4@qC`k3EmN57 z6@QmqL%|evzQHE1ZzXUSqwYR@^i*lZc~Y&p70#2ghhr7(Eglb@%STv|#V2(lGq*bT zt9f*RrS)uWI8+2o>*7SaBa6ovkK#ri6Ff%UBZr^O%~UeIl#3jfwxt_7(hDwjt3Vu- zYPcj7XsHqJ42xJZ)vaY|oT#TSxx8se7uDQCmZhmcT*wkB7-f}YB|+2BZ%Eye4#Yle z-CARDzb5Wx026S4K<0a4bkIyo$VsM7R>EUW*Ta8BNyp}+<@X(4qK1=|>T8i92z(^U@3Ul1KW{Bsrwhhcf?75{vaC3f$#(L_QA0z5qvp%r2Ma zN${ej6-ZE}wuFHrLFTnUyeASg;U9z}pWQr0g5zOhdWPM6hxZ?G6`N*i2smsR6_j>3 zDlnwoE?Z>nXOfP!yWZ3s?oM!dbb9HmM7lW!(6Guy3! zEVE4~GSAJqh})&pS-wA3n-nH?bHtX$r6-NIbkn`>%lcI_s{=RZc@1G z33F@icz93#Z^*~BBikC}K?;9X)GYCzoPyu8M@XA-x4S9o-X@$&HBH?{OVlvhXAHeD ztLA|gAqaL7YUzMN5?B*s3I#%EUdW_ARzBBns_^mqW-#p1^c@OOA0?-;Et^yvqz}0J zUCa6?Qn5#U6cV~#R1jpY7a18j97v9`p1TEBv0iFi;9S|1bz{j+@lple`AkWNB+qE? zrs7rBVBb3f*E@}+y16#?eQ-~=GT@&3gaVnKe_&iPJ#`!UnSFs|FYX{25O&xcU~Dxm zF~+3=J*VD^IfEyC-);odX-Pl;f)UW2Gw6g^{rL&$tygk8g)mpIGw!OD%Ixl(xl61 zk~LLLQkQT|ass4r5qVo&-cFjo#5e!))Er%^?c2R9e*~Rve1GYqcP@I2RdAqKN!R;| zlx}KRPnsI;`(-&V5w(8%!{fQ(7_|?_t`ClWzkHfcU&$>v$mJb9Zh0jm7=Krl`fuT` zs=~lU7rMj}8Ngh7yDWBWce|qMEZyi*de`6)Xp_<8sP3mq2zKr`PNiXXIaPwosruaI zRQML$xlFgEBy=+s1`B4XE{5rhRC7CwZZ{cJjj%;igc^jbQb>FsA!CMK1#9e@L1$;& zjh(T=?ioZpx{C&NCzX^Mqb0j@k6XQX)TLfrigH5fb#NoZ30C3y$S@(7sMK%`%n9U; zGN?IG*R;_^>vfro<)1c(E<1<2e7K59@8J*#fqxrY9qSt+{ewvNX!F!JYEArRH_eR&I2ObLG{%i{fG9#fk86^+vAnsdoKU6p^LPPt;^#)z!nNu3{-$j^zD-1S~aczzAF?iIVOZiov#Y)$-0~5 zM0jT+yh*hhQM`5KQ%^0&rStKk`WP;qbL5wvBdD>jA2eJ}Idx*VJbl5dkISxEg}W?= zgvE)OlzE96QKnlVlra&(5Im+KIOA|#aLX1d#%^m&))i!%W;J?wM~u2k?^1@|Mf7xN zDnM}(IlUHok;PbkQ1G;cy04gV{2a#fjaU|MbSl1)p>-p(0CQ?~z6pho(qD*}nKRv# zyx+QNH)*RQVkO*E)DZhKen&huL>X!HQ5A;pHMwtn1YR2uIH^l|dy^81cITjj5^xe} z+Z;3th)s%WF_Al5WWCEW;-Hv=Oa!=*8aa2lH1(0lIcrYlIaE}R=U~}>A4*Y^jK7v)8h9WN(rG2V<=j9z}zo~FC$ zAm8-$DRQXkJ%nIl6#*DpgDXJ`nj^!tAdz>3V&czV&p*3+>kABox1Lt_gF0d2qua2q zBY_QrgI`2eJgvgn813d&av#5|+`#r@>ckHjQ{P6`WV(3?T}0Sv4sQg#-HLRxYz(M` zdyjKpqG#dpXvJ__G{RV1E9#ibAUp+~0aClwPLq-tV;nj%kb#kTk(tMZj+bGE&7*_c z2?S(lOm-lkunyS5e(zQUE@PR6jAe8xWZ}iBIhsptUsUF}K+~aRgR&w?RS!oxUGro_{zD%6qI zb&j?Ulz+Y3P;{*@j9f!^TqVxt5v(}>kl{CbiE*v{=5;*AQ$Jiwz@SVWA5W9t0m>hS zQCPm-QMrG4pW~y`H;*^oDr&3SZ=c7-yIR-K;*;|P#VMn-3og*>mtUa3JJOJpsQ&cYBl|+wl8NZk$QhlAd^ovwqUn_2m)NwDS z?w)mWN8>{~e0YyA9=UW^B>F5H!*AptKjNime8&x(@7!G5O?4)9MK~U@%-yD*f0md( z0=7PA>bzjP*HVe`v318M4=T3c%1ehG%DxRc%W-tb|1H5$qaXT0DXl@s0&PVE&(d2H z6Tx|N((>vv;)|w@UmCT4@riLzORHsU>?c27-PXy+8h-1f+_L65g!8>>tp zf7!e#I-zl+(i)HA&`#KRj85oG$M;v1GkA@&_(7EWd(jcXVsY-FX1NT`7yGv8K;7}PYgq5aczet1AOx5=aweVR8CCM zB>o}8ZB6o;`g^`Gb9;LtvS?7~i$~7e&TP$0<_03?-L>;8$O_%Wtt-SOC7cjkV?wa7 z@S0$#vd*YikXrM>9wZ$gQdn%ZIhtF5P`fL=o6nWrb?P;>+m%4m?5f+_J;2@Jew|ZT zWyBN%y|nJ!+Gd7C3*v4fWxhPFY9?i&W>U(iq5GEOsYZDbn$w<=_aM0p5*VQ0(%$V+lS8H-#O{xd3w5Cb}n=EH8E2f+vQ3_V~#Vic(}^vPkFeSP+f7gLS`On6zcM}uN3An_QNNK-I$^oT)PtO zZ}@aFbA{c7=FXor`TIt`+>}1T_DeLSKVG_DV&(Vkz7eWp)$o%TY7+K>pL#<8S{op{ z>Ry<|fVzcg44tr)^9vkBFiCESEy{B~fNq3&oXK++-?;TR?Jzj?#w8pNf?NwM-{CFL(M!m7n z0Z+*PySYw0`bV`UqgE3*8TH=JEO@`TV``ERx(}F z78$O5#Go-Vb~R4Dg3a;aMi;0uRER$M_c z+bY`B2{kdsGyl!?Y_W*3#iB*>Nh(`bxiolTprQQ3Rv$NKtj@Rt_{(pn+(Q;0+qCEA z$O>KMl4Okm2hMvU!BcQgzMiNAJChzr4E^db$IH3of6#w^36}8>e zR1?Rm2xT#?R>)w-u}DD|7dA=3&*B^DVktT4;&M0Uk^aqI6|eBBm}%`euQ*lAT1DP1 z`oGLNtnqc2zt1|{;Onqhb-2OT0k2P7k+}19W%ryW!yD;1m{V$ZWLm*35bYH(3&cws zVlAwwZ2&O;=epY;i(y6WClnLjP-`L)So|vAO}hvsJZTy!#nKF$4igSw&P zUhTjW*CsN4hhOz<`((HEgsG8g{AO3KGS_+na}dbSNnK|r(-+8%#^sU%m)9~Sxu&+8 zrps(d5sG$_2C|NrkYdHi12F-;9+;J%DkNY+3=$(YGNb|bdDsXB-0NXO5(~9$vj00} z|92~eSpt1+ZzNU8ZG4H@i7!Rn>_m&!%37nmWNc;O=K4^?sacNkGs zg!-c6Dd@A#nzGq&Z2Bd*Sd|QKvrDCa(j4ZJ;jK+!-fp0M3Wpw|FdyX8GBj%Px2VnG zbtYQmvZ@vMRVCt&-&sn;x2Zjn4HlLXarNwjM?^`Xs2Yx;TrYeXQU8f=Cc`qyB*UBV z`JN29YR{oYZ?^D;)8*I5JYxoG2X8Wua;GZ2b;5VM$TXy!L;vz{eh=wdDlNUFL`#3? zyJ+bzRMu4s)w5Is7&>NcxWO6u<_u0^Mk{dg5~NAxIgCB!9cU3;xrmwCcBUh7NFFY0 z!|v_C?v*!ktB8puNse-{_=q>5n@nRD0 zwv-eJ?(j8>CF_PG%U{4ma>Lvk-A0p{+eMQ>GR+)JWY$<8RiE6Z*TNU_uK|hW`{iv6 z+@>0VhKnU(3)7hH?MU@&WMYjNIi1OsNT2f#3GnsAMXJx9uJm4>ZL(tnUt%bHL#?}_ z$vIPtr_Y%gPoICXMzSB!5V$`7Rq|=S(yR3S^Jk{Nd@>#A14azhqrN%3M`{DE1M!T# z%wBM)l9=q2z+9qz_1&r}8dW%mOgmK8kf|BOuuzZ)&wPiHg@VYmGpEN>D{6%W=3g8Z z7*%fqhRDv_+Sw#BQ{R-8Bsr`*Yy#*CIWc7P1UKM5~*&%Y-z2DRJUQapjZ@*{ayv*N{=}^{yMYkn;0~6u^u@z zA@(>^W6N%m03M`n-Iv$CZ_;8M)jcDlx`sT-x~<8`N4K#1U-gm9%54qaU6oiJ3??EC zyLEeR>SrqrEMPnG{)}l`+Zm7OPId)?48{YTZc#$*Mf1t*jjc3yJXYWcXl$@+1V3;X_8rNbr7*z}loGU`%F! zg-KRFRYj~u!*A5H309-wH|p3VQs+8Ea5^^;k*%zHE`i2IKZM;>erQl8vTkV0n zJ#4K4UghCxLJ`bR6$!dkBMj6SidADpkf*=I*4T6(*84D_a7*mMDO+M4Rr!?wLT;~$ z1-X3|dcFX;!-8J|xeNzgEhuNi%JayFNLFpiQFSBJ+S)kY(!w#97{^^uiBl3`g8vq@ zWyf^nT}-zbNq?1VRmTWBAH=q=dcE29Z$74A+ehy4R{vElSf;1qb0gPcdTzG3NnOY5JdiNcj!>o(xZPjk>6-k>L`zESQdoy% zmT&>_mtWe+3OsQ2ABhS==a2 zb$6aS!J~#Ks|1Jg?ov}Owa-Bc_&}_5JY280RF+s{76qy#9zUXZm7@4Fs9TKC ztYZvk4Th=YETwgj_7TD_D&`EuEYetGI*mmnexKh7&S&JGH~i2k)HC2xLz3+m^nC*{ zXMF;3X?+1PXMJFrZ$C3$|EaG|yQcP53)j@%r!eYgK>iwlXyDs`*dYEW9D z5}i_@;XR^Y0hRdv3=xT|LIAP<@9*3@Z%JCh>wf;9HJ^6QbMJGX`*QBN=bn4+x#yDZ zeuWux8XFoTQ-swMgNnbJVsqc;i6(VmGpH_UmtI>ABiS5wOE>g&?=Y{oii~4zk@8=f!*(pp( zlHldt+v!k0Ek(JY;%=U=(!7CrySJ-G>-6{1VWR&`J*o-7KvH*0c32 zRKI0au=Is`fM}LttBDP`HYdm7Rem3Mn*F7`HkO>9Ob|q5!71-<)57=1iNGML&XQ$@ zSP$WAT#@0IjSJZA7q+T;Ck9@__P#9HTa0BFlj(XzOP01w?Rv$x@>!V%7V~ipI_%4o zlrOT%7<)qi#(qxKof)@KCKRZ(`=&5Fn{tsARFO!LGDi;=S}O)FAjBeS;BdXXdO$ZG zU|ClU;Hc4&0)e^kB=iy&(mmK*<}s*DtIVY}AvZoUYd|V?Z^{(I$`m2Klb6PZ^oYJA zGhL3r{ZL%i0llQ+2Kws&ptRmXnFIiT!%2(GtT528Nw1-IAOqlfMaiyQuh<9R94Ws+ zDyn+zNa5j|lZr2N0j2J>i%Vo8MS#Z|(bQ@enl$WMOE7d*6S(X`b;r~J`>y_Gm^^v@J8*ts9ng5L=HPxhq zK#X2j10>L4dOF6p5SHi*(^tI@zx*1_G6Q;pH|RYEwuz9bTPRSQ%92i==`EBQvrvDf zmDoRSp@C`(4NO{SbKF9kEBF9&w0c6+CaO?i_jyEWH+Q=aItSFTTC{UFeqhf@%xX`!@4ZF}Jp#n|VWq4R=Dwp!!4E)-p%u$z)U&io1-fQo}Bk)yHv1fjHK+kfXUO zJNAr=ZppT=5D5=BD@Xd^NO^(ojiLTxm98uhG7ji^S2@Y&v7wNa-lvKsucgKO$`#F+r;!33quN-s`rz6LP?%+looef zWY*5B^-kXX`1jnv4RucfAd|wGnxbldkm*xZqWnvu6>5vo)mU(~V!^cxTO-dvo;2sM zGH6o5HA!XUIY<8NVq;X<^PUooKK01Gzy=&2iaS13wQ`c$j8m&I(qe*Jll<1Z_z>_lZLdr+FNJG&D0z})z-bWp3%<2nJIWhxK;(PaJQ2$ImnjRF9x_p z^w4!$M3?Jl_jjJsay*_K`;zOgiy4J+bu|Yo)?;&sjXJ!CNO3srm=<^1PS2< zuhy*AK#Vlet=f&T{i0%u=buoT0&z)da@G*a%cP~Npfo%FSl^gG|0tuniM0|4>vjAw zpMv>$xG{UEnc)C-v?w*;c|cuKejB`WxD2mz1HDJZPOEj z36K(AQ}cO%jxqA6(+WIdRp-i3w&TRja{4ij;_Z0S#!&p4y%o}{YFwonSEEkD*Vj?i;M$@T+LlEq;Xw zsUSqDN9sAV!BCb&Ayy~-gA#<1S4ts<7SxdGl(Ko{vDCKp#OIaAS|~_)tiEdlN`hY@ zSj+Y(nJFv@Na0BzUgN_RKyCK)3ZkylFxEy@*V}~)`yr+=1 zG^-(fOMxngO&zm)vr4hLQe}`xFoKmn1r3Zm*3{|o*goMJ%j-4l#Bij0@Q#!rp z8#ZlTmir+!6k-N}PDt5c&sv1rAd#5T$_LZLluFV=?oLb@(1S)(_@dHL6iHpd3mI_M zi@*~aF-Z|WBf!?YT3ItHRu?e8PaLMMVezxSHVNfwlV77cX-s3^PS(yi4$A;-Ty&#G zXYNq>Yo|W54p2WZ-QK%2*<)%dgw_Wv&vlkzs6)tp7#@=!ez{G~0_&u`Z(_cke+0ns zz^&geGaoQ};AJuwZKD-=4knsM=>TVPYgZcu;gyIVqUIr0PV9>%-zFO|<>{KatD-F3 z-)n5x93W<9OziuVR=VU9inKkhQKOXlB5UExO|P!eBBW@vjRU213nu5_uve3?HNQ4@?aKE!bqz*GLxoN}P?p@?H(a=CxYqxiPc5YQNvvz2)es5_4+J?&@ODn4jHc5KhLb zIJ66LQ)~Qa3}`MHCnts5eR$G`JAByq z5bwKvI4Y>|=fmPpHVn@6HorZOscv(d!p(os&y-%bsNSiE^M1U-8+m>xg|+fdRR`p% z7>0XMu!4q|qc!bUOQ?%%Lwg-KR9x^|E^X^y4bLpk7cH zeVZaH@}|#AZRF#Xiis?I=|@RRf4TAhu0=Qcrl;m>7#f>#=FVj^>>&B&O`Y*FC7%6gXBl5Ra3;&hF9_5gbx5MHAo%Nx)o-q)Vi|K4_(g|e z1#5(v5>_ICUtt@cyx-`<6+nqZTLh`I#;e?NbiGc~LA}h!*3FS|OnguoDFcLd6ZDli z3}S^aomItP5LQ9DY}~@mFAC~OJV7jH!L}5Ih6MhCH;9Rd8@o->vT-Y_H_2FY7|W=G z=BbBS_NmT`AH5{eTwoi`NAGF=_Iyec+h|=p8tHkZafEx4JMS-bFmq#`zH>LZk@wy| z*~mK);6~m}SCvY*)9lIW87nq}yUl9hQk9edo2Bq%#>I!PpR!F`#bL6O(krkwDyUC< zSXfec$cOj%u!e=wkNfbT4~IUy(TCN|`o7PHr+m2Aht)HB-%U98CIX_Fm|!iCrYNkg zR9G4)g{?aYYvH7DmX9SatFjUi#tr%|Wvwx3-|y2a%_Rs%szV*gv_h^2#>he_ODGPM zWq}$KN)z7yA~%idrEDiPCPZ>=1~=FuSe&Qb!kfIinyqFmqA|3Fc&$ad1|qv*3J7E3OLYpk zzSW$E*gx)*yADN~QH3Xcr0Ye^akQqwT64J>7Mp%U>>{d22Ehsis(pavs$-3MlayK} z&Ku%hr35>F5o=j+ZDhw*zl^!Mr{)CWF@kHTIl&zF{SVN_#~+Ea11#2MoU(eZcTL=mUmdaZ^6s zs<@XlC$flWgYnee1bQt$#5t^G%O{F{<2BJK=M8Ua9 zp3dRK^Qip%NJ=EC#;+z1Et>6ApXtJ_DBU6cVkumU_ie1V`@|zX6Z+Df@ta7NpYhxB zF|42OGWt+|yRN0u3b?MdwiGRxXrj|MS)+x>1P8r@LJBGAVdMhjxhtGyt?y#tq{9wq ztgB>3M3uF)8Wm7X*DkX0R;TymhR!Eg3dN}!IKI%s3LXr(Ebf~Ow@Dt_Ig-en73*Do zK3)_rSQVV@U35Ipt)Mjnm05&|H>&?zI3&WO^*-xUJv#I!Bsg8-*(d>jihAyI z@!0gcMKEos({s0rhh3Q-6`vwJpw?-EHpRuvtq5015?Di^9j#w-=Yz3C@47<0X)%~- z;`L`;ZsxC}CHN0l=J!;M;NJ%MwFdv2q{T$<*Ea)X&2d8BN5_Gh$!(<{>3P_%!Rx2r zM=!nJH`cIjxswzH^?Ff1HAYv?l%PxXQ&mSe<{}L4Pe1k5>FH+CPsvWRR6liNK|ke; zjfLT?%3*wts=Z9KW5C(;Q({riqJB!*KP~;#+_h3_o$LDz&bCuWcx+uE_3Ij`#=C_C zbTIAKXm24;c(uaJ$!!K5lb6(zuypyk9481MQgkJOREOmu%_wwOE#XvYg>dDe$#R8# z+vCgH;MD21Z@#pSZ$;w?hBJfJRhN7is@^6>^z;OptPiQ2f`mGA-~4;jGns+eghyPa z8i`Suz;cIP5Ts;nYk(WZnH#EVUpKG)!6$8aup;WCB&jk74Z;L~l1;O!fgd^ltW4*| zqLW`mHbyOQm6z~m9?D?IsYIn;Gx1BS z?X)Zs((y}zbtg6kO^cGWP@Gei_YHL?1+zu-iW9G49`Nyza%sBp<$345#yj^4Jhbo;Q|PME;4c-qK7KS~3ZX(~J5bZuph1Up;j~R*IwPTUVg?2+ zv(rpL)8Rkp1~Q0FTfxuCaAKEbYj9d3KRaruDLbWNf4u7CSaWb%v^hArx-~eUId~`2 z=@|B7;+kbLDD3wie_`zR41hameA$=9etGkVdvk~098H_T)%M0Q73gsE&75`M915`M60YB%6K<<|~$D@m;xUSiYK zZlP2gfL(+o_iL4#s^A0aTnRXuqGi3Mm`uNtVbi4d;RBo;$0kj0;L6)I0(H?tB((;_ zG~iLOykWn8u-LFu^nqH2VdpylJI68U&9w5g0QWLKkKskXS=lYP6>}ps0`u4v01T(p zmfWwND}1~&H+Ovebp8x{(7gMouWO#>h(h!3Cg7Sk&J)cO!*b{orO?nxA{u(P4+#X@ zt^~B;hht}0*PFUpY4Hh74&EAqs^m=%w${_J1X1R{P`v~x)WQ4KkAs1tzTTqx#3eJ&Jrp*91Kexi<=qMo(}DlBEcngEHZg^=c$ zRbze(p$8JHQ)qWee8ruH&W{2mgT(Yc{LDdy(uAVYMlhJUwGkqNdbQErIH2qZMWWl= z^)ByrGF4%bBWo;jpcjCvK^r%u8FbmiEt`=ogj$0?gVjpR!G;L2%K!R&l{7F#Yq;cAz1Ifz0{}A@Q1bD?=|~EoRvBxZeKwO zWV~7cZ?>-59WJulMXD02eXon%=welSJOW;nQBRS>kc-wlPH5PL#PkVeU1;2eu6Lnd z6M{-_CDfbxkQJP|jR5^s0TL+iXD$>Ky3(l!+-EP>yQ@~cy6XP<+<6p zhe&{Q+{LEQYpwJVYj8P9{&jlN&skEl6DJGHymmCQ{^bYT{&7lKAanY|$}+0Rxwbr+ z5eLak(iDv8jbx)Em8yJtpc)`-$AH-6*IDdHJs`K;8f(=eK|4_}TGvf7$VQ@$PFfcvvZGHo@?oJO}W6wva zpW>E3#nh=U;^u~y&=5$V{-nS}UkQVOm;%A}V*pT>bx+{xU*+mw~^AbMm#f;x|YJpTtgh9&`4|v zu)GT^nTUq;O}c;FlB6_p;IWem1*ty+WGhXQye(>N<6xw=b%-xCT9U!C@2C6kCK!h`PJ|k#iKOl%`Kp%4y4xG&Z{z1J!9C3^@Nhj#ZE}*_;ZUlr2z82& zBR%sK2`^NF`&1K0)j4_w0=OmS5*W0eZW?WRk$Z}966DW=Tu6 zL?@8KN*+ZyJhB(rID~of#mV%t??X^2qKO(LY84bnVL`w4ZPWcCl%U`2J%ZLzESSd{ zdRzA-xq${pXuYlX1&wz@sWhkYr(8rwV(^fsQuiJXjTb+vJN82)DoA)E98^4Ls?T_cZ3b(5D( z`gtZp^#L>}RTm-am>@Msh!WH>y{RpFwSFW@0BXKXq1|(KFk;=2X&nuJaxLWl0b3K9 zl!H9v3hTET%=-Zmm98!-DYBFjr*o++DGG&$tw6|v{s-H(`x>cKm0jWh~yE1|Rh zO>3mG{S9 z#kwjwj|QoFntgy@`hIuqXj>#sehf6S=9glU>#ti~Hqs(5ZxF7Zbp7_p`0QFEF*kRu zk)G6*cXyUEK%(wyFJXR#W+vV+=Vtbkf$qSbLo=tzpHIHM<<}?~^FCtM`ggy6&h@|Z zeRHmVaqmM&3?$&7&S~xxfhKNxkT?5b&(z3h3gMW@7KF0xd09G<<=8gYeTz$-8b zul8Y0M^ZCt6(`lvxDWUG@T3oK^kIo$(hP19q;^rDkxJnznuUs)+wMY6xhps2A`w8^ zCzT+PK+jo~E~T$Qr_PmYJge1gMnp}_!%L%fQ{^lgLA#wQO+6m#* zC}kZIwR>35h^ad{#~ZUWvz+qddV~BizagV?TlY}kEoA3t+${%+$NYE^-t$M%xTz1& zR|tbF=Q3GfI(4lJZMy;JFU>`q7$t;!ItHMYBYS{+5dzXF`DJA__<q4HJ_5Lr5J>N_A!jL3L3dVbZR3X$M?BQm9je z7SRyVkluMBO21SpNW~nmDj1RSLKk0-3=={5S@&I*=vjL!cc=2_^r)&->u4|Px}i2@ z&Etk7WyR59fauIr#(lBwMLg}k)!$f@BFE)iY3f>qB}}WbqAMe zj*{tYDeuE`{$NBG;~Aoht9Do0nhqqm#=Mp|I%V4%fS&Z+B|4l+WxPE+4NX0_6wuUl zsHfxH_UEqg9Y2|S<5z?6WH3c9mbBmB5F`#GPs(L9aP`M@^jIBpK-bYAN}Ug)egh_; zr0)=dA|tFf3)UB)li*O(U%`ILgr4Fs`cgqQ(Bz)ZbF*Bfv%XAH?) z&F#$JW2@BRiRYFJ>FJC`zj_&h`p#d*S{D3L$3V8!c zmc0j%I|dv-N4(&3cTXpdW1-C1dBK?v%yT{IW-sovqOx>oomIWR-hescaGUvm)fg$m z!6-?5<6#vjOL9pzE$mvv_ZXRQiN;OzikL0Ea;pYOJk@O=BYup+KWo4=hImHA3NV`c zhVbRs5?=|mOfIE-i7Zt+UJAc+p{;aEq{Rmt0Z*O6W~Zrgy6fg%+x=149jj)gu$$k> zmhjGB$66Qs+9vP=2UOLW#Fo<`lGfl>^d`|KjavHVz(}f@j{IX}ogoisz76E$)bPogav&nPOYqNI{+HJ9m z+4;m1_17!TnYF);I$izsD_Ftijo?9D*K*)CwRc+gwJvxVViw0;f+5Ik3<8CWh+It6 zfH`*|? zWfPjoq*QiI`1e}Ax*=Hi;b!a@$z$Dx*lw+|PWr^Fho>x2r*( zt7FCtGju&-LuCek&z;U{q&X0i!+wD7b0Zdu^aD-tuP%&SomCH}Gh%+ppmina9TLln zJI+_t%0a-!gu4kcX#JQ7gx9Nr)^+G)2XRBOB^fjh(QU264Z#K9@m+tx_qfO~i$-{q zQKi|AL}NUc`N7}8){;R z(3eWz*jbY(S8avVIec@g(@Z6#K$Pl`FOuu8TTwP3O6}vGW_dTaJh$b&_c<^IU3}*Fu{9!d)4*8gj|&E?9tR$tEpD-YDBi z#>k|^BZ!TOI5QR*Uc%ZP)?iV(I7q(Y%s#6;Srn`5(q!@#XUQ1)WNNmRzu=+NFgv^G z#@u=pmA`m4HEtmrg$SdQgqU|K_>4uTt<`H=WALzQ7ZVexwJU~E4!oLBOE56PN9+j< z$UqPwO52N(9d>6XEL?_w>>TeANN<0O3*D^M_+TGY-?1?bV1v2cLUz$E_m%eQgWiG70NlfU1;A$1768c82e97+ zO;7O1&BS%ITi>(q+6I<7EWxsN9#vCV>uMgm-6QPFawiu1RI5D5>8A381}zhlXQi%- zR2|Hg99g!K*Rs_u>BbJ-rwYTj^t0GuWB-Z%-V_w53fr0Lt8Zvp`zm)XLewRmbM}(= zt>lh+Bb?KmKeJJ*oFgnb3VBT7lKm-kfl;bhp=fl0$3T4vp2M*&*yN7X2+wbMRo4<& z^9mkwcS*a42Q8lU$D?rKAB9_c3DFZldL$}zLuBod__7WhB3U-I zjf2`ykJK*9+AY%_y|sTPHiN?sUqO)_3DqeMqUr>IhR`ol1toua?+cMdQtNOH1L^DV$hG<1L5??u1Y94ML@Z!{6 z=hdT)4*)OF4s>tRS|;PBb-6K{5Ericj_F?C25`F9J3l7fEB^nB^P!m5zV3dt3NE37 z1ic_JjKUK$g7Y@(x{)+Zv#45BO6IIFB=MD>E`Wq9}ruZ8j z8Kkn2p379rx$U@2v@0{q#O?`o1u!^lyQM;fdgn}8b=khRUNGO#b)vdfRC_K5PaHxG zV7ye){7RCO+uoSRaV#CCO~PJY5*n4{8@3?Q-_}lx<{P^qtM?e0i?N{15+wWJhPnn=t_9>+~MQn-#nBTqm zeirtC#Hx{t0OtDMtgXY18>LrQ4BHD>0!ds#<*wHkng+yTh_oR%TC4Dno)j0Rn( z+r8_vP@}{t<(L<4v9`9*K)1bL*^WfihGdkG1f0yw|H+6cjD8=>C+tReHG-<^)kmr@pW%^D~Y z>SaHg$LjGHR?}yTT#o{6OM)LY^!^fJ7G*Nrj9k;(gi##Dq7K{~v&VC=x@;XskvE0% zi&tHh_?V5M^h5YxiTcj>NNb3Z<|Hc;F$xSD*>e-!ibRu{R{4)1nlai`?O~mVNx>VM zxa)EVWZ7h|w{_o~RtdsP35=JcsiCHpk@ z8dsK^^o2tt&7G&p#vKER`(q+bnSgNt8RUM)&;AlXD#k;CT{)R;Cew{^R@xk_mMdcU zDQJ|Eo%M)1Mh*-b=^UH^M;rIB&=?eLPD4WB(bm{+%}en@wkN{vQ$oYqt*yfxB&wu`vHH!y3G?oxZEk zfX*yi5q_~x3{}Acx?T*MsN{*+GYVk#tOoddL%rg}n5Js)Fx@@aEhF$ZSfIn|}u{J=|#*j$Km($JZE897jqc7fVw6M@GL83OxM zV|pI&+Sw4O_hEQz0fDNh#(QK(2H(lrJv|nX9>JlVXh9Mrw4ibMbg*jOiV~A-boxYf zG^}nVVoCR34(O`Xh1V6tFL~&?c}uRE7fJn5wcl;z!IK`h2=d2c)*kFp`e*&!V5eE0 zcY_&*K{)eY_zgEtt1x#ebXJ6@(D28%JQE1Xk`;ZuLO826+SwPGX&Wk!jczLMu(A3O zo=V2&KOb78sCUs(BO0K&^Hd5f*MM0GNdv49R)hfUtEnb3%&HK=opRn!;Vr>$*m; z&KHI6o|m{93YWb9v?%<8Tc=a_tf*Dbg@3;B8ANTC9G?!MA6cn=70D5*o6SWjc5U)= z(QA=8MCzLE1p+(NC(}gDN#L|G!K=8vYOK%6!2z{t7kE}#Y|VcezQ1Ojg<91 z)H2)8QM5)J_UUp{wO^BzXez5J%rZ;;NaY0EH4qTu>m#*Y31t4&QUUg-bbC-K%3lj7 z@hEQy&N*XAu(#{n{JhoJ!^vUUq~gQ>I`pEE)Jqr(i|)<62=H`A!E#m*bMG*z5pLWvolVS&1K~Kl?fPc|2O`h?@`n-}%sv%%LS_xYFTp`>GadFsyjBI4@Y*qg ze!fcvw`;y@4sK!bS{=UilW^h5nKW!Q_IJ!opG_M(O0w=2`4m>e)!_p~vC0{C|2- z{2iEsAR2<3ZCqUabjQV4HcuZHvtq)=#SRWaJR_KRx( z&31RaV`9y;9G}v#@Y!`9&mvnh5ho;(NgEToPWxJULO!gZSj3MQQD<6h-nR0;DO}g=n znt6%t-_Bcf2lB1m>UR??5&ciJHBLpW!T~Cu__73dL812HxO31N%2aL=r5&|gHrm@5 zP4up<>RowQL+?2+NUmSoUeWoF;Bj)U8oJkBN(I$fk)BhuN#J`c((`&kWjz+@c?D7B zy>`WM=)#__@4UV$vZFEDi(Y3(V^wd{>43v}o8Ad{L2uK$(v2?+n$A!YM`_}oNOV~k ziLOM2bvAk-x8W(I7Vdob7Grxq_H(o8b7;q$DK0$LQ`~DluCCgr9_LBulSFYp|JZ(W za~50jkLS#_5>TJNtRg12+i`7)Go8SU&!~xo$9(E>aNFZzOawbhA9xc3`P(%aheMnj z`9}VD2lXxc(7zVM$La;z@z(m-e3L0KssLWih7CF|b~^X@fWllz@_S2Myv@AA28iFy z#_+IRd*?ACbwc$584t)HOQ-VUP!S3c1miiWhr1uaH|+R-mcO)y zm^K9*lJNCdj=t%bVNc%n=5>bKJn2Q^${>Cgh^cDQzP-pf30a%lRuI&5PVZ7&%r3uB zd-<0*6|K8JL3&Z``cA5b7z7xqvFV7?Or6CPmZxW`&NqaY^f!o4G4cOdtEc_ z1oMATcBxTd;X1UuyGop?=^%5vzXL(u7je9%D$ChozE?%?ijP_RCcD%}4iSYDq!V{j zk6c54MG3h$NZp@ym;LyQgSHY=esRzS=f#jNP`0`|sKT-@-W{}%aJuB~pd(cre&*y) zS;vk?RT>AC$AI!9H*V0~cO)-}hm%fT5RU-r{vfSllQhd9ChOcZgLD@hbeOEtnEb33sJ4UWyHft61zOpPS|Z2$&Ah=XE3%3zxX+hAYNM2c0dF49w6d&VI^!a!w zPk&HOJ};FE-fL>Qsi*jLFHl2TWSw&z=MX6_J4iv|XoI{|xX*{(7+_kkuujrPTVOxj zH`GzMAgXp#O^04%8rE*mnOZ5E1mR?6e$OV!zOXSln60l-Md(oxa5CfU%UUwL4Znxi zHdWEyFp@-Ox>Rf&C>Q6dbxZmR<6@eU)LCj`1;wa|rpB?!>pxX6IjIX(GP7L)arOB9 zG{m(8R~Q}Wl7K8(bsZ@qKA0&@EFv-|QW0*31fO+WUHb2H!_~j+D8-eVROAD4oLbJn zmEq)I;ev)InLNdq<~U>uUNUtA(tNz>D)#2gnbC==zT_u&iA2n$n;maXpTcJD)Pa{A z%>n186BWFnr(za=g)dO=IRM*1I zf)^qkuZksu3)#dwyH0(awfA^r=UIKl_)D-Km_&+hW8Pz6sQ-heb{c#D?`pIpdwZr*X*1@^Ety$aEhjvg%^mYeo*B_sh(Hbc7GGMAhIdk3G=BCvy?qU- z+*wErS@TIg`t6b=sbZ2wP|T;Qfh_bdlP5E@-73P{Z|gDX>X=--J91f6m0*V0r+3## z>V*gLNyg6nhl?MVq&gB(6+6V-^IBd;qF4x{jzyEjBbGj?arccsno#E5N*zs-d8Wf2$#@0- z+sS-2nQv>i>^8R<7)TiCuM>!GR~c;SZHZK!!t(0vtbloVF*_=`0Qb=!*K(N9oLmnyDGIgs!ka`?|tTb?^US2(Lm%xsZJ&H}I?iRpCiQ35Fn+qL7DCZn#Kg~J}xH=5% zuMXQ?9k#nVY%eG}M$C}KP9HIYimmPMGmz;v z;CMu^ZHka;1F&*48Id_7sDl``()A+z**A=5=na-~8!dqwdC?^*wnHN$x*!rgow0N# zW9j{jrOj?E4Yb+Ia~Xcy+Q^LL2?Lw!3=G5!^hXV3Dgb6;eJYv;(YuIQJg~Dix!X{d z+`XjQs=9kgorg)m8Gv}AR~#LAZ7TyzBUgue;aT`3jobBRXK0_Gh+AA^+M&Si@)Ckd7e7#I1~_@K z;xx&Ny!mmjy%`2L-^{;h)|-9l54gA0+oN=1k1`8CIeAovfw7C;?ih+cD;BFQXC|B# zd+FisG+PWKl=`v???-=9R{pdjhu|k1ec`?`z2%l^^6(bA!pp-&X9%ns|8n zX_^<1FRk0V-0Be_7}F-Ze5Vr;8R@4E>1VUDnVagsGzMpAkeUqjX?>|H79|6*2#)kf zL`k0a!xg!sdC;mdF^h<7SER{XB3Gs%-biFJ2?3F3P&rBsh+y4@_+V>(LgIbE1(twM;ZB)fbenhoq{E)LvE70n|Z?4k4d4ah5Dv0w?~N z-1B&)I5;+)ZryX`0U)U*Bky{dYb>?LS8x7;F}DK1dXfv1!n=%5vDz_fN+TTBnjg@s zj}M83>6MlWjwpUi>3QL^rFJZ`{z``PqB~YKM=re9``*1#%acB8yC|y#%%JMc!et|n z<6Ybum6HS1RedNeO)rsOz-htRP4GA)K2mwe$-}8-FOk^w#draxjPg3rj!D8O9d~b zZmI;*?fFHJyLDZQpO_MWoi?CuT-YNDFwuZq#C8-psmKb31A&O1$H-on!$(qY)Z7yM zl#{^O->-_?m3Q~%=&<{mnl)r`fDMYy6S;z{rFNnva`J;M!4FisIB9U zJl>z&n93$2ScSs%dM_exUA>_^1XZefU=L7(CbQL|T7vt-fRn6RS7TawmPX8@2PmPW zlCIO0lqAP(^GT%0vm}w!mkdo#qijcgZ$T~{I(QK`KHiJ7Hr!exq2aRa=cFs1M;DQ{ zYiO>vk;DUPYNjOcGtQvYxIjAvxNJDU7WBSwuOVaNms>eR*Q#euF*ZJ_7-_wpK@^+k2SSattFwOeGj_suJ{~D!Fkk#!@exRUJ_bYd5@GxbQC{byZ~ZlNj0g5nUL`?KDv2 zSvHc}942ifCwO)v`4m0vy)M#oC=VJvT6-je33}`Nnpd@AWJm2`GweHtam_EIsxEnJ zc#0QlG)pO@Q5Wn)iBp&cQ;$w@_sMNaNBS(^HP6GXhnrH9^pmn`uDvdD+2^$`BrnZk z*!79BRHWcWgN_-CH+rVk4ATgHTE=N2sei%OZ*Hd?{=#L%Hcqos-HvgoK(P?>@ff!P zIn9j#v3IX(c=Txb(QamQ*CpYJCvfWv8BXeB^TgC+PmUuY^8FXVp~@2OvFHwlIoQ)Q zEOh2J>MSwbT*E|vde#WZKdYbY8LAaa#ui=Z*3FHJbT!rr;+6zIEwCqe(=INy$+LKM zwX)Mxpsd7fG~$feXvAq}OnKxoe3hiLW*c&@&Z33XpWNB!n=ZA*z%SS47Xx>nWXl97 zqJ!L$yETw1a$n*{Ttrl-X<||(5*EQJJnq9Hx{0{nxDi=QseDRPs_zsY^Is}Q(V zR3+<`hviz8WPRk*RV5j`)yW{q`ll`060}t_l_z2?L87iDNG2n3FWY_cI*EE^QsE75 zmR_Lo*k&EU!)o`yEUyRt)N32vV+CJmWJ98}4dZ0SW@!!NrY}B)ft=S<=CPR{%Zg73 z2YIX#Zu4Q`$_?q8qlM74)?9wr5ENU%0dtgguYP@ns*-L2=$ z!uNmN2;oftw_Y53^UVE)S^NiIUNcC}lAgB!lbIGN%Uxu6>lIGgjoX^4RWrCPxr!;y zg9kbVtF~i~*CR?yj)O>a<|0*V4zf=Gc{ES5zAb z8poQ(I~2q2oa0C2+sg|^km-bX{xX(a@Iwi?8Dbe4n`%C54~(QfrMsp^uGZm~LoRf= z3w;Zq1MMnAS&#d0)`!P{d}|+Vtx;+wofxbZJ)5bLRdLRZl*Vi4tJ0R#7qOA=ZYE*glQeOKR z?GJdZH^e?l^kMeOu|kn`T*7CT$nbpjLJNG6!RdI4-~UDNE@qdXcBTEU_F)^ugyTNk zElAinS8Z{BDCyr10yV>lfr*rcfaVP0%_4FU7Ccy*lsPWDbEat~LuJGkqB#{-A0 z>~=lFRji`)rByJ_ZMc?ZmYd1lai!b_-fN~Cq(&`v19^` zY4ns<{#c~c=LL}#7PtAMOC7vN&7I63N9w-ExE#b6?<02iJ>K~R$JN@CtS45xRlW`k z`a2&lh7!f;+9itn*K*!z+|PDB#w0kY z6;|IP*~WVVXKxJ)7G6vEZr9MwQj`KHMj0+XkWgUI1>ALgBzbp?pZC?-g@U|N?{ynw z7#T$TcAuQuLCSyXrZa(`>vQl6g9fY4)|z8Ec~vdNRUaN)qK)u|R#djjV%S-czxP1S z1UShjDyM>msNASvw9%>;bI(@qIz7WNRel8HhCPCW6;ByWlM3hq1;!N^SI#g1D*^hn z5?}x-fkbDI@v}V3&(a}%GpMm@y#iVV!_(g*p_)yR>%gYA%%L9)pda<44NHIGwIOmC zPzzYL)Mve?)9DpV6rxU&_rypf1`G+hJ3M=8M)VRQXhls^eqpC3qU ziw_)=`xl;`b{#hPI-IqiI-sUf6;QIocvJ;=JcheGXWtBQV!O;(daVaB;89?ZfW}6v z<^mS?G|iesR$BY9bx0$xs<{TJerYp!mCYVv#O)T&-{9*+N?Yj>ueHfWpiEu117+&M zR=AnE3YNCZ@l`qT63lIQM{XXRpPsL2q|X6m6Vpm{&Ec&&gNT0UU3JLm$l4lQ2U z&@$M9Bv5NI!TD&SkysN%+t?PVYqDY!t6g(Uq}C z^c+Un6>c;!s*Lud7f{WuUZBVHLf@07&fun+m_aPQ3_6{WNp+_RQzV4EXuHLuZXr88QsHjGxQ-99%+*clOrFIxsMLtN5fGejG}%@Dt- zvn5Yv;mAey=05;#XXF-pQ&cDy?IBeYzmu(J(Q zwPJ)#m8?LW4!|JisPA)*z_)#5 zZU{W_U-yl`yv32k$Y%n9UFg6|NpA&*Q46HEw1HBDIn4)J_2f<#@}>EcIcP%Wpe(OH zsAba?PWpu*bXx~q?xbVLsGV?*m6{R3IJrEBH2V_@>UcpNlA0qeZi7 z^j}on0_{FSC_h_FZ%u_3+-S0?(i1qC$Vq?HymLI(5RA4g$V!Nnu|8%%C^Oc@WU!y# zoBO2d`xN>|xwkGD#m$@;rFu+acZWgWqjBHERjb;OaM&$e&TPB1j@?4}N=C||LQ7+E z)8NEv@wjp$+*#KDm??|@v5U&&tqG|vyvx`Jvyx2^GyG{?(yyM%zh{vcmtroWgvs(63UF3#<8f6yHmy|LWCcG_}(Oj6Gvwe9tlhMP10 z9#8C7iDh}Y6#&CO_Y$|-7akIvW>6>)OTTg(3qi{?^TL zU`>2b87YJOD!)R7_*H&Z1v46~f{cc73-9OZprw@z&FDl#mdASXgL3*R6I|or=^zX- zSd?jV0mpWaUXo}ocoA(rdQbDWIUuijy`pvTXr$+rr~_s!)BQ3Y`p(_t)Uo$|$Rv=f z08TbJEnZx`&amg(NcMSqKCEXnUQy;zjxNB?8dAImEnMkjocpXBIn%d(?f3y*Z()x< z#FD5|nc${{$0}8<8ec-R?2QV~2Yj zXH_?e%t?xsd_2&u=-U1^1LpXLv~`3a)YsU=n#z(j4H*SEGR4Vk#;#w*21qZ%d(zUi zu4OlHEtZ)p+gs8&%#Jp8kkyzKo9ZSRAypM?n?6D^7BaAT5P&(F20BRwElEm)f))=E za@Rv^*@C%~P@tPNl`61nYq8U@LJFRA#$86DFYF7mqzupeCkBz-a9FXI*rRuTAHyTm zLHrmwBp3gnYkqFN^8U6u%k4~X|HIBdB_msR&f}ia1()16{6!^*d>IFy_o#gDg~#{d z<|Cyda=0_Ql51217mF%sdLRMd0Jny3ZWBNIt9B&bFEr3EQ2?0=4PYZ?ktrLx?(Q6N zu~6K(Kdx;Y)M+%nP*Mg9IyO52ufeDJ#M!uBTwUTvC+4P`rLe{eli1<5wFGa?Y4t^) zxVmRlX%0{K2~;^BJyCb`ttvA}D|y%9-l=B^wYyNa3$lidNH9a*8~|jSv22??eOjv4Jmj8uwFK)!=ve>uj6UZCTC_j?taI+w7`Vy6xh& zGPWotRBp>9m%DL>zNed7Pd9Gt)H*i_X*WO}p_SA=(sQ|KP@G9)>JF|1SGZvNope@? z`NrJ*``^%DGknawmxR*BmFeSV`j=<(!R*;e3dLRt-vYFwLO12QqKhSZytPwQUvm9* z@v_Di*M@qUn|!nb9##~9PSdtXvP67(H%jK>YuuKbe1wQ)b_|6Lk!1PR+}+eZ$;4D5 zBbmmhumh5ykG09vOTy_gk_6>J;!A|2mIb@aAgD}ABF3qwiegfnM@bv(aU3s+Q^iR1 za#US(`4~9eYb71{@pXZ2>I`EbqA1fg-aS~$aK zSm8F`#?(tpq}iW9)*S3k*=(_efj;33lZvU<07ltGav?m- zU$_8LEjXa-gkWR~xg(JpMHcRE?BH!d(y)a??)9#|32H&@hXkG-G9CKxbTWOh_04Q# zdf_JuU7$9&N|lhL+MxCYe({s4bjWwqm#TK}9Q92jP$8es9f8hXw2+LGYFF76gu)+wQWApWjk0WcC+u#8y)R34K8&z5neM2uWNG8` zCh+aX`CZvTA||y@t9R4=O3D}Q%9!I^09xN+k(q7_nRgByGow=esx6rNpx)IQ$#YH3 zHhmBbJOF?_4v1%=7Tc~XshCB?yBg9XI)}&UBaMAR*SL@v0*6+VIg7PweZbOKpej=b zfafSz93`Iw;5+yEX2(cIniUyrZUI1*B0iY4SOxrO(n7Xkfp9A<7xQ_-jWuz7*E`S% zz=Uyo6ObcKNr1aAleIk0993xm^ro(I0VVG>j?Da`Z@3iGwb49p_8OO_zj+g+)LfFa zx@02??MS@?(3|?c0?!U}YFcIEK=@>GSp)DFAq%I)aiI6%4?b2h4&3}um@oU3L4i4m ztf{bPPFZEe0ZS#xv;AqzX;8Q?FsC7P$h6thCWbt7`XN+6PW-x2k>iQaRV*cR6M`+N zN~~^Kn2!wEixFc~RVm5BB=J)BVPRGs8Rw{omE^Be{21 zQr5m2N}fVB#2cpsl8vbaf$2GTCmhp)ta~>k01g2p1Y_xp!>W~+QF-JbRFcXn9ygVj zD$hDrTppQ|b4A;cTNrLz+y|cD8^Y5A#`bmQXhLEpnjR9hWY$dgUy|H=bEIdKB>V7R zvf@7U2Y0DDuF`|lDvxS6@8r>0Xu2nbdOpabrO_J{jnBsU>jkx{#70tH+a zRwdP@m=o8Ei_*CPVvuXHEIFsYiDAlBR%oO|Jzj%Kjxh_F+w^osYKC;bDM%dKFcv}u zMZCctEM&8PlytAqwyu>n14JkXzBJHy4Pt%Mb)2qhB8^_SQjpK-G z5=UHh1&8@up~YvYLNR@`93oYX6rgX??)zou2d(E4C6+)s{x_n(U7NtyetSA4ZqnO` zp_)lLXdUiVcDtKke+FY7)_d3{ctg_#_}1?rog7DyV=nyt>lv^2s0d@wRMw$A?$93Z zZ?{Iy&Y+E%=D9|{;~I9~d)lsQXR#uwBIwt+Wszbm`mvnme)_RZxJ+e{N7R-`&u10A zb6oC+65jogYkck^`=GJi6xur)SNAq`q#Mr-nm!V_x)I+I8M^(`c+39$;Fm9(sKt%l6wo^WInHN!Xp+VS3juK@ICEWL9bj&))+t{t%yZt8C7*9+^CMY@Fl;qER4hBw5Kc-1%Bq zsOH{q>$YE(6xjJ-w>+|5T;O?C{MxBm@M5#_Rvg1b7nw404M|SLT^3493 z2J9(IsVHj1CMc_fg_JQ38~T9_eT)FGLth$)Mp5~D?x1@dJkMC#UdAYvek54l$rb?h zY>HyGpk18R4ZRn36o$E6H6@WA%CzLnF6t`%@imR#LtG*m={;Cr1Mk>2vWv znKo_bX{Js4zW}#0TK9Zu)1H*Re>D^*IjPt|&)+(i4m#(q*;M~!_X8I1Zz$|9_|esg zeU6Q+@NATEWwhi+Tq#L~kKDNrT5A8Vxm5K#d_HrRA}@bPxgIT3Iu`FVq|0rfFSc2r zGmeLWWN<_B+|hA5C3&C?|M2Z7YLa_z(1!S%w~Ik^-8*ATWUl)!Pc*6?{LwxzvHWXu z!Nd@s&&0%&pqB!p*w?sSI%^5i>*oK;Q2oi@t%jcS`d#k7((uF$kH##cVi-`|z3(8z zGFSo#@a&ZF`|_L2ODu%k~=`AT_jcYxYmp#GYa%=|x`ZX%=c!`(Jh97Donrj>&|%LY;K z>P>j!`4Se-scT7JfM2DR33lt5A-g#BuAO`C9F4Bku01Dnyx^7Uwc;FWW~)?rqU$Cv zchl8-!CdqD#}DW{6p;j*skJd&hC`wwgCs%EwFS@;Y#TCgL3A3*u0OnpG7dP-f-;7s z+D(}o$s(tD?3u>gJ#Eu5_X?Fb4Reovcy`QTmeJ;G_mmL$8DS>9U3g;N6j?Ftv;f|U`2YQEy0<@5hdp#_U>+3%$wJ#`+~>uS9QoK z-It!wHNWfEZ(o1u3DJtqpS~mAc|sg#6rFf!w4M2-=?})Mo7Z1gIq|$c0RALy(|t$> z)oA|ZKBShKQil>ZjWI*-$@4eg!ndazPKc2_((`e+{o6B#o`88pbuzu6e3lP0e4JaM z?Io0G)|gaQh$)v#-F?oG>LBlOH_{Z6tI^DXm1f4r;=={ydKb#{&c%Xt5WnB{$FG;a z>gYOU5M)GWb1$|8{l1O34k4qKU~|0{UF?NP!no=7{WDQrx*yKT&(_6%iS*n;8oONM zw}&k0zVxl?kLLB4zE%Cvn(lmSS%2WluActD&xiU${ynTe8l8WSY4=mT`F6Uact4e| zYje8ct?Cbko@gf0(+SR-Gl#x)_HKFTHoE0>b<27i-{8rb=RZdXOPkRORso0PeV+Xx z%<@(9!`C|seILa@aBxE5*{E}v-h(>J@R9WNxruj}AUE&)%^|ovd7bca+WJdhCwweT zU-~-mvA6RS2=jH0FuCljhcCpEM4z|shd%$FS{3Q@v~zu?h1iN-976`c15sA}8Mmnn!A}!hncz2ly)cXXf$4+yFN9TqyYH&V zYdV=$a8`WX35Xq@7|cY&##^ELX^j|LIC9Hxxb3V{w$0>)U{Ze5mGcMW{25QuNIWBW z6aE<{tS^8K7dNGswqUtXYNByf*=u~MnV%r-d)H1y);CfY{I?_{7w*P;#%RN;$b;@` z=0(}ayYHCz1imFOc`y$Xc4U>Q@GPBD&3mfMdj@ug1r)D2-rKP@u+w}6!RDR6jWsX0 zU3ROR38Jyz;62GYQ-=l&Ii-AP0OfH7q=QfZD-BnWGR_jIunJIEec!-#K3|+wbG(wr z5@i|3>VFqxTu>QYHjnDN*VmY0A!ndo%bOALI0Eg9a1-+aFYuy;oNoGirgJnr@ZKh}uI~=grii?kG!-VyI7r zLD|BehS310F%)q?*9&E5CG7F>p@5v6GArkH!RHQ%FKaDD;>%S1S&?`F^~xhrRTmPe z`lWzp5|^^R5iVuuRm7z{P~}JK20hPBP|dx@YUg`}-VsC50kdvFa6B%E^QMGOS+waC zOuJ6OU_qQ`gPfnTv>P0I^(6=Mc-e)@4h9^_`rOfc+yy64z zJG<1~`Yi>2>r$OZYOkv40CL1+8oOx8pZxgAKa@_JGyJZv#RpcA7f<)Qeg_>lZKHc) zt!&H8xdZFQ791tu@S%Nfe%FNqc}p1(4BX*W_P3v^-}OFfS3oUiRK+HAu5ZM$zse4i zV%x~X*@=PU)|#EX*CEyGfXToep2#0g)uD&g7VlVBgo7U%TW0BK@ba2Lpbn{y0Ch<9 zdqDYP&jQ6Vh6N!_=U+AG{J$q$Jtth-Gj)O`VRQ+y!`!&TK-1xm3E-Oxm&K}R2ulE}r5UGCdg`y}NS z=WuzkDA)F0r1x;8HemRt)iQW@zRaB0-ba|)W}+d_y`AZ#-fy(#6-_HwC=9xUep$f^ z?Q%u#(BRL)f;JnspmUtI3C&|_V+Qy6q*t}}(C8(@(o=*NTu}>U_+u~(KKlgO$g*JY zRj3GhSi-SRH?J|s(I10&n-b)E>nYN0@nP#p!oxmX=kpmQEH6&&g5D0)3_`plfJ6|Z zUNFq2dJo$KOLk=V(psS`!iSjva&M8SzzHGYM}K%TRCySi>XD^FLXEx10gE<=3VHRdmf5?ov z720x=$uZ`&;m zltbMWZu4OiNC+oh#+GSLB`T?$VmA@N#h1L__Mi~FbgZ0`R_l)&A|x? zGReFkBbpHcl}Lh2BFxbvnuCp+sK%5v!OJR@mNzU>6}E=ZB$HL*_Qub8ysY=(tUf24 z^x-iT$b3a9^pzuCC(G#aJk66#k-`=8WQSG?-O2z|j$1Ra^ESAlCTkE2YM?CIIS@#s za?MB%y7nyB42zLP)R`L3qxQZu-FsF}OSed(v!z4YbtdpPQ3O7LT=b$lmVEPI^LK(U zp8Je%jy_O|F@rPGK?2|?#)NSU-^2rq;x$Pa zcIXAGK11KC56iIX^WLfttFX*?uV!e{u<8@9e8p-+vw5dMn8(lNHE4<*B^9Yw_WDK? zj}cm9HdsTT)gL58t5i?eg)xi*on?{}aEcV`(u5~2pN(iaKrSMoTPju0TI%V;)jsUT zP*1^ckc}nM*V}tf^hqCRFVd~tB+z`z9u92T!htP2Xx6fUX8Y_*+?E*hb1&6sCoJ)z zLnB~_#+A^0?S`5`#gMEIXr^~1ub<4Yh{Ufj6h`7({eqhVxt8}b@y7Syh)0B zP<@0A)n}40(|v-)K8m2FF_c45oAeY<`ASb5d*Vy2Uz8rv5{x2Z7DNO@1M&27j|@n7 zGfofeid=Rxn~0?X!W3-jph)UARmiiJ@T@;;6^t4KEVyflZ`bPr$M9Si3fdz)F*Aff zF#?So&HojucL^hK+dxaa8o>2D3$b!a?j@Ul{dXjrX~^3@ zPgAx!UjrvWWdl$1&LiMS6{<44EUG3DA5*x5m&Gmq3OCkEcv-^Yx0)cB=-p~F6;nZ+ za*l^EnO7=;o|-cO>i23v!W#Mts}zNuBrucnxaqXWnN$mnb+HV6zrw!vlWNjl`sudb z2bdqrIgb@RMgVVW(=Ms>$;~IG`;<$>M>9_;) zlE{tx95>0=({lx|Ip%3=HDh|o@E(m(C{C0XzUK2zdhYN|F-ApGtVkG{F)EP{pBniX zgtr@nw+m9ViYPK7#5JE@e*aZfRZ&RQbpUd2J4tzRJ~{<-QgkP-f97n{L~b@(lufw( z1xyStl~Yn$rI;ndZPvkm2-`Ly`yODg7XG!?WZxeHoa}qS{Ux&REb?!!+EmM`%IfaA zNo&X~g=-C|dDy&`Jw1Qr$GuClHM8qXf8{q9Ucsett*pzH|K_iJqdGtRB>boUFY;Hu zxJ4V-{~!A+AG-W$`76Ks9U4sg^;do|%)yfAXfK26Q3lnQjHI0V;=lPTXG+oxiRZn) z`73u0VbQ;J{tx>re;?w{oJY1~Y{_2uzjHSav@?fkr7f{Zk(fH8+#`~}-~5$xT3QmS ztUveZ*Ru;>C~mzSUj8rtTm6;4IA$``>yAc-lF}@!{kdc)Nq7=s^G>bBP9+VB>O^Rh zyi-^Nr|`HBCkX$q^H=_F4NqYpYw_$BM-H3$v8?!nu$jjyVF|wqj{%=8f8|%c%n0E# z04Gex?wck|m+6z=m0bV3STc=!9eKdDlia~=5@&m~fn&B}f3YbT$2DoZvgw@EP9ho? zJv4E6;eMm$y*D&3{#m5wKY7!7-d}Y;(%anqNPC;tzpbM4zSi`IxE<+NolULjiz>}% z>hLoAtM#&E#isdhcmr@2GAa+>kl7)f*IneiIF5xB>cwlUq+_GL|ikWGB$w{*8_BL-Xc!J&*V1 z{De)N;PzztBVg)GVXE`>Et!j>6VG3Teb@~N&X0B0EP1GDa$e_TbNXOaC~QtIEj8LZ zT&?_JGW~9^G;>+i><~Um zp1qQ4jV9C0Y-u)*C({W`AsQ!jfI)7qTBq!OGr7E4+&J0EDJ=IQb7c}15T1fjEn5{6 zKf}&a-x?mjim|`m=8gTi$;!&fEu&_Ump6!C%br@5!s`3O2`n?ozIC$m6$RsIeV;tA zbt?S%L6qPvr@JP*ey(;><=O0!OY$pL=7<@U32*yPZ{bWn4oS=M9hS)BXo`IuG)%We zc6{=Bh_>t^NOy7D33N`o=;zp$pi7vV4A1%QkN1|{v_{cyY4HSRi)NYLxqcVuS+me(%d9SdqE-NrO-k4GIufQ-F>dE zy~a9cY3fp+Z+L9JNqIWV57`1eBD$Q9N0;4=d3tx_AerxfvL{3*{AV(=*Pg9Um9C!V6b3Jh*C{MeTr ztzeLv2wT53jZ~M-MxP~oWjcMrSF$=uQl!u4T|JXN5B6owl|JwK(%k6t>!cIihpBJ+ zcFds9nez#ioeCSYS)E=s71?pwpTW;eu9*zRx?Y`3_e$X@-g&eLDSS2KeL6p=wMsNj zJ(TDunW)mqHOX|hECQj$aic|sZ)<4NK}r9~FXQ6I@jN|FLXS3I{p(-#rJJv&$f?`v zk?s7#^jRW=E|?l~U-}|A^Zcu1erYB9*72G1RTwT(3HkYIe9rS#X=P?iSz&k-)v!Z3 zkZFP5OX`E~$&4X2TmmlhDGTz~wE1>Au15w-bDwp7W(wcg5njbXzJHM_vEBHOb&EtZC=vZKoIBaP#rH%MBA?MR6J7g9~@%qY}J8 zb1j2hduo?CMF$OKDcDdGf14gMmts7eIin_?7cw6S-_`Y#y-SAet*-3&@9<5L5Z_bQPhe-Vod}!s8u3f5=_FZ?gq4is03pb#5+P3X%$>Z z7Ba4@Xu(T`Hf^<~t+m(+qM~lVa;rryts=HI-r8B?rx7azRPukG_sq=B>~2E5^!v*1 zPkyjxX3qVb_q^x5o%itGj>&r6o}AjF^~jFU(UguC>xdajksatf7^SsL!(Cl1-Gj!K zSRW#ZEdQ2w0tb!5g&wh)J2Pc~;nJQd<$>(DzbT#@7_!ZeW#1If*Rwb2O)Gu+ko9`@ zMm+V^hpY@_!ie_bH2XW(?Dm2*JE;KM? zb6UApp(x%dccYcjZpy5W;j@n++cXKzq2!^A%`&@6_gy(c~$J`2(>LMs{fRVl_s-B39K7 zPpewp{Y()(qRfbwh1Z758+sflaKZVi$N3<5PRokv?crU=YIE;J()e55!@Ekgy6f;9 zerqT__HKE<0ibhsHcrhj@u)rF-MzHAR0YQR{FUX|fwhd93t{ z;jup484>-ue@mjgAy9B)7?R%EbMP%T>T@Tv9XqHj+}3T%4aoXgde*_nI%Q;R)b6xw zCrP%`k!@Fcwv(BypVbh3OH0GJf>W4Yt6RZV!f|3ChE*c>(rh2fMs87m+&i9!fdC6p>_#7@#&cyBz~4ZW?a5|@riw3gYf=G z2~+<9(v}bc(1&1Z+$xwOJpXtbUejtk8!$OpEkv}PwJ@4 zF7s5(P#p?Ei{aZI;NSqrIjOl*`#t!U&)HG<7ngaa%D6sWd$4yt(`WtD-R(*e;+o%y zb!Xuq9WjhE zXOfH2iOiFHIAStSa?&2ulHaK{{0mUA2 zq{puQ>QS{8R$(SOMs{z&9?F{Eg=y>Ho~ygo*#}SvI-9bojY`d(+S&F81lie}S}{6- zQZj66ha)EQ1iSj%W&Ca);dD8DejoW>*Sh?36p}u_)v38tyL@B7gWu1Ad16=Qw=dFt zwfX(*aHq5B^ZUeAUF+;J6p}u_lT&l2c2=9>ncq?H(~^09&p=EE^J{UIg*wnx?bJ?p zGN0Ym5H6B+@49PhI_##xG|R@2*bg1xw#T9S@bC%?ru%A-~QE+;Dq8u#PYacgZ6qNg#IBB`uAg}?OZUOx1V$7Chj*J+DZFojqg(XFIV(X=j~sr2!{;qAC%JmPT)Va^**Qd zsqkOjQOhmh__k_JI{de$!G9<1NoAG7huEW;(w;N-)}Cn>WL}R4r?scc{6EHKKmY%= z`G3r4C;b1hhYFA0h~Qbp|G#K)?>$w_GACxf9n*4%&1!zMMYo z+eqIPecB$w(pUWT;g0kbUt9lj`GWNR%(3e2s{UmR(s!jlC)@q$*-?Lz`|Yd`Oxa@L z_%xe$ra_+$X{$(W&1q*q7`H-hY448RIG&)BL;Xb`ezS;`V#=pNAXdven{mfTQeObG zpav<|Iwy_e!*H|#YjJ!`ULMaoQgE~wvRj^Pi!+XAIV7}=*_ClSb|gxR>vM%-x&}tT zVE@O6eCT8I+_6N&_!2!p$%iH?u5hB-*S4G0%|bDq1kDXO!2ZJihx*g(8e8MN-$`~; ziio;^e=jraqOFi9%p$Qmar^`u3c(@)t7>qEwNVfI7 z>nuk2W{ipq!x2g_aEgrWHuIrVt>$Wxn>YqKepE_k-~AxD-kW_bzs9)Ky;P$HMR;b~ ztB`(^@fiJGc(zzf=zz^n^g7T9n>fArL%)E#;bwY<8mh+2Lvjgaqu?sf(=%@ z{hJ`*(MNOox0#<(+)PCP?|s&lRs2>dQKBCxaH7lY=(A`Cf-G`^arUp|EyKB|KWei> zC@5ewd+Y!qPtYPf(gG^Vock*rhK5fGHV&4<7vM9@iGn=bun2i!Pgzk)7@udo@JkR^ zZR37z{P2QpoZ>_rVSKWLu#=OpURiD}t1ke2XPph>D4w>WXPJZXuHE8qzPLW3Om zu=0hicM9ai?oL9he4OG?^@*1S`dh&1+fi~nsiD4L0kTds?k;!$Ayxum?)U>`d5!hL z+dnSxz?%!!tW|mP?XtX}ixs$fQMl{SAv#W3%B)AufiVp3lI$i+iooGLh!)E|yN_%( z#~@H!+@F@q2Bqw|znuSpe3VZsSgP`PSmPwTyZjHVu)Os=CD%^UyN2@C1JuVC<*lc@ zU{K;-?Plg@VjXLWB#!C3SfhA=r zXP8Hdkd*K2F5k1PZnHLan~=ooy9;sl4Gx9s3m`ek!ucD}(SRg%geYJz0MnBNFeL}bSJsQy$N2hmy;MIDsj2m0G|NErV!Wa# z>8qMqCWg=$ZN`=6R$?d%nD}>m#W6b$oh)4Iy_I26eL>iIXUAx68JEzyVhg?tn)zOo zzPNC5chy0*rvBodimIV{Vz1Vu3iEKWDl+W zP$1v3W-NIINB2<9 zZnK|NfQTSG1#B4UDL{{2>7zA}fdH3LTG@X!Kyc}G*6w=ZeS#w|7j}HRc{{G_foSAH z#6r_#-VMd3&Jduck-3XJ38##l4q9P33JrJ^4-dt z&%CuqEy-@_20h}emjvMo4I|q%jnM28Yq!Bp$6eYdGhrz4M<^YCeSl!(LA`B^T=EBt zWtgX8ZbhJQ^|30(Dim&u(ONk1oQEI~jWxP4#R>JF-oE@I8b zBEe9LSg)~&)xv{aX8as1h4=SXc!S4*>>$XpifZ($FWRh{P5}ivQZb<12o=BrX*mEk zt{bDV+IZt*#nu39kpjkOVA|?qCK@yPmo|j*TZ&-6$3X)wsMu(QrWGsj6_ ziN@ZLdC$$0pklJZV&8p=P%+Q4&vd9jYK_22sQVsmm_9<_GEc8dxysR=KG=-DlLC&{ z+yQXhkbYkq(Mb|N#xbZ#{Md*$7%tfOQE(}(%BS)>@#E4)bTAMT7nlAOKD-ba1!6ZX zaq%yaB}`6y2#01CKIA8hXSe}747`XoBCihbt_kj9H?llBmnVbl65Rkxm*?8 zSfX$vn{DAn=>gooGhqo%-$4m=(}{2Lml~q|Bv=7aEYZbS@48C@GdZw3}d@XL{IpWz7>7 z#_6wO+OzGL->R7Cf+ZXoxL8L3j1xxyjI&YRlw0K@>mp*yyK=0RaR6~nQ#A4gGZ>K= z-iUgD@PT?3@!kYnz?8$U(MWFwxRyk{(R&wK}IrtMGNAL^tb>9K6(m}pu7;qaxWC9$ejhK;QfY3u253^ zcLW<@uv6`EGvg-^jQPC1LZcG}jm?W6zA-<3j!#n7NSZFM1g;o&8irSiBQCp89o!@!?J~{-efO!&+ z@I1k?V%WW+7l7uhnC>@pI6)d-gY%=7WF$lolbc z7k-{JVNWeGhg4JD^I^Qfq+>eYqKh8F3(wXBaQ9XNp8a+3h)w6k_;cn9A93E|Po4N5 z{&fgDm*XEB_NVe3Hq*{u>!`%;+4lHYu{_MZx26XHGV z0tkEV=OtKqJ#*SiEJE<`Us(wICKXeK;MoCaqWSq^iRluFxFn541kq@dh{3&)h;67Y zNg@J7N$_>n@~XKahw)VCCb{W>o_70x1tM zs!zvifcxGF8-bIzfGmq0&(CMB@RMk7~#=ml-K>&y3EdH45PWas!bdG^cc+S}L7=eR!78RJ zq+zfX*v>>Vz!0}GC<-PC(~8_ARrAULhc{7&vbzaGnmFR|A|k12}JHX~WVmlC}&6dh3S=qPb!#)UB|FAqtufv=<5E z8L}xQJHtg{cQizBt_(ze#f*lCqWUXl;#yKQ#*(~2L{m}KGGPL6EolVhAQ?rgxR!J- z-WnoU)tI~rXs{wOfxe2d4ryD_4;p|%C;)~+{;z}4-iRz-_q;enIL70;Sine`MAj>{al+?O-_-%`x&6!~xSBIp{F zVkXK{#eyyUQiEX2^~q?eh$Q;gj7G_X?EoD9&pr|ujo#O|j&a)vjC$aYm(`*wCellw z*V)F@hMB@WL$7lj@u7$}gYZ}Hzl`J`6h*2oI++X@*FbLsL!nYjKhpDKF`&4@OOL)d zECr*@R95D2POVtvH{TT$27!<08-Mbqy!O?jkE>QC>kr=93b4~p_A-*>wqy~h$ z8luIlt?8}&K<_4CA*D_c_nSXvI(p@6WWuKkeu}`TEhxq#MWuK=O<3dq!}^297cGZO z^y40gvL*0QiVFkQ4cScfiS1w5lHudM8BJ#I;|QUDErufYG<2a5v#wM?LBsSnnYe(U zg^mPy-U$VQN3qImxf%Dg(3^ec!RCU`G}x?;ZXP+?A8 zUB3}8f{gynccI?o6ZM|E&A+exyuEJ563|E=AsWsfs<92t0EsjL;?s)Bd?>|34IX;o zKM5WmNgv;pke*f}&1ghpuPUm@$DVS`*#~O%+$OcBgZ;s3&%o{4vSp~dgGClnSW#nd z7=_4Gh|Gm3q>zOzYDQzROAvM-0f|c>bW1~oTCj;mjLJ6{nNb|jwBhsi@bmoMQ(LeS zoZ=Fs&(h{MYfD z^hWIC&7I8Ennrx`HJOmTnEvE-3$n~Y(*yttZKgvbFAbnT*h1dQilbfPnxbIX>E-aYU zVLly)`BL-?N;PWh7jFHlOs?n`dfxCR@-DK6+^t_=z2t+*U!aB^`h|RXixn~`ij{JlqYLQ87d#wC z1s_Mr$4C%w&@WWujhx(QMn1i041;CQk3|4J=rRUIq=9Lok#XuRiZ@%o@b%iTNVQ>6 z$8Cr%WfP30Y(aD>8(=JD{T=HU*ky2YChja_M=8z%1hNM3cDd+<>Wq{EQPz=AcH*=Z zF7`G;PDAd zfE8PKhL314Q;6J(4;gJd)-Wsdhwq&sHXgt;pF#Yz4PVQa6BZ!JqK(HA^9Q9K8;{UC z#4uW9HPd)ZGzOjQ!7{ER!??qAv8Wh!n`c#|d_y5aAR*m;rXl&=Z60;S7LSu7OOqZnYHK|hfSTQPh1n-e^@J1ZgnRx~` zC#-&&NdTkWfVafGGPKIvq;vC(jv8Qz-xqb<09yjj>TL-;EAQAyqsGEs?4pIeSiFV3 zR5zBg2ru@k?gV?y0QL%X342wiVXuuCq_1tN@i5@RCOeA-Msg<#K-iM_#rF%|(vtqu zl2RbA{0Ja846r&c%~HdW$GdaR`asYMag!1s1t30BRHu@{$R(O%Fq)R|2ucV`c(j6y zC+*Dwv8M{+90lusPmlcQbY@MHA0?m|q`anBY^N1YFxw5z@t62aV?yp(G^8(n z1|QJn?dB_Q3LTUpH8P4)h}=}E(Q-Hff_a85HM;I)!5)2iu>f%*M>PVQxTIk%r@@6S zXjAcSv!H|t@7O3|YRp0w>s8Ee5GZ7EnTmm^sFXJ7kQ~u5Ii6}LLxOlyxt9ze!E_o! zhS3IoRA{1JERzF(0BfBt6#HWB=@nvMtSx&=L>-hbJ&cUyyr_ULlrr&UP~vVpQBd_& zYF}v8zOeJ!VPMP3c>x3-S+%mYU6a|C%krlQ+giX<7Hw@6zOb%RKBc!cuAwp$q z8%Ik1(WaKA@Q=?dfq#6?L2CZlmp*`Ks+S_r@_fW$vgRS0!aW$y(;#-f^~!qjx`3}R zpJnwlpQWWZQ?nU}eh9B9O8Tm%m5EQX64U&eiBD09f5KNR4R>X4!v7SEz0NZGXHX_ z`cm=AxK__k*ESn?4q+5HOi1?3C>EbG{)U(E&;Ym)>a9fxJZ0f?v$V*4c!CR(A-JCO zlLUn^TrFb*Ftvu9H9$G5>O=s@C5*IOFbxdxJ&uqfK@K0kH!?(*iiw(jix+n191h)5 zyg=kyU$BfxaN+E7gwYiRD-cjViN|NuV_{3)lxvst8nR9JTF~tF+N^hu~FtOaI zoY+t`simBLd`6)xwDWbnXczo?A+22b`nNMco#Alpke&Z%`d9b5e+{LdNNp{I;9HvY zEoR!4G$slm!V)hxm%S;d>MR7$4n%~xwt=Wh%^UX{o=Keb0ei%`ie3)it8dg!BgGp% zm9mXu^HqrFWlK+@K_Xx_2?Ebdg%r~|7i+{ zH=N(J?i-gOnVH|xV|C^6FkO2C@65}dX)Qy)k0Jt#CvfRN`<#1z9^K6`-WSN9I}p= zA;Uq}bk4SDrb@B4 zlGCl#%Lz2&H8tP={D@5=9uV0GmMrEQXVD~<^BrmRB>1}|AUQzaA(V}bVDZr-E)bh^ zc!wF0Bc@P4VqcY590>vgV0!7pC*mrd+V!XT5K~Ln43lXA9ngpbpacHKIIQG0yaI4W z5w8)@v8GD-yqM2e_FT(UzpRyTp|ux`$I2X&kJahZ@(v)Jjqa}Cj00ic>=?`K^SXf9 z|7^9v?2(A<>)1bSPidLAaJ5^fY~jSobTChN~y3Rxm`W9$pCp){?if6+)3R2(J{K8;{FHy*hTCMyAH5$$=w*u|(dj0R&*i z<-3J%k&c7S&9f(p;pR!DE;mnZhida|L<;_KljJn;kIx&`qdc<|{_(0B&bw@$ECN%@ zch}}gRWi0id-G(yc;&(%?q>Dw&68yy`XNN4DCui*^Q4-9iS5mk%4H@V=C z8NT|S^WhWc6V{cj6+_zLlV13vx;4<6R&3=ti-2*q51L>f{4R_(_4bvJV3|SVUxAX3 zAfiC#)fF08AJN6Uw^>N`+mSL$A2zxzm9ou5C8r@ex|!aW4}~SY zG++5%G>;1MjPvL=#%YLaEnCjPF}vaWAF^@qCVdof4g7>wG#K>;x1yzsA;XJ{94}VE z=jGB&oH#H~dY={p#K5;S+ zr0xvh5@(EMEkNg32w`$Si}{P*oN_HX8ozCdI^2pBMQu2XIrV8JTw(U>V9y?i&h)kX z9NpTey6l{aL5tU#Cj^`>YxPsav#itYgAkV(k8dzwJmpocg4fLxfJ0jj#fSd#VH3)Y zoA=iXV(m=6S2ts07Tg1~72XE?;=+G&mcS*ZoOqbmslF$}ER91+>Fjvd^he* z1tq|IC5aLOc@|1IzY~GZ~DfB0VT!`t8P3cb(=N2@xf7bbOv9Bg`F(pNwZOV@XV z9Bxp1Ix$Ws^g>VRT*yr?3K_EJWh858MW!K`Cj5o9h`5+vIp^CsC?T=eYa=fHN?HX`m zO-r(A;j}FcIehyN4{}hnq{C1IiduulPQ3(nq`&J%c(iC!Ka4>SDJTL(0O=lWI6Go8 zUV92igDUOJjE3IyPLDwLCyLR)>C#r*XoLeqVRQ+VjmCv8t6>D8cnsY*9X!Sz9v&lL z?2$WbU7n>E zwfT)N0wrxzkC2jMxRrp;V%p3;7jv=Pgp9BfrwbW)K5a8UKaMN#i-2*HFfHtprAdAH z4}x_H0xaC&QjT(yB+ul$)1K(j2{|&o)LDKWj8lW}q76;u@>2PeMvFgL48s6EFJY%} z5@m@=1FBAl5tz0tZy5xF#5v!UiC@_>z=MBq{L00zXtQT?2Eemua}AjbI^}Wrmft1$ zmM2G9c<2!fR7Sq#mh+r}(CYVmPM*%;TfU39#QXdvU`bf5u?kF_rO1_-;ok=KkO9m0r2CM;GXo zv(9!FjR$)ihwopTUJ1f4Pbc^zvwUO2F&=#JW#t=2U~lxwh+$5b)995!h_mUHk$+SO zVMMKk5YCkk3L*S{>Q|>%R-g4v;e$I+(tidY9G9`=Zw4O(q5~lBbjden4rxz_BO8x= zy~#? zmi8O$_VU%?UuFOw;OYeg=$9&Eo7qG9rWhEJq3$+k{l-QJZc^e3Hz{#*mW2>1Iw2>D zhB~XmgAnrY9kXGyWf;X&ilSqQ=P+m^I>QJjQM}PPJ@LemUkg86r|%6voN%Ty0%`J% zgAixSH%@6%_~C@f7Jle29~6GL|CX=m6*}q&H*~cbg|ZitA`& zxN?h;TKyn|L0Awjhy&H}qA7T|wVk;_*OPgCsM~F7?xDx}#8bw|9-pfFF2gg~8lJ(O504rjoVOAim1ZgCHJGXRUqC)FXoY&fT=Oz|P6Ms1 zES#>?2Q>L(W3q8MT5ZVxVt0JxUIE(@$X`NN<0hLNXM;HS&m1z#t|fGt4%>*NP0N#> z$g@2gLmjPbx6>AFC=RL0*;hIEs?4z0RPr24)^h$N;6w;@z|}KTm(nr`qe&OBI3^5Z zPi3P>^G{eN%`XTei+xI#W}6&27;wa2O87EgnK`UbW|y=w zTcOM@VZ6q}xErlvWrgECZoM}m6r(g6gy5bA9Csb4!xoKsByHXpoPn*<`OdVknHhzX zty`dfEw0d(;f}oKLO)KjJ}c9K1p0t&0i1L-#=wWbm`UhoKFu`;8e^`5S=)`eQ3X$$ zl`y%f%GZqpl)+6ivRP-ac~s16CFC!8Ng0g!2fP_9*%LZb86+)ugy*E}iG%-T*|agV zGRQO|V>PHQUnZgDeqLcGM}Obo(O+09Bo8Ym4npHQogt1y+6*<~BW-KuA@r7>VLtMc z^D!{-2&_0@!S?afvPZ8+pmyTYtB5hZ3Shwxdxd{s%Z}h5t?LB-p%zIFBkZO<@b8Jl zIaU{8R7WLkCithlrVjXLwfY*GeP<UNz%n9*P3PBI1%Q0D z5W2boUc@+BE8qmR0uKH3bJq$uRZtPFNv%O|dCUuwUWh;Xe;ML`qaeQhDS`N{2o%Iu zjZcMm54@A6h1n_15}y+UBk!Bc*C31cz`Gv%F7drqU&nER6aX-f|N4Nfuw@C|s&KxV zJ6bCq0c8d)2OF6N7LD8$Rw#cK7SYaBPo}0iCxAR)N0C=qHP(^Nr#YVO7!a-x5ei5NMl7n>^Yo!d?&- zueI1C9=A+jpOWo`wyUL7!NIPThZqbTVhG@MI?VzXAmc<>8FGs%ZCIgpsQH2~u|06l z;;z;(<{I1LwqeW!?dkcFexfmEqP?qeA5oUK*hQFtx+)~Ni3w=1*D&T54q_OOSOIDa zkbRb0EcRLYjm{fiioFXqpD@vuok5mhip8gOqmai;6&ui$DS-i>1xh{%ouZar;U?}E z_U3b;+I%qM7%+eNQdf&bKkjXR_~j}zp#%De>xBO^(nlXMBidA~*X`;Sy41Tr-1m|@ z@+@l)z7)pXE48{?F&Os#5T`jb4Cdb$vMv!tRjWZB*?WT=IpWTeq>gCZpQMhsR5I?p zfC&zui#XDIZ?QoMw2=ZN?8TM|s6!jM_hN_6vFI>|&cS<}rGq8{@DBuSRLE7M8*B8Y zk6=2t+TZly(DH_9ntCjRW%jgOV`gsx7l8~${n$QiKOvRY_FS5nk@|P(WS)0Z{;Q!xuqkUNDWNleCymIwEhgF60mt>=~#7zV_$UB?fhj)~1 z{-*a8i4#{OuV7AR@zr>b9qjQ$p0D5)$XYMjs@07HNDkRdJN;Gm#oO^G z9Yg)ZJ!~pgF&BfP-1CqD=LxVR1Rf_~mSamHg7Y{1E8pMy z6`m>~Msyu3P(*vj#|pGU+opJ-BF6C^M-lePg>nTNa_ayIZJe(MeThKZk7R z)OuVe1)^vAV}1JThGpK56McU{n&5!XA<+&E6Wl51SGJlHf6L>?HU@=)m!ze&XDSoq z@u;ZMBHr(&EBB^EVbIv+Z%T+~AbJ{72P_f?0>R#C8qK4tIdF0i`sd?P3@cjJ}(8^d*K}z zKO?-~%#04ar^qMs#PHkRMEA=l8!`I-E%M1v=j{9P$%}q2(0?KV1^tbIROs&_|9JxR z3mw6~5IdN;%<#{Q9r2%e(CZ{4_w%3s-|(Ny8wD`$L!bb&*98t>5+7UIA{X!J!Nw2& zz5{5y5ikfAxhKVecP2T`1k*c6I7J9@_aEGmHV~?V?sXRfxNRZGx-xYrd>urD6sbW7 zk|H3-iQ=RXgn*qY1Q9M~enA+ysUm7bSZ*uL+?JSRKO#$P+mGxe zHmaOU42y5Biismo9!buS7?RjsqOaG`YWS*+zvi_f52Q5MN$w~#Y0FFbF_!Ac2wg$mg{VTQqBb_Nh55qRV1?Aaw-G&)NKN(dI zUrp`*DA!diclU#`47MOpJB`20pfp|6s1pzV;?Frsnm2UGwD*R z9N(4yu=$p6n7#Q4TWI+STOkg*sK_nk2pFQMq?M^LW-Re9Zvbu>GmZ&ZF%nes^YQX| z0##JX;TLqB&|hw4o1x?-u|rd!HVGGs4i`HgRIDJj@~R48&C0In4Eo>eC_}r=< z9OOffOw|1LrJ&~Z{X$50zjogY%n})|$De59O z4SyOZ*g-=bnt7$r@NtZZO~bnhtzhq0Kxplqi2u@dUQiZ^oflL^mM+t+E#h+{nnW>5 zr?h-ssJB!rnzPOrP2eQl_sFWhKckcbS;I&KR!5omdA``U=C+OZ2O85@3l*_`I5=7rpn^ zwPwQtv$v+R zraJ;fWNnfdueq7W9<^hBXAF#7GOxcI?DYqp#>MYE#thE-yUe}*wwd~)?nqqC?B;i_ z#k?yXdPsYjQrB{zs9CiXhV}@YfRvq1ArX+Ju}yN(aeVA}1v)xgWldmjMCIVOxf4<4 z3gx_Vamkmx8e5iQxfJ3**xzw5x5V1<8>;|>a2%MlxJ+4wWTnaPknaIYy~*!bTLuU0 z4)$JOj)Aq7A(XYU3}FCSZjA3^TO%Y_-I$uvhM8UGd4{=GT?U?KgB;hh(drrCd2rby zO>!_-bl+J2S3DEQpX?=0)|Cbq>yAr>CI;{WHKWrx>%y`l|Kt>DQ3~z}0xOuDpn-|I zx$+KEjiTX}T6oj&HI3(iM=Ei*c+-1|=efY*dHS^+AjssCXm<@x7q>KTF)g;osO)2d z<3nme9(0c^yLV&ug1r1pYeC+pVt$W6Eyz-d@h(UY|I>=mv?xMYJ#WH5dlsSoEaF9b zM%(8*lQz{>&@8m>r54nmftrrEk83AE2V^usoT2K9tC(9j2XLad-+=mY#( zU+@^-#R?kafcR}(%ycUXKp@j?XE7cDpnN>dSzf5D8Q=IGXNdQW2!V5oK^UGUo1+*( zzoHC%HY5#w_?W@ar%DWcnps#L4SmKy@8%f(a2v&KLmkK~VCe&Sg(Zjp*$hyHv9x38 zb3j8?jw0_k^PL&`XtRf4h%FxJyL4sA5!K<~ZaG7l%$OQxa~ws>1%@@-8v*H*T*C4$ZDQldOW&-dKS|W8iM<4atyGhq zS*75zqglOM&1wMH^KLb(0hnU}h{U{w)o?1C85W{=*Sw0i!^A)~a#?wSZta_i8u}rM z<=$|Ytj}@;YQuc?G)0N3b;$L%7kRQDjEH9)+NTdJd2)7&Jo#ayr*r3GKRw>2$dk{8 z#3&hQ%ag6;Mn~z^UbxQQ3o#36Ms?)0z8Y4=*m8z2E8Jjt;y@R1va=7`3|VKyjeD(a zlnJq@N=#6krDry(V>U_Nu~6CC0bfrMD*uT)ptY;Y4j3>FhgF;3fT>dgR(gA-L^}{P zN4@5BuZcMw5Wu?8mQDbVlOR{-uU zW4cV|zaB(JY=saD;1ocr{MQrtCFQ>~VcJLKzho916fP#D|AptjCb$89A3gsyOCWwd z0tNA??ra-RB>%%O~M~jFNoW$p1-CWQkWaJPPXy zdmwe%iVB3+bJ1(tX1qxgY7%KmGE5>7l40DVx%b15pc&IB5x052qu2f>k3Ncc6-IMQ zFkpC2JM?7}^Lw+}hagyp`G9ruu}V%pQd;W>Zz;5GMl~L)-tA~WPCmYd6c$x~uI$R@ zBeUF7b^&KkgzdDSmW^K3P+7={Ao5e1kf>wbpHzq^Cr)__>tvcZAf2j0yv2*`@*(5_ z2PP7GQhd&d)PafliZ}jfrmTRq2-FHVw=i`Dc;LUI^I$w*?1BH3^I){27<*kHyb$$}^ zqMyc6S4pSxBIH$sQ<}VJD+_W22r2TS+o2##M(&pvr5_C2*W^VH-?U#|RN32>7Y&;( ztMD)cY8Bo!z`Y8)$glUkD`hSEV@ZCUyn}LCk%3>of;k;zlftj>@kH+D*Z*7j^~%2c z{`sGftb;xX)H;~mpX;Ej@ISW`_!lx3G+Rb_)fLRyA^dwH_rw2xEBv2v=DrXAQxyCo zu;Bk_2mbeZ{;fU@`W<;y68UG4SB+;z2l!LuRoM}DWQx4%Myw~>6g|~n(L`{H$ZC0O zISDC+Wp^8+yUpS@VtY#C1>^Ymf99`4Aq{7{Rt-{8}2PC z540wv=*A=OgpU#)QxiR>oHJZB5|+c+`n^+ zK>xuA6!h2kQ&dpO{Z(55&i4IPTG8{Rc-4xQ^15(+O@#Nlqc}Jo5En0CQTBup;kN7Y zsI;|ugG1<8f?E5^?deR;!zY<)B@ zQZ5$F_k6Pi5i(?2QAJ}Q`dcbwaML|SG}f)?(Fjck%cDzaHt28qC%gu%)|N$RIjB7y z>(4lC*<-YWiY^#{Ut<9e%0?IPN>O7$cMfe~MI#E^h!0w!T%?Y-X34;$xG|ckj0O38 zF(LyIK=+JgGOeGMH?t6VB&)2Fo1s^gyj&!(xres^SRKXTmab6my;gUeRRjintoLq$ zJw1+VOq>*ru=j` zN?4vmBTumBMr1YOw5P=p;zT2|LFyCe)(rtW-B=`Gm#4rkPl25U33&p20YgDvp$vwW zCjb~QmI~-KDClzcGA7U!A-n+=*~W&*ALXUzQOioRo?*Ucv3q2hhcv&}&QmzUXjd3p zz(rTKoYA_`WDa6K00xOyJ{PU~r`HSq*nmLckMhHaKb~Pp&oYzw!$bICUZ(p!V4U*n zFcNA-5G!g$wNT%vHE-VY$*b*JAwFn@h=RjK-2-0`s(a*#%_t<3KIyhQ@ZF7uY>htT z>1Z1vBC|aG1!i>i=M;JRRWsa?`{n6yqV``PPrvYb_pI#O^7NlvE30Zc0=23>^r>Ch z)+Qz4pQqW{9PpoqFB9> zilwonc_eb|58RQWyc_G7l#Rv$>+m*Raj)qmS1l(!xD=Wc&?IG1hLda!Xd7>`E~V-D zLwv!n7TZLua>C`ZLXK%RlM}zd@+!oy8o0uV2BaQ;oYp5FDtAUSeBs@ zo|$WAa+ix9Zv8xkhUDW4PGiP=%SBHWwp+UCxm)ECMHAhWIM+yXVOVZ@EcZ|=lWuza z1Gd8DCX`7vFk69c&E=*?opZCjLvel;{!lYW_zAsnVa;U)XWZG-e4xCTr4GBDJ8zk9T}iIR#Dz>?>)|Xi8DAM7nf>w-krhP`6hVL2n8Lb|2ye$8V_^||m!V6AM z^W7SvBRvFLA1J*!FHy@dk))~9A#-+oEVSA=1l^l0_Qvgj%p)b^F3vG-L&rRMo(0W z>2eaDDpiY>M}4gbhOIo3A&k|s$K?bVhJx({ax26mTZ_j*It*fkK8;mPFI!HSHS3=) z6u@>5R0^C4vWJ60%xNL!bP!4^2I@SGT@RxSCRgx<6vaq!8e)eb70zx=<1u#&Y#rF(&r`D!# zkuTL=WD>XaH<=Ornk3i;eyrhIliRvP&YI$mJdO4ulO0c~^(c}yli~^zM_sUItdre* z^_<5rYJ(G1Y%7LqvUNhk8XG{X02H9Kk)ul}C8}A%7kreN!bia>glhmRyn%bL%AfHr zSY?Ae0IO_d!W9LZ5MWUgtNcYhCb0_nY|dpVCzep}z^)6iNFv0SN@A6c>5K9H714|M zCABR@ls!tlDj#e)unowBdMO{EG|KjpfT6Y!3|Ve9q$er46k(uq#Igk`Y{a5iY)q(m z^^;$;W5v%e$VIf8^RF>G#37s=!66)dp2^_wJ11y30dj(-EWCSgDCn%Zw0ZENi^PNu zFo+FfqY)oKW!zc<#*ay+I9n93oZ6ipRoE`?7XoW}KMpfh-k8Y(H3uVS$Ibb&V1e}N zpuvs63beJQ{|j}J(?$-QVS%U&Gp<{HF}yQg-tYid5oDh~=23`5HaZR4_Is}oJTVD@ z!V_=yuWJ){u)rgPw!7sqad=@Mo_V+#aDQ>6w9UiZA z%cfH}fhi>x7m!C#1c~FgFn-ay+Ps_dcPP7!*TpR`{eI7U{%=cDaaFr~f7 z(ua?^l+qUNdJ4Hx+H%;W6oA)B$%trCFKG(-R#%?n_{cs5xDa=s2BNn?xnaprE@6Iv zz2eL-AlN4bEIU1sCovraES6KMPf$yWfQ9~pge2SCGHq`>I*G4`P()Ik0ydgVAw}^N zBAkOgzJBjQln$74@%Dof>FS5)pw7X0y6Pl%&V%MS*lIcSsRTW(WGN(!;4FIrcEGBM z&S@SFIRzk=LJq#MyNPe?kvaaN4O5OmCWY*b@%`X+I3Je~!)jKPIV~>$v5mS!rnCrw zLTo?zf>Ua5of39w|2$!0%4FN}WbB_k(MFd%*?T|D&CCe03;Sof|Mk3U-H|Cr#cp-& zpZoo9^AISAocpN* zkska@u~8;|`iSuz!y~}aE%SHifl|uf#xo=EFElYYub5(apM9k}Qe1h#Q-gI=(OjDz z(7odQd8lr6KT=DdwA3@1W2)KJ%g}4!4{7wiKDz>+CevsNkJxnU_QE)_aaC7{(fCc?WuZ3{)rM zv0qk78TN=m?%)|w?5FDT8;@Yq2GYkmkohTRF7ZSQ#pGQFVs(d~tqP>5vXNb&`e`p? z1^|mADYLToUSWv?rna)<5+%LgHA2wGW&{d-=pQ@i!{vXe)ARm+y$qAvk-P+O(y_ec z=*tNfwn#2TUh;w`a=*Ofzg1rHz~TG6yyTN|Sp_d6P^)10hg=1o{j(W>oN51jZA=>U zJNDDal5zhOe-`~ObpwA2|I*}%{F3|&S$H{VyYKNYig&S8YX7C@{f}>P9~js-&--T& z7l_|hW<&g_mL%S{g-Ray=T4dw8NT)16sY$YXr=l4au!0``OSWps8yh-$jhn46{8;^ zF`x59p2Mvo>F=usTZ?FAKt;OF{wJuFNm0t=BWcPW{54&EQ5l&^Mko zGaa{ipjd=TX-4-z=YfLB?AvQ^?f@z+cL45-kPi?|3&}&yvWGlO(avbIPsdnV8k)WM z_R1aRA{j#?T)w@O%~t&PaO`E@eN5k83sJdawv}`Z;3P@>ld427E#;lZI7-Ou;Y-n; zE@r^GpmA@Ln92*V2GaJ;455-wckWe!MiNi~gCu_7g)dR7h^@QNl|?rJf!b!?_?KtV zdDdG;{MxmnQdXWze#`nY-7hYS=?P{;!!q(~7g;hH75U}(HT!T#Vn4qI&O#Yx{h#w| zOQLF%k_p|ca@IUAes>xy6+mnHu8GMuwJj334RQ9n=I)MVUJ11uV)`Sz;sJIarhNmYh_t zvrxsu99A^zmDH@$2ngh^uY-fFDdcIV#zR|q#f{4WCjDMQ01dnHGnDbr2d4{={Skoz zvSDv}fXstm!<;B}SXA9ACGVTeHI?}8mWHMHfAV28DQQgg|J01n6sz|dfeG=b%eM&gNFRpEgAv!2%)Zq_R0%t?1$-m2pH-LY`L<7_$e`kHOF!<9U_ae7=c=pzu0CkO3!+1 zMxIRg{>=07-Mt=N{1UQsOz+HOMhD-g&^rUl-H~6C-sz5N_si$7bn?Z;xP$E7Ow-q( zcS7(Bkes-Elis=NWP$p#5Gbf$@|q3xHnsEe%cJQI{JVPH2c>%KMxePh6>V5EIK#3* zTQ=(^tof#kV(q_8yGYL#_V0bF*qM^GB!U_@guX>5=wYc#IgI({kWEy>3-Mz5SKiWAtcu zp0@r-k6zfO->`A4D#cug5?Z$Tqu9L>dpM5kch_Twm0EQeADg!$fxm8MzAC>ECsYY+7XyQy!hSC(@>s#p4G%=m?JUeEI(h>*FpJSplCJM zHL6zGxhCT8WbN2`3^2eZy?x&NrfDF*4xrL8`^P-_DiC~CzIhlQFcsRe2RKvaVLwZ4 zT9?Z&N@-tmvEXTR+ET$f`6Ftyrt4X?PBw;jW1Z;HvKmfvA?HdrDonZ#c=iwJ;IZr{ zYG8L{XNL~pgwc0InSlJqn1h@oh)85&4$@E5j^zd-!jUGTCtk!u`=qqSgP9S=#FHnR-obf5g>F_F_{V`;&exubqbXH-O zKYK^OxXp)_77ARf(v4km@kp!r;qMATh1}+AS#Q@cdd#J1BdQx~^=NMZBB+pxR)U8M zJ_w?9X7-dL8K=jdY!;vindbMn*Bc+V{GCH|<@jnqqcc8Ii3RL4OaY$Aj@rY}Fmn*I z%~~VHv~LJ~fZX}aZ8gxQ4~QZQb#z;g?9l4}z)GVfL*8gPTAJr-U;8S(gPjc-JCe#I1Jv3!>#`<}=-#3u1k6NoP|(4xI-}nq!e8aW(l9Yf8q6 z1+nxnbN@)vss0_2v46EQ0ylgzi5;8JGxUK!dygRacY;9f?ATes=)@f9SMR;|=h=ns z{@9rQL14z5lzz-Z%EaxN`(eYA%(OjGwNUqz=yhv+$??TosouV!cHoW?t=Y9$T)jAW z30RZ6$N1Z9(_c7TSB|$KLDiuA0l^^_0RnzHZiFqfwPyz4C&btQHsx6=1j@qggF}ax zEhpg(uq4B^V@6?CLJ{X%%9fue5t|tC5h5b-(D$`vBhDLo{&}Ivf!Ng2Kb3UKTJWw1VYAMsi^NtgzS$g(_ZMIpM(7m6NipV~AzpHD6#uS>xTn2gr0C zjnd6;^~%a>$#XSxn>iA#(U#3+Co=3ohw62AmS)xVk%7eec>~QMV_o-BF;}~QR`n_% zCl9{Gts`aDpm7<(z#f~|yq;NEf^b|Jovo?VLyrWBeL#|2J|XPoZ-uwQ)&SC$6xnL}#>PO9Akt|LpcT*+aHZELIc+ql)7Hrd&mD#ZJf>223uReP~h@jGD7I6p013I3IE?FS04R0+C z?->xn^?8QiQ1rVP{cbbYaot8M+VmLuy#krNt!hKRhmNmKe9vkdp3~r)jV!eAP@6uh zN#G$Hm2(UVnZb*{Tr9=yJ-6u5JUz0x_F8S(aC>T9Orma# zZVeUb(F57$0cf*nz6I%xw*jX4{Cwh)(O8ogOfp;HOUs*pohq$PJcv{rY?8%pcr5j% zHqD!*IIdBE#!pckbD?t`tk0DEt>(#AMV*ZY`rYL&f0))I(_H^USC_x|tb;B;id1Rq zHKo0#IaA8A`uilx`jY)U7x}F$7M6ABeNg(^vdbpK&c`MPuD@uxTDEI-<5iG2Qzn$f z#(aT?m1W_!qB3oGd}veX_$Ap$cw0U`Hw9w3ulFy>8hLe(S;6eJW$n%N>q5N}!+|r0 z#4#rpXAs_%6Z$wY7+=G?@x6e5qD98>4VMMs?FcPW#WzFV`e~6;ytT{>?>bV8e20%y!@G`#X#gK5g?D{R ziyX_x>hP}qTI4W3UL4+)uSI(EaYT66aav>#g}5n`vf~~$a-bF=j%YbHysJQqyvoPJ z!n=;wB7fpz@9?f~Ymqn}!{>oMJ)ri$`na|ro_GRZ@H9W3c$9IwPQX36cu1{cRcu>3 zVBF#lj8_5QrY2cyuhwHDC+V>3b_JC{| z8?e4XG#;ltJ=cc`nmB9@gU}%$pAW&qS#$V{rs0}2f%;T#;^mk1=tVgM-Q#s*BiNk- z^z4;--O7t<`x4z3HG!dvmo4|9?!^7~zSq7A@;Z{zqZKhd>jUNQkdT>_O z1+gAqAQi;kttbzFcj^P0v}HX%y{1(8N0e>o!+S_cR!jx~rqxf(MPHZo+=3L(P~oH8 zDE^5_7=0C@{l*{lD8#ZAAZ04B0qc~EmM-!)l+?zNL zEL6Whbfzy5o!BpEycI0krOiIE4~L@yclwOY36{L0%^oHn4%ef+b1&{M+NjOG_aN#Q zM%M(4>Qa9R9C==X56q-TF;;!x_5y@K_R65KAy~9Js10v2kD3e@kq<@U0j;7n2%$m4 z@7SEW88zLt*}PyLOafY0T^ulOnuLNd3f~%9_B_y5mYe~?pTk^Ix`ze*84UIb0pZ%KOcqv%)QUC}VV_?p?#c5M> zF!HX}@JCeVZ~r5tu<$qh@1U_0EvcbXg1HF-ywzM2kDWF*xxc2gcb2=oKXtWtnBCrG zowfJXn?3FQ{*f8m8WpgrF1{dk*r1^CJ{pbYs_BQb)JgEC3W3#xewx99=Pj^k_-?nd zXF1SLB9$PaA-=;{y=03vcf^4l=H1%d%ke-k(`IkuI2o@7uzok00b>&!%l6Q_2lI7f zrQY;*54~s;4mV|odIgPFhiq=Si2zmCyhraoV=KN?#rhnI+f;i5x(AzwZ1z9L#fv}9 zp+CVBwt|c8t>ukGn3wH0HV21n^JlNb9m+kxC=S&qS>CLe_z#$ z-qdEFlVf%KbUaKAqU#4v9ihjtv`Y5)wexrC03D{AhiF7*`|CCXWPTe~kTV_F1_QD^ zXl#U6+o9$(4x_z5cLz)U9lC)_0RqMgV?EBmTB;F`vv2hTKB=p*Fpe3%%R(hVR06N8 z5U%xrL^WW%AB5=fp&JX~pcOHwH$jg6DkS$CUl5`#WJ1HxC|6uFP;C#tQQH$3XjSQ6OG@T$U|UfiIwufItRt6wLkrWnr~{tFS6|cA>v+O^&~4huUY@ zfFsZVBq-Lqv%>Cp%=a6;coBvV&uu!!KUz`h&yM>!{>EG82RBd}Isp>E&oS~datotD@y6VwU66&i3~df?+8f5~Us zoZ&sVEH2IVV+G7f0F43>_VXK``k zXme|s-x!Vm7#w3p8*%8!=pD!713aArZFir6`>ywJI;&!X&(w`iaMBJl3y>+=5GdM% zLa+nWXm#zFT)(k{2{B%i1C%Sv+%LSoFe{k7hv+IxyGO?=qL}uc^Z3xcy4l5_L9Eyc z=~0{CSm`fXug$K)kN}|qjbEIjm#oxgU&S#3R~-aL3dhX;qPRA@8@>ffkb07n`Vc*P zlb*dXfQ2vkekGQ>c>PG;KN}NcLd-OUHw?pQt-E$eUcdst= zm;7C;)A1tvr9T>Ecd(DC{;nsAbN6?bd^jKgajV_kR<0p-_jxC=)!m@+TCivhwm0eS zP}FYiaBV~4Y{bKHtUX=xZ_s?%T3#>UA|HDUhzOMI(CU_fT=F-4G_0)dU#-FHFWA!A zSFoRp5K%?|M%$`=i2-eVrHWf#55a5D_?tW*fM-3rpn-9KI%mO~Q|CZ+W@{cN3s0GW zv~%9sF<$D`VKw>*Kd7TrzmZfBtM4{jS0LfrvZN~}VT%Y0z&X7@k^K+lfJ1n{-8`SAF6}Jw z$LO-4q_@q(nYf{|#4mAtAb-D+Z5ZEK${$IwZ;|RV&t+=4Z6Mk~i*HOe;yxy(gM92h znY(wMB$n=7!^E%3dha0dAy$i@eGVxf?<}Q>A;$hDExwznXCk$m7>MOA^&v^D=bH$g z9gJZ&4|^Kv=v2d*+L(f-;B=&WKqjq8N<51t4(=%Bjgk^tm6hgwOxQh{5X+lo%|@NN z@jCS`w=l(9sNSiRJ2&AsccCT?{1m~ngV?~S%aC?yGObnG=j;ggp|{NeEbWKM6s`q< zYPU$jx3GDe(;-J|xydykh<^ECX_fgm#$Du%TOx7LQtUR*Vf3kJ-{<&-Y{xt8+p?6# z9f)~b#SC;}o{<>s*f5%go{Rq9#YBoERQ%6lcwwJbF$%=mSTH?i<<&yaWPlx8oHDLV zv5cwmQa6+8DIbJjjO|F`Zu8l&B@%V>ppaG9v$>tN*Ng7WTQe49$+hgj!#~%30Ji_e zf*Rm9VVnK2(ssRMqgJ;QPy>|{h;5M3THQFlMvMH=d;>f{zu-~??rLi-j&&;tqP5r( zT3ZHV>{>C7&@opu>qa*O8+BtiD9qJ*UBy5AF7QlIapd<$u zBm|1celo5E0`b{2cZBU=35qN)0nHK@UbL6w4Q|v+Dv;(3yp4>VJvfm4zHYn;Y6Q&Q zDuAT<@Ks4_1Ox|LrWsSQ-GT>h)?+U{FBu zUWCfath&)hbINV3cgnax_S@e2ioEq{Mk~oLm;vdrGSmS&CtGiainPgJvM2OQ87O0Y zVha=1y)?-)`+)49=W;=C$+wv!fE-#5!N+^#qpa>f;G1?3zWpHi?I-rPiTDN##O*t3 zf4f+|t&;+GU@=SPb0o8> zbij(EZnstmfRJLIXm4#o|*-EYGk!qJ7!ZRrmPtvwa&-u#Qf?g6Ax z^vC8sR(yYb%?L_Bvs!Zagoi8dr*p1n_#%w(wk#b%tp}M zwKRYq*o3#4Sy(%CDPM{;3)|M(qjhN=(uKiL)gB5tb*QiTYwU7B)CP*iH8OQCjfGH< z_Q9jf$xjf>Y)qv>w13tIv}J|*JBT)2tSvjs-@X;%0Hq6Y$ z$!qY@YqywojY~MBDU!uex1#8k=tW z1pIzWe=q;Ex`!_dgQpvp`us2hDbxIqL;sYW!>&OjrF&E5{wN8 z6CIy=u0Q+rvgaVT%z}I&?%(;&hd@YVW@|r;H#PUl*;v+) z?Qd`Lx37m}Wl!j3B}*p41mwhWk5uSt_d&Lu=i1*Aju3O6ipeJ;D?n}L6A}ZA@b?@= zZrt=_3dk+V)@SXa^mfV-y0L!ZygiT@y`O_`?O?uPDskI~UV9k9gqCFoxT6hX1hd6& zyb^>`=A0mGy&zX?ImVG^`J=stukKL{q2uZx)~mn$<=Ufz!*0t7{Zpu@?dFAG1(~ho zul&V`=tbM7O!6Cl^Jo8i$`2^V;&2n!U>gn;#RDbH+U&dV>W3X#?Cc{0*+Bcd&3TtY zB2e;gZSHRvRrEJMo+H$Epc<@l+NxcPBr=p^)!rjs6=S(~VQ4TyS0hknv)_N*8qWX6 z+q=L=Rb36dGf4&#NH{@>qN0o%BvHV`YE2Yn1~YI5XCzutYEiLO3Ti72GlEviz$BXK zIQ?v^)>`{X?TfayUu-L{`bYqifC?d4MQt_ssAn7>L0b&?nEPLQpLv9!wY~Ru`DtdK z{akzP$69->wb!oEDc_fraa3hpsZz*%H&O7E)^Q4*9Fd+bk%$JppX#k6;aY7+)~SON z+bg^8JSnNx?^k~(%~07@(u@$V_pA%r?6_-moE${X8Z=}|+pcIzq}~xa-AwazRREi$ zMA=tWYdohxD;E)#ZK}q*o>L)^by!hIjHv$Vm_ij(NY5roWO554YT1Dpa?)R-d9OA% zkKdRfO=^RZ_KkHHp1dG>Q zI4R12gYB|A{fu0O!j0rCBhq7aOcBt20K>UY>7RKSXTtFg<-Od)V+IcSf+Q|el5Kle16K>qrjT> zoAE}~qM=)a5g)M5ph?*cvUVw%5mAORdd~7(-Ut~MWVO(ut>GdDW*oDSq4COu`VyVY zjmsw?e6Y#<{kIcak5jCX^N(5Hnw`p-;X9e0u`3p4JDB`cZurpWiXo;O1&lUWfIwda z*}g=P?Y-8={}Q6kb*A{R)^YruQLMg%0gy=8ixtIYH7BWortxOs5whEfA@hJW>tYU1 z&hL~f0wI>_;C!zn{O%{!uy>b~r+O5MF1ZxHR?Jyr?V_=s$j8Ht+mxCQaN#?DAWlE8<-9)X-mhFy?y(7nj6Na!z&a}S)k1v(4N*wL!j2+x(9*#lP~3g zTP63kGVp$QuMO`GCd*4j3YY8n(M#c{zZ6`O^14nbbCIIt9Z{8{{CC+GL;~^JK>Q|n zXXuDkbc@r0#5Xk6F9Q6;8Kn-PW4r}mCgxRE<>>=sA(-Q6CsP@^3u^nVqZTm_^J~Bvs!L9!4s}0cleL=zm5MzfDbKvKkmPe(A~81Xwl4%1CRH|Gec;``+O43VxZg{{j4`428ccb*<)iMesH@1OH*E zi?hIo{aPQ9g*O;`!(aWfvFhdw$loG>*7{r+A6|&HUT74fXrtvaqJ=MacKWNk0$k?#`KBXJmzk(Hb6L4Tq2O*LQ`Fszn{g#&|%chka>L9lbZ}(y2Z6d{(~b;82(Z z+vP9^*CL!D$0l_umXJr{6#vJ)CVfe07mn5hP6-NwVx(dww7Wv@V{)Y8$taHzmBlL~@V6ha z*~Hqt``SUTyu#%NwSmONQx_Y}vLkCV{OSRJ*JeRaZEr*DiH2B5_Pi2|z3h+eRHwMj zO#A4^D`HPCeN!wzqU$N{Ph}R@6}2pl(LgM>fYp2$ zEgmSD19I0nLQc7Me~0{zzT|jr&|)Mo!^t7t(>ctUD(oCaP2#Lc7J*tR_UWhelRBZc zZ+~289~r-WzfB?jNE9hQl$7HsWnGm?8PH`GK?3x-Xl5qmC7m)pn=)CYP)(&oO`{q) zT)*)^cFWF}tgU=YPEJDFV)h5pUd*q z#nlSWUg{=NHIQ($ z_JVcWbpo)_az67n18ukkQn+%9jCh_Xc(aV2n>g9-WCxJ%a{GI={Vn2(>~=_cyNcKM z;Kjp5pZdN}?>g)-5&5nbC&1O>6@z)v$O-N==4$2yH{&Cj>t#2nACfg^vD%*2t{=%7 zkjWc>6OOf8zg{i#_y0doPo@22BgnJu8BNF-Yw8}Ng$JwiZYT#h8O3wptxQ-j*fQ7m zC7CgFbD&>N*cJ$AG46ir2Vaq_9o8(IEyz*8R6;w=|0^j1f2_;dchxx|!=!26cltv1 z`JyG%T;wskiZ(GI4rU5_Ps65SR_?-2+C!JOk}E!az8Uk*m#9|n!ua$>G4CQ{-SlrP zh zDErm{wLzUm*Yq~j4(oeJd8%v&8fDkmD68^rz$A&t{niNB(?H^a`C#nQJdF7WXGA3X zt!pkrh`aWJg%ClgINeqJ0X3+=!c1V94ruSvneaUl;Gfy0z5Qjv>s72+-9lj-sWXr$ z^>b-(y9FgbiEo%ohPkodj4taZaqa+P9#9>qn4lni&Tljf1dWDWn3ZkE2+R^U6- zDjWS+!n25&96So%;>XeNaI1#Rk z^vVP3$FcM>leJjF!Z^u{ts7ch&2{~lu@L=(jH;Y_5@j<#R5M|KAH8zd-Xk*s zbp2AIgdeuvzfVmLeYRPw&yTcwy4|i)gve$@BgdXOAi&InQxS^?;SJe(t7Pkabb%9_ z@ir$SjuyE;!VSJ_iawc&c&B}XEG%x!V+;>SV`RU@7#^izx{r3=0uXItnQ%F1GpVjz zCR}4A{6ErcTrP*nLpR`Nu7u`OY%&~%#vN|Hlyjd*#3^>u#R_KQFIQ7rT4ha zk`5H8Rc6T!Gxo`$v<=kj*%?R;iKN{4um5o2d69ntVbhHWtuiITo_T z!IEuMQbfxi<@K>JP_k26hH)@fm4l~LM4?2EOGDcXHGN8Zp)Zrr$au^}BYU(z_M|_$ znPx644tYqJTL=(i0iqlr{2i|X%PuN+0n3MZuoMMKo>#CqoW`nVlt;WrEntM&F%wfqh!z2`h7w6Uyu!UdpfABI#wrO5P{xB`?uNiMOCD&g7gk(^f*Jd{ThC(3QM5 z0q{A-!3a*`3Sv3kijy(%Koy}Ugy)L}mmQwF3i-an?6sM@KL1o!pJ}Z9)-*Hvi3g>t z+`M=aRtG&tQ#oe)W_^DXzBTgPB)l~(>n1@2K$+`MupdhJ(Qo-~t7fUA1?z@rRlRSs zn?iBUzIzZ;1OH`mW6)(29j%pbz}%m;44HQAhIIMARun-`q3F)V9|#-6{RT&JJAc^S zFCZrQzd9UHsa(`>B-VyN-Nm6R0e&Jg2?bL|8%o;b`7bJWtt6MOdwHnj1?6LuK6k<1r}?WY@0 z+)iH5)XGoJc;Y^VBind_Rm^xU6rDr@jTLP`^DFiPfP@=`>zJQ`VwW8&CLF)E!#OBC zf=U6$JyHURitD8piL!6<<6W;3VfDv@B;n>4W~jAlA0DhHqeOgI)hr7zQSp6Mg;FAp zR>H_RVnC zo-IO0-kZ0Q24p3T$~YVuupXEyD+!8oW2Q2#78l0}h!F>@52Lb@Ze%5?Jra6~4jH45 z;-(wmONaZTdj`vt~wvVVQV{ugL*girU^cX&4x(_a|Zt%1a>0qp6QjLpi2 z0xd;in-J|NCcbI!1$>6aqcO_pU+|IPNW&&~FME^2q8Uv(m%Nol77&SMhM9%lyaVY* zv9YR!rf9|ntQ+M7NjO?rdV{$k1DM$|B7BO!erFc24hRc?buTf@meK-&ryY2@oA%CX zDIF0y_j7LJsWTVc5xHeVn%UN|3{D0X-*PT_TQg)|!x@wqw^TX8N9i4vJ=fl2wPLFA z3Qp^?)mAGG+2vGgL!CFvmj6>tzfSc-vS!O?-!W(}lK~QZc)*8l^c^G{y3vq0!yXH6 zgk`F+e-$T%#|uS-Q2FB3Mm8z7Zssu1@vgmM!ff6uy2X<>)6{f8zunE_k$Liu`fZ^x z2%CzEy^;1l)amH;u53zXb%2@q$=OJ}eTZZ?d=;e6jB)RrYdwk50$HI8p-xtz zM+3|uN7!_c88^x(qZ$z(9P9hA@`p^nZ>(z<3OQQ1N34U&GbC){=Nv#i4$7P%(@~l4 zqF^{d_<&QD);SFbp;By-Mn!IRI&L~THB5e&9VUuaSL7_mvMeK(<3eoAdu+^mH0Cp! zX^l$tS5%oNtEqFq8Fm?Ki&IDP2c57qI+{j{Bg<%Xc&Z3K(>YkTDiu&vAax7SQhr40 zoE*?2C_hC3`+0SXn`z}4bmYY-g+Zs*k>`Q?l)!tO4R0t9)Uphy%ecC^S;4$N^{*^^ z$0($pmjmrI@}I6ioAPZ(0eER> z^^8DSKC;y;ZD?&QYiON2DuX5t4+Y`l7HzAZ=Wy)XR2VvYLC4l2W8K!3`+orlOTO{Y zv8lU1Z(k`|fcw~;4;|}WdEkFo1Y8e-?ie`aJB7lm@2_I9P;C7^8U#mD0Jxypc^kbhX5|Z5%OTUL~5dW<%Os zdzmw`xhL`=iD}_(#ona(UxYAID2R0QMD~;Nx=txHnqMSDmD3B^3aE2ngc0r5iA6^9 zV>{fPfGqyC%TO0pXtO|E-$rW%RtHR5yi0e`kcKp6JvhR;MirX{gD1Y=S|$( z!>OJV+x7f-BI(m$-*y4pFr)d)6f)M{Jj@g6>LGAMEwEhXjlUR_z^X}!L(s&$^QAF%HYv0m#fQT(vWduX>H zj5#@bYNGX%57DcCeDEHOVI-8PuWX8Wa`E%GGgwP{5*m$CNBf`&!! zAJh~ru4N)LIQu)S;nBWfGAXJ$6#&^fNW9;0W9qy{lQZhT( zU(L444cmjJP%hWhOs>cdnQ5NZsfV7BW9)q7!Nm76Gjq6bYvra$g*T;y2X(#2&&D%> z)LOl22>UtMUS#E4B9zEbm>FsnjmXf6GxN#I$$YSLUgXS?pCgHqP0DC4(}|ZATP@hFT7IJt9%ckqvuXb+A5+Q6PAV-_Bgh&%8O^LjYjw~h8 zROtytp@gHF>F6-lHsF6;Q#DPdTH&;WR4FoLTIN1Yqf8n8aHG&Dj(FMA(tk*KWC{+p zW#N3IXv`YvqD^~LcWv6!s^b;yS(c$a3p2E5Za(d~Zzw%ED#ns6Tx31rW--4#=DH`o z-eHw+v|%xOs-Eyfo@O29pX=}4u6GZ$I>lNoM+nxvD0LMqvc5e=>KeW1iF=PCU>Ul) zYF%4)M`--inq*&lN>Q%E73C_5RB!e!>Ks&?xB4Jz;>=a|sdVh`Pix>0y{G-RbnG^} z)_+4p=YMwN|0Nw8@%b8m^{LP7`F}~r5_YZsrsoSjyYc^$j+KAD#*)+6^fSvEt=$O7=1xacvP{$r6E)vl`$7P=~vXT>g6B33>b^#=Rfyzp= z8Z)d8{9O!KORB3JY)6$ww`bqWp7u8iWBYgY?XvPVr^|C^+DV*gkC0R9O(!6scZIoZ zv*~eBo~BlFtRB^dEKfg z@*I&p#opLk-d%5bIeYkw^Zt=V>HkR|zTR!4^k=FMnn%-4i9zcAJqoE`eIbg{wV0MYaf1)Izm4q8j!VagnvC-3{O=8Hd;_N)0)JaoQ% zx9ijA%W=AE>-f?0<=DKgsWTqpPh^7aqGoQC>&MmGP$AWCTZ#jY?m(kH6^zy(4PWNRxX8(d8rJsnGL=L*|^xHmBlW0}Ns@G)-DOH8+S7O%m!}Bw$3RD?ake)H- zK`76Cr)L^80HOsD5Jdgbk$fyT=&}2@pFvE59HGBz{QmlYz$pvW2j1Fh%CAOHdIc?=0C|s z(is^f**P_q$eCa4q-?Q?Hlk4YRa*5NRz*u!B`ZkVE7i~iahs7F;fpILDKeM5Ex!jx zXL>LxTlM6}IE^||U$Z+fG1Gxb`H)P`W}osHV}Q+24t|v}1OMdwQd6>}PJK*|bG^JI zrLOQ+@6Kq!P3QBX$ebisL0)sqwH5B^Ua7Tr;zFE@E18=jr(Rdh_+OdP-N`7*`bt#% ziVZY*AqFP)cc*-NbKgfmJCe1z?`I|bc=?{A6qKk^m9?sV>_q8X=j;x~&2lbPS=w;X zx0~76p(#hciFaPU!~vjFaD0U2Pi85`AJ|=|d@0pi%R_rvP7^1!t3Sx;J z%myU$j;E_JCY7CrlG~em(Xz%}zyE^AVeaf>XOau*du5ESFw+xWLg{RMYf&{;&S9&Q zM|@MS*kg1^d~0&UK8GNfn|*0}2I*^hhh=b}5f?vOcN$;F{|Wvswu|LF8*6|>^(7CC zaJgy>7Xy`#hLQF}aZ@HcQEd3lXuZQ|>Er^7PBE2x2d;s36eruVvAGEuxrw=rUUtYV z+QovGqj=gL})->EIiU-Z?!oexid$Iokm^{Ie7hlexFpfPioH})&6xbx1s{#Zx&DsHv}>R$-IEYH)`G{io(>1_ZXfYCTDi#LM$ zUL*Qv!rb9LL3K!ERWqpMh?!?i8XMXbD7;$U%bV{OsLWvO6~G9{TYKT-Qd1nnpL3hf!T? z90y`o!A@LQzMgKenw>13xr3x=NP_F0gG-F@*S6RK)YbRadIGp!1br{Z4R* zO|+|CXP4ArDph8=?VSU@vr^yZUQ*gRVuLiA`~`n7G89g0oSd+P*D8qYnHJd^X`SU% z*VK~{oyXyHEK$2tl~7v_^Z0WVV?-$?99V%WuQ;pe&P){r%ECD15d(uNp|_MPyzwH* zsu?m>N>l3T&b%73Koo9}VuAXOrJRtqhzLx9w7U87YI3>h#7DMEO%SW9OUMRpWmQITGdn>>4Pqt&Y`UVWbiH#7W zawICwm169|3$2E01rqR$y_@Vo;WFjNMZC(u4`O)YEmqf3XsaG06RFG%NUuv@5@n-y z%MV++wmW$)JAA^=CzqjA&Fol%_M??=nT+Iu24ls8>S;;|{X$(wk~AaN7RNzK<`)?2N_Rss#|itDf;cCOBB`HkvSJt1`_9UPyWM#Fm_a* zj5b!uQp1vOf$>fLpWptTvAEr_z*yWbBJDt>Q_D7z;sYwo2DC@Hw%Bd`?~!tM(ret= zm3#tJ`fAh3NBOPA+TeL?kc#kivojd$=Dw*vVLDA9`Ifl5s^4uyw=yNLYbZTEn3$2S z>j=GMCcb2dyWv|O0TgAS_=;T5JXoZmyD5f#C~xE)|`!yhaZLvGHPLP*%eu;h_H zSka$14OZ5OeiNJr64$NpCnlY1MxUs`Q#E*gf4Xr)(Zu&>7&lx!v0Q#Gp6HgJhKV%` zj8LZ}2PX7L%=Huc%~b@$`iSz@-k-W4~RhO6>F|sLkN4;K{FPl->wp@S4D}$ zwMNOsV!x}4Q8KFZ9%5AKO{GCzaP1?VfZlls=*@_L-k%8QEsKEO#n|d)TN_Lb#g0Oj zl1va`z?3Zmimtibeief(kNj45+<4mb$W&+h^4g?m1I=h>zgQ>T1=(P(h*lQS7OqvdGwiie1=z#EKnVg>UgrEXg8i*55pUl|YA5pp`C|ColMOkb0SJOO7x z$3KSQCS;noWG}Wg{Y|roo#!kh`*3f^D~EYI_K^JQG+)V+zLH(O*z>6xIPIFGJb*y@ zFmK6wzSz#xF;MNZcLHmOr2DJxIHT%;p81&%R8sq`=Ou*wpnAT15v zoUu~F9H~VjHAl*Ja!v#@Kz_yLHB?T{ zFEQnD8pU;ehO^^f8zXN{3X@lGN`AppmA=MQeow9_$5WYjI^oI2Q8_8hfOUl-QkW01 zIu&Nhmchu15slIBzAQ4BD>6?uYW%qK9Q-NI>Eh$>gp7~Bqww(uiy#jE-kzi#{GEV^ zr#Ll9ocx`QlfVBf@Ib27qWqoC0iU6q_+ioCmFM6u=hM&j!LnP9+RvogGOIx8!?b@t zwRK@REXUbIQ3;Mb@$c7z2*ah3fPX(+?8gTD*sU9PZVDudrkT!OnUsSa{mI}6|9EIe zf7StZ2F;_0q4B4A`P+h>orvg%dineA6`GT^=dV0}so|F`msvN|KVd%nA{^^To(=q} zCwL+4ctt&&J5B~wypk$-FXSh@cKa+>t#~5@TVXxO#f7p$F70)#%bHS+C--W^n_Gk(;v7w~H z8+)quZS^3AcARK5e<DnqRx=PYtm>(LLiyLiRZf((QA4qkWL-k6ymS;9|# zu-fuR+Y9A#8H>MQLG)wZr+{Wh+v$`Dn=RMH_-=kqt%!p>#|)k>O8$pP$@TG*47Xf& z^KKZa=KWr4=gD&X-D{N`r$@0yD3zkmXL=a{cmVGH>8t8*P?}1nG5Q;?pt$v~%j`|T ze*bdiTM?->@nEI;wO<&u-tiC#VHbnvcO(OkZ})$4K~=~HD^_L3kDW8#LrX7)E;SS9 z9REfgC%=6nj>^fGG-*_O?*Z=y5SmW!YIF8C7;Rs~9}^N+NN_O^^Cfu0(Srf0T&xxl z#3zG@uj6HBeK-xqZ+|*G1GmZCTo7%iYqCTpf_-8U-0rL8zpd#WcIpL6;;UWH^qa;* zWgi`wCXa{4y3!RZIfV=Q|BzMbTMejdnBhnreC_-ItN3O1wehW)z(mDY zC2JzM+IpTU#erHxWn`fbdN2F85^deZl}5=!<%deo0Bn^%=dx43oktS~y)Lq-=0)`g57u&$l}q27~UFlT?D@S9g(+_yVBMSHAo;3^HEM7*b8Z64&` zd*xfpkY?moQAuTxdM+m;s1GMz;#YI#iZ0qY5u^y~Vi@ekBl-fRGfAT#ld^%tH`Z|7HuV+e2R^~@=^d!wyaYS-gtR6n>bqwPQ>7X= zW2y}^{-`v*UahD4F7G1}z?1hIf!Hs1lVHZUH2jZ1{PzM7uCrKQ6?Le`8q^yo>55;V zZ1Bc9S#qP&6|+eYS-`IW&Byjv-(|FXNh+*3gOupN&DzUm(3w{4;W{f|oX2Y?19m@* zRi~3V=@Ag>JB?Lh$q)2v6!dReYsP`E@)r3t$`j%T+KfLe_~hbjIlcYgWBfm<99T_t(}8o?mW0_59)j8(Ya0Vd=kbHG^C%Ic4AWuqMse!w&h5`__;& zR)Sq>8VJJlRFtVYcq*2YO;5$QGxM$1c5j?NAK#;jO!{c=<9b4dR|jKTQkN~b15y~M zPG#n!3=B``Si^#9KI(C5k%pL$0zq~@J}T3P`S>nR6ATE_Vjl)$@A8I|WX4at%*Qng zrIv*Bl*^aCSYNv0SfVnsasy$Rm6agCE3Pv&Wx{8T4o#Et5f zc7BG;Q`K?i=|uPI>Byt9>@HU5D7(Hxt&Cq{ z1fy5R<}cYR<7T4d3aL0fZnr*S+h(uM`YZc4>qF*1W__sHk?E;bNEe5$59rBftheZ+ zf-*;lvx-JurnU^;{&3u(D$OI8PbG!h%8P)0ih~a&3C?j#Hg%;o*onB$e#pK`X6t)0R%DE&dj!-O-2Li?>7c+Qd998#KN zmK#?85tTvI!%$K=@t!Yvuns63gQbpo*abN{+!^X&6yyol`*!V+e7cFxB=>alAO2P9)!yMbPn%I~Fdcr(2(p zo`(CpO5Y^x>B(;CgzGPoVE6J@gae5n77MBYGPR%%gwc!#i>(*F>2S3A42rbn6}e9r zF>*yNvWv{&^u3&(?YCBcSwZ`=ykZH$-t`(?xKrJ4jZ>vMtY<)54EA!)0MpHAo+zE* z!3tZFbN9H{)5*i_jzvGIT6!elJdBZt`L)tE-bG9Ascl!j&)TZhqo#O5lRE)z1<7B^ zPoWZPw-u>JP1{^aIcc{IQ;(Xq4NtC;uj15q+DcM4w~a{M*fuiN)K;4MW?Nb6+O|=t z1#L#^t8L|}E80egcu;Qb)9%m^!SjGBv7gLTW_YNvUCN z6H^6kRjs~0hU+c}9K*%L%#1{w?UIDkRf6z^_|vebSR)vTZN|1l>+aZQgj19Cr=>J= z&4l7sZLErHEQ`^GWAsXs%ffl)6WGUm`g&51_+mYJNxdjW6`3U^?>ytj7?YknSd#tK zOrrQKw#w5CsbgrjsN$YF~+Hllnx$s@`!T;yH=n!iOX2 z(>Y$2h$AIJ-5g4|UY7_3wcJ^yNS{QAdx|7;Tq1T$1XqI{NpY`5#7>D&nCvH(h#rYh zmA~L(JgOsJln8}i*(In$LCPJKtQ)QuB!>vll422e>MNq!`SG80I$oBFhxpe`y^4A3$a{g&ouZ#3iLpKm5E;yJ! z(EABc{x%}j>Ro!!e)7*Fa+EuNKhgHu;uOSI6bqx*}N80Zsgx2Ale9e+(VfZyO(J_;nxLzhd6(r5ePW{)r4 z*cWu}_r>S(YT>S+^GRR4F6ew&-KmJSqetBq7O`~bM0w;<1nY=lYkT#1xFKFNI_T`e z^?f-4>9D*#S?m|>0e(H|dA&(ZFV0H~gxb4<@dZ4X_(l;X_!D(`zc@QVt#Zd?*TenED^lbwZ#7R>EhtZ|HRCi8 zkT++#gk=Dq{pxrl*BR{d4bMjHw{tSD=WOZZi|H-$<~&J6s;0=}vP<`Xk@5neNo7 zJk4F6t~dhiYuxo`U2u?Pxhfc&IksyiY>jjZ)L9>48&71U5@6I z!0vCM06ZPxKfcSW+DSEhdxa*X{qFE#W|w!YDjDsd@zFG{k>ybomgyw&G0SRy7Kg$6 zGNt~O>V`KAXg)l_&qmoCtz%}|!jWdFk%}~ZmIZ-)#DgpZ`G~G>G4%;ctt1(P(bE&o9#!}w+X}oT-$mA zsfyYc(S*MckX~pR0(rDRA zCfi2cSbN@B^7mm^;bxDr7`1*sbhPt{`jaomWc8VG`SJPu^)Hw1BPrz{0 zvJpm>e?(i$`@(0WDlxtLvS@b%x&7ARvQ64EBAW}2$n|DP2Ci@e*acv>0(h7iJ6F}s z$~LkhC(HUS$Id@Fl|`>+o~+hs)sEAhG2chYQ&}(8O?;w_{!{17vCh=*KYKsL064n5 zUr&I3>jo~i%P5M>LCiZF1eG~{j{W!AMuA0AYxhy(jNJ%HEA{ee$8J&6w<*YE!Vl7-G7ftE409z+L2=T0QeUku`6KK@6v=xYbd z?P39NKzpYSkFa??#gzJr?Nzy&g1hBnraUQ{AX>;$!qtKtkKlTO1-i+0n(T)A5hB*d z4->+-nk+qh?^f}NiVrrb3DRzz)G%1yW8VkR)QW?RRl&u1g@-}RE(=9+VpzzI3GmzH zQSDm1Jh?9aLml4u!M|Vm1B#axv)h*oC3%OdImH91LL}TWHg5RKjsKKk|KlaVsPH8^Rske`5GM;wva1 z_uSE<-XM0YZ0Gw`QpH3EBechh9kxkD}Qec}63C3i%Y87GErP2mKGdFc`2o1+zdsT8Q%B!j@XpP)9n zTz{24??QD+aXVXcF!ls5F38i@V6JwnueP_g9r@^t__z^)>fKGFkwW7-65Y+FAauY= z;oGstk74Sn-&5F+7b8mY>~?{_`spxFXdp-WrPSK;cDOPrrdZxMR%+eGZBG)eMhj-l zayAs;?elG;c{Wkv>v}%!ubUqf42Q&yYx3Xz3YtL%|MKJ^8GIWpa7Xm)d24r%*qXv? zJg2I|Sd-y<$K(}iuu|U{I>r|-6)*aFegxwU!v|7j_Wn(0kzk268G~idl-7&&FwJ%F z3Jk+EU)$TuFqzq5x;1$()8r1h2sU3KQG~D{Z7VZ14_=x+GQhB%2>yi0K*nR%KMVdU zH2)yuXEc9N=r|9Dw}a89D{X9^pBOV-usKqRC6ALVb2!Hd5@i#w?ud;z-`OynnSV>= zT!!E|qvajQdGeq9QPW}JAQK{%?)~dQ=s%bfcSCPQt~kmk>ynfwga9LLQ1Xl#5XgYI z27ap}^W5rIJg6u&Mts&q9=q)GhbsHXA3&PiOzo77YK{d^GE~ z8>j*Pss4_JksBh>)!7pcckR zUg=hd@1hKd4?5KBW&Kfe_*Z7^udI2anKxI!n~0MJ3YS!%+r#>K#=-NKO9*>D;(irO zEa?sL={*hcS@5s@4e^WMU$+IFn;PP$1)a|_V{weS$-~=(;oY&lT=@tcuPg|hmN2rl zy&^w{e=QI4pu6H{6gpJUfrkRTJ-F*$aTz=bsI~kt$aC<*im2-$sV6X`Vf7{=}FnhRtZcpP8&?{L+hL zwu5t5aq@qN%rxI`J@`f4d{Q2;QnP-r899Ugn}_XLzxvO5CmcK7p1I>m88RIT*67Im z=`ckyVnXM(=A9#DZQ{Yt(EB1{u^_i@a(q%Zdz#{arWIzHq%oRF3QEO>56p1sW^;}k za&c8&Z|UgT_?Nf;3BQrYoo1PnUT&rf2_1Zc18>j`>yj_xmL zn!um1TU4fsBo7OZQD|SkjofjHrm@1~nM~oA^e2l|I2;bHnM;iW)^~MovhaRa%*lg` z7_bYIlqkFOp*n~4-Lqr{Wb9XM{*O)w_vgvf3y-KcM1WWPVP1NsVyZpF{l`PUUxpRD zbrC+aq`z_-lQYy%z;~*f=h8O?IC=GLOnH#(V12C(PYv*9^B)qPgY6aL>dK&490scU zaeH}?=4A{y8i;OR&;J(PA%T^Y0;=YDkBV0*tujz+fk00vCFfIvC}tzYwpvp7^8?1Z9xS#vLaH)boombXKd4Y59adF^owsCy&3G3no#I`yFa zG*JJ6(R@2K8tY&=x(W^|u$ub0+4&-7g$-m4VJL(%(5?b6PwK5~chD41E4F)A4#-oA zO;hm5H$kjt^gD-a{zog|N;Ua9}^{% zQSR$A%6VSe*8eIl*vw-VFW+qa3F(|M@(w*;b5vQlVtZ!uXg10;5mNWrV*mS#azdpH z-r8zUVa&Di#ie%9`EVZ!OB?L#pu$C=!}#kApAxCB z@fde@dK~*w$H$#UH-;?deB=7?0`5YzpL4wgqPrcE15SFMbTec7`bgpH>BI~iL$sSQ z*LZ+dxWi8=Am8&#;Z*51bmhIeK7TC|ujCA!}a1{NgoS zXFD#OaAGaH8fqe7iTkm`@^dMCYd}2nI=g|cIQ6X3houlOeoB^t)Sr}DLh3K` z>uo6BB!I;Aw5#oCj#;j&p?vKo5tuk3nM@=zwzKIu4E-V*B z90L@PgNDi#+)o;9l>3jD7iV~O2A*DS6`#c)e;t8(CH<3ALRBl5BIF&X`9_s;OWsgf zYm5$5dS&vh5UpclLu*6jWexb8noHoz3^1=Ay(x{O6KZp04qlH(h-w}RKE(GltuHXozA>%xz_dVSDE7L%;{yAe6=4_lxo;9nV3qO=vcF=xw zaQ$4L93`VTQAY6uyPY>P?Szj`oj4etOnae`*pxZL$3)JZ5$`5e&_3UhV{rZKuuujII}8V_d*O)iM0|GyPT^su zrZeOUD0cFDt##BAz@0p*$i%gpr`XZUg;E#Uj48NP2J}BK-iyN6! zLx)E{oEI9Em+y_#(f$u!3^;e2X%37%OTXpEIhyVVZ(vq$3RSjY=zpMq6KWJszEzR> zDd7`q+XVu)v_z4IN8?aqj!2D?l#<9z&MC&7?WdRcoj4^K)hgV>1?4=lIaWAEaJL!s zEdHIKr^6b6r&jkZXW9{Os0f9x9A!}QgF29KE$(VR##7#64qlLJBIfOS`e;Kyi@gJ0*&I;ZzxXAmhxtVgx|0;|KvHR2oDZJ*{1 zJ)W7nhfyVC0ry#rmY{Bb|PhJ6j2WbkWa{>*(pH| z9CGe=0%UQV=?tzs~Tf-bfw0?%J2Ue<=Y?Uc>id>KKU& zS9tNV%p}?zdA}qFF9%k6nW%b~v5M<6oE|p?o2&VD>!o|KPdFe0^8!k0;I)|rli%rt|Kypyhu+(sdu&~p~!zfUe zEp>xr9j!+NV%}ojtS(RW$&}zkFFNVK*Gm7$0`R8yFbb*TJDtN)9cuohD!dy+e44^D z0t1s8rYU5w{(0lJIPsKUr^=6^d@tiC3`SMza81lg6}ypgDY`|cS)NVT3oVS{e}SDO zJ`*D2bsOa~p)s?0?9b0*e_kH@s|89nIDd_LWSJFsH)l_|@qFVK>=pP8BGjtqHqup@ z$a0knLDLJ?)0wz2>ePxA(F<06CT?tA;Yt-L{z=&GOl_sEwrKW4(YpNNY+*1Ognt47 z!bEvknC);G&u&sr)2vh@-H%O(bRTzRsnY|A>GooU@^ggkC{DRG8jl*1RFHBhDotDd z>TYAzYQd^=KM&FfZ$F9|SHeQ#Db4-!LPb-Hmh#GkFmoEX;hzfJ90gnvz;%1meG05P z&UohzY5#M8X4darS~_)@?ZQTHiDkc%E%80;^;(;=8?^snzsjTy#GX`o(`V(yTA*gI z6-qBWOHg{fU{fyNF=HA*>C+7JU(i0y{#t2k(1}Tsyn?`t%%Ic*O5550+J~a_prjm1 z-}6^*Ggi$Ovk5^d9@=|DV?e26>Z!(^9aHCV(fA2(@zWv{e_O#}a=lT`KH}@R*5G{= zuTiaE?lh{KE7jOYN7R{Zx7AuN9bqHRb%ahFMkj(_E4_nGV4;r{f3_1Q4WQA2zb{OU_dN#=Nd@Y zun>2F$J_cqt}zRygiD+)*Et0_a+_0>1i~$P^tJXF*R%AcPjzCwvy$VX!_)d;WgowS z^Vw!>#&}^I;T{#7$`rSO93udwq4gJ)#p?Hw$`XFzdd!4=W7Ud@u!G@PC^6D&Ybi0Z zSQo-F)v&>SpEjoQo8VWKw=7FiA;_Mm4bff=7M zJ~Ks_vNmYOS`8a98fatfj480Vlj1W@20K-PIiuxC_H)IXPaP4SDVM-C_L?h&E)GTD z?b+8O%So4Am8#s*xk*%A31?9dMvRZ;231KFG7#|I_A8SNgy@xp1HVvSe)Cd;n;h3k z4VBcO^f0VQaVFAwJ)2tV)s+hyxa7B}fzNBzdbOT=UqokEJyX>nI>Iy``GDR5UY%@j z$p?NW5ieN1Dq^U7EhqRxTV1i`Y%!`0m5W%-de^5tMIq`-SIk0^n6;-?I#SoES@CqD z?8&s2`uD9V0w8Nq~UlXZZnrUT06QQQ{}jvu<6d1%Wkk6u0%u%$@6T^w8x~ z61E00^U#kVmHp){?kI5lzqdONa8sCaUdx0 z8b4^qd7oq3y=N~Sxn6#1dq3DKOEhtZrF`#9Y)KJ->)PTN61hE^3$D z)tk(CAvDEb-Lb?KKfgFt!k=)Ues7bxQPR!ofhDe_%pe5wy|P1<-5cB1 z@g~*w>T2JdXgYh0RU$H6)T=V=jBQKJt>1fNh46>Xdr0u7w>Bj1mc&${H};;ldYg~; zkvmc)!9_1hE&h(w#Gv!}CSS0=qvY_eXTC5QE{7ON(8&D zPfn6z>53`Ln!LHuO{ow6B&CEvC(8bh{LGD3_2cW-bK`-Nb(3Wmk`rK>_}O@(08^)G z)%qqqU$XW>*Une%-uIXY0?jM_Xa7TmfoQw^A%8Ek&Nty zRn|^bHXm5RtOPujkSqrWm5)cl6%*=}&BO(KWNap6^R<@{GRh)JiO)1!FBfBYj;d$`5@nCc48TPh z!CfqDg6nCcT}=$s=A_Czu!zr_Fmu+U!%p|0^o=YZ(6$B7TA6mkRn+xAe5NZ(1STb( zTBe54y5l%)_b`yWj%jSIyp)+Mzx?ZL`3oUu^NYq^Esqky!nWPJ zzDFvK?T6K0wsWF{(iO|kka?C^PZ>68qxn7H#`w)lJS=wfKaF96Jv`gO~%nMg=+nhC~|R`qxWSwj<7@n+gP78RM1`uc)9 zjI}C-b#<8^|2eu&Rfld#1>*|wfq09Iqxh?Vv%VfthFBfQ1%f)sRlC(6dp=$9;pu}$ zyya}xQ{+)KfkNj*9=!*+3V0DIepjn>5Jn$obcqOITP8p9?bp)itneYi(qtdV$>lR6 zS8wvp?oWm+g%RZ-47G#KFm1*aU3*7}0;_PE8_hGi^K7 z&r#huR3}Q!!ODsu{Li85XUVErkoJg_Yj71AvVqM7{H)iFxJ6vy1(fedxvY^qfk^`Y zq^jmYBe})W$1vq~JKtP;t5Z$^oShB??cU-@ode%c@hjcv$k>}j6(@%yYjc{iQQ5$e zI?q8I<|~#|>)Ra;2hqrg-;t%5EAWF%0i#(61Uz{;b=xa8eg#)W#jk+T{9}OP0X?@j zaxMzfh=3TsfPJ+@SQP60;U>mAc&{S7C&lRia4@>Ooz!2Sgx*(}l!QdH zA#>wpjqKv;j_#fxtBEln)KD)R-&k4!R<_a@-RSa_%PL~?9Iyg!GZQ<9vAQIyK+QC# z)-GS8{f(9BT<*p%1wktmf;eT0QR@SrkX;bueMD+g!j$mYgK#ywU1}6{?SKeA<3SjE zv|8mpXh*QzD4*jts^|0>)xjR48rWdDN$0!;U8y3jinP(>8BN~NKIt(}3x;tUwcKMy zx%NB?2~9C6-QGt)I1BZfb}@*ZJx=ixuwI#cf>AO92}&!Ix)-eB7@mXlnpS22eU&@F=E*r zMEE@dI>~M`%-cEKk@__mDkK9}=Q0_Rf6QiZrf!wGjh5}=iXlE@EGqBhCc?S%tkOs4 zCbekeGFIa@=vg~51$Snl*uN}a{MlfNZ|k|T_u*FqP~O@YD{BMEh)<3hQ26a;^ek|6 z5&id+gTJ28Sj(ZV=>>ZjE(Hr#p+gsUIO6S*icXa6=$o z7>J)=F8QXsgPSYBLs*fYhq(oWa$~D31Ipm^^Q1k1Ibe%=7BJakno8?T9v**r~!ObAw&_*)f@L>NALcA5c`=V3MkAFulK2OL9G_ z-_sd$ww76A6AH_9oGzbbFG;$w*IJuI6Z{oM~@PttI3WK@jxa)VXO&jcD+*lh~11?a-hR$HmYPpk-xT|?^w$nSz z#P?PU$`TcSWw)@}PlLC(RSG(>e;%9}x8?DO%8UWlxtKkFsU2IPirT@sN|8QokX(-N z+r%t${*!#Mex=*O1`mTP{)*Y4dYOT*T`VrPd* zCMibqE5!N}9`S!xtkomp1??r4dS4TYwf%30C#ifJbv~)iX#PDPq8Pb z!BnJvWw*$d)Lz>jB=22_bZJ~NP+NafGn_beh>BY!z>GSQ*Rx1r7nF?r0V4eM`;6Ou zOF+&eJ6>0O*mCW(oEX%f)!u@CU>tCxOG3fFCu^)KY-ke|B3gk%45_)n~&=4 zrt?YBDIY@xFegal;f|`Zq$;_H3Q@~a3d!`~q{sGh6;lkNa@j?3I8(Lrp7pqDgorQZ z8a_qEWjBpEuu*qNcM=a)M&!54S1hC=a!&pFX^cwCZ-}&avrgYX0c6e^7>zY*SHrCf zHw6h=?14?RL9mS)6tBQ<4`r!YY<}2Nv!^^voMbt}zUcIdGxd6ee*4<2-(rj-n=~|5 zJfKnY`UEwL(VLWlA;XOZ=#py+4(s|~$ckLKMfxDygpelH9ywiCYUlvLRrKl5$;Ofg zUBzh0nh3U8jtYBs7{cGOJ-9PuI=Won`2d)gf3CNOJd;1YKe%lLPrU4@-AD?6{wQ%* zx@3xSu*LYvW{w~1e;^r3S1jbOh}Ncx)D2x z`)6W-PVObglk+e;r&!M05X-YJlQgFkF$YSWUe2<8s}PoupjAJBo5y ztT$b8z)qd+*B$UzvomxBogd7S4w&`to5u9_wb_6u#F8Bo;n!vg%&k-;HJH>OIu!UC zSr?ihdaumut*u{!dr|&J9 ztuOtLT1#tKBW;Rl(O0zAYZBJZ6t|ePyGiboQjoNNu2hqDH%n-Z_4VCq3H7mra8NEw zDEwW$gi`XYmQJ5l`!i)Tsty&w-PT1+-mKsDgZR_D`EG4ITvkO^AEWr!ymXkBK7Bu@ z&)Tti$a?sE{h#um_n)&Ei`MQxx3q+n%j-V}E!jc_^&jXMpltsi_?-Pe?DO~k{-OQX zCsz?XzEcrw zj-?;{X8cSuz5+IUZ~D@)=7!9BHD>Kjb7S@yo7zog$u{06z+yF3oynSc`bK5VzKEl< za-ntx`VwA5aHLAtmnz81)SfI48?gCXx2fAm(0*U>dUZrVPa=CZ_cRa3iiB;vH^hZ^ zOiI$-*z~|%_h__>tWkJrMG;`6ZAy`#OB{a@+m`K`CWK&er>lSvY-iu|LvhjuNRH4E zFoJ?syolPACD|pg#+JKbM=$11u{u^PcN@*$VNIFwn#^O&u`o%P$={>0hoKx|iW79F zE4H5?ERXAhUN!*rYJt%LNr4`6;DR`=qvqNmYOh^^z3`q)4V-2O7XWg~-p{6`Q8ttwn(FjTVd1#` zu6TM~c#$sr=FRzqD=7?Tf5$=k6@9}ky4=mVie9<1ynV5?>bH8a3M(a-37dfd1giZ_ zQ$$V#x_o}YvDR-WsKC-}n7SZvkUns5d1LM6lW81O=iihpwj5MsqdIi>zRk{X9-12l zL3gmead7>ScC0x#i$VUHx4jO!UfrwGp#G3rF%AG3gMbju1stqt$q?;Pbq(7+xTu!T?V6 zmLjSePktl?9Dl>tc-x%Tk6zcnxhWjJCiRWl_FG-w{+-%+t^%kU8z{FlT&3x;>$`dY6hqmJbh28KVkVqFWZLwN@Q&W1H^QzWb!8 zbyu+_vP=ejpBKE)!)vhx7Nb@XP>Dzfn0jnE`_E~|sFK9!mKv#*Dcz7;zk|vzFmCX* zEijGmDF1&s!BDq#`N6du>bH|@IXw_v+G zi|qt?W#Uz+jeeP6d*f}ir@2s#V99Nr&aN!;MA+3t#ogr5Y_r%;%+DAnD9)6{jEs=s zZyd{6z!^e$-yWU=ki68Ja9!PmZ|>fdA>Tj`pMW#Ei=Yf}r*arW0w0L`kuQ6g8zzP% zp5w6sslpoDO}pm`Y;bK>3owcM-#ni7vrA6OlssRRJZS&2M|-}Sv(P%8>e06)GS>*g zyEIOfO-A-GOdu;i6{aGOL#vWSgK|k$s1KN69i(@zlx*CFIb-yJ2w zTQ47I_3bCYN4x2YiAOVtYh4~b%;-7t<3Pyl4!b*j6X7lPi;`N8gNhJD-vXxykPXxzWm)>b}_T_d|xfO!kWKTEr=)oHlW(CP5B7GQwGBN(|NZXr+qG5wX(whEwWJmFU5w)Yp z!ubUSzjIF9Rlc3s6o?m1m`jiS@uK#~dNrHE$8-L9`k*v39Z^d~PdLWRVvp%(p3D$l z5Lg9`LwZ&ODshd zI<;pX1lEE0@d050Vs}DL-W}1v(j9BT4vpd2t{jG+poER#@jtUMY>%{! zVlX~gap8CBZt%{l0_x8Hwvjo$%@(X(OQ zhtXLqkA>rf2{D?t!T+=S87=6y(Ker_%zoz^<%LH1`7m2wavSAesWGbORW=&coG-*O zm`{o;l<1>GbLDOdGnnfp@WWvC$tQy;H)jaw;m?F+=aGNrdN+U7;8H{;O{ca(E~KW! zV(It)L*2W_M_FC_{~1Ui0m2iIAR=nih>4KqJMe2=&C^v5b>kX~kyv)ORL0h?r%Yfz1LoQ?X}ll%f%835PCSnq`n|xJpn42DUm}q0|jxb+_?5!oHG^D%U)1# zgzM~Y&}ydvMQ=u(9e>%rN`$DdP+Jh)c8rzPRh9*lLn=jRD&$11$|~zCUFfP%au%oDY2=E`6Wp>j2SNhSYa=+%g~a)lMGxci8HJF>%`AYY=R&4(ML z`1kjtoBm@8_dSG0&Vd++`W)@FE#8HW zs?purO_X>W&z6t3x@!N_#Z?(7=~bv}!N+VwjP(N~bHQteBtpK891YmN*^p;}*WJGv ze>r4K`46B4(H`W6hPf;#Pjg*_^sP??4sh_fsUdZxk4wUZXbHV8|B{P<2ae_B*nz^x zO(ArULg!B}i(G9undHpk^xqyiReIw0w`W2eY8Ez4tDDdfnG9vJBvR*&i?Py~%XmsI zp#Dk!r8dsLF#CT9-I{5E%tfyC2y-gKXe|Iq0J(;irq7n4Qx&m6WfK+B+A zeF~F0Ks(2AuF=_K(eR#0CvtvrUz_Rv^55}DUp5%3x=fjA?H*YhM?wMj;1tGQ6xlV0 zE6LJLou*E2w>4yAD7n-Wl>D}+X^0tBW_|XEczI^C)})9fkYn!&T1560galY`e5$n zYAyes_JjboSW`Yqgc)++YZQT4PJkic?oz>+&(WM;obJTAheHSnTbQn6(aP-?yQjOO ze~5T=)$3*8>6t%dzgzuGx16B0kzk1m%mhz75aJWNLKwF|pSXYz4)W0_uKMMv1(=!# z%lGPxqAWa$y_9{YFyLl-MHp~&FtN4;rK5tf#8WDTYxz2hphG;3vR>^sm z@oey^Ke5mB_$>&~DCJUrqJ5H&SSz-T1ul?E4HFQkRi{t-6)(vjn{Qp}Tu)ipr>{_a zGF7FAG@LIXTPRhC#Ibza_a_(Fb@V6t%0P*hxGAeu-~|$`yDc86qAL%WuYKk#Ws)RP zPSab9O@^Y$w3H0(N`gxX9l zWNTG(GIx{T1YsN+{if_5^*ey)*Y6-w%4w!k|BDZs`kmHE$Y;Pt z&S&G>M)#CAOxaV|4|Y|%Mdl zUq5``s$Bf{83%mw)EA?F>r=D$avizIS}Oe(E=qGk^i{pN&igKvtHF+4y10D8lH==j z@mi)D`5YRlQKF$VCq9Ot%xMHxgvE`DlAAB{VI9bVqU)$NtQG=gEV&0{~rCo>aM zHpbq>ey*)SI3jrL9=l5!S5EP9Q?z~`*?UE>Th=qXG1YFZys}sH^U?mNRg>SUdz-Yq zBS-a2YcF+5>pgLFomIb^B!!XEyd;^gfnzfYVH8IDpHM;dR^4-?DvI>;Qf2TqIi<+t zf1Q{2Mu*Fyck~(^?ianI_h_rNp2Q8Q#zUDIB*nbS zR>~#Sd2sB!Su1-b)pB$zmKH)F+_Q?ReW`)(@7iY39L47c@s^zgW;2$ z^AQkWKrh)$2oI9I1k8$LF?!e@!RTE3S|8F9`Em1?W&Xgp6yBND? zS)0d%O1hZnFEi3rn()Dn?G+6rn}Q`B0kKR4m(H9z7w#g`02qC(dvxKK4lJevVU`3ZxzF*7tOLZoTZLeIqIaHEJlBf<+;sPd@$$o##j4)t`y%h!FF9jS*pLbw#7IK# z=7AJl7`}<$KH;M>e%f>qR1ljB`kfmY6TPG8yvS+R$})dqv!CJiGv3hHV{RK7J-}$U zw{I&N)3w&uYq{TNcd&Y^gT`)-PAp>p1G2x<75OyN-^}36nM*L+uvQy1r{C=r%8**T zHK~aZej2Jf`9kq&@RaDCeM;tr-xJW6JLV*B<)-X}#c zabT?vdA$m}f*oRzft+1okEdV=+TcZ)9FVwyi*q7qH~qtp_H>jp_+wmIX`nEIByg~1S42sgauelStUZ~SX{`KKbMtj?8O|lDFt>2stn(n zmUVT9h0WuRWPk6=^_xr`sCUTcnTkjM>p+!+8nDg;>v*Q+nJ5vuio4pE&-Lk0%_xX; z(TaP2A~p?qe5#160*pfa!-$n10jc00>f3pMU9MUQiijqh^DXBb;o+ZGeznL(`ohRMe00;-93@b&~yVj>4{s%{5<}|pE{Trpgiz{R6 zFuM3YLLtbO{C5r_7SzH-yZ=qe9EE%<{zFr0(NE1dQj1K#s_^uwVdok^>aH$xnzSZe zt|EvzqeU_8Ou@`WYo`_#WW*)4Pb{)xWi*`nbQ3)N9NPgRO`YK@K$VfE3eK?CNsb7h zX7`X=%XRrDl;mthX5bH`=a44zCcVgUZRx)wlZHle;)_AUd4Zb!i>_SWo6>!mT61S8 zX-<2F;U^XgyQV>=o74;glI~4_;;%XUDXDvQE+w=+wrs}(>bDq}{GEk2}=EutTFhHW4mbL4jX( zvb0N$h-0>{^seoPrP$!4Sd~k$-lWJsU;h$*D%r3e{i%ah4w1-pwVQI)!V0*mkMA|x zCngKla+x~8mi;~usOjw029Kg<$FzD$JFmSl!%(MT1Y)Tl*vlQk$;~q=w98y`CMsBy2|vR{Ck z`)NZiRb`n!Wy{Cq!@~yLok5vW*%#~fjnMLp2Gkv8sh|%rM>%h3`j^-)F1Dj9pyt%7 zqXVh|d_VajC$Q0Au}->D<-b-!b$|M<_m!9OeoxTj!V2`~)7O9ChORXwnp!S4VUB%r zP{~MN9Yf>61ER}PxWLeOzCH|7$h3dB||1jGWX)sV)-tI48kk4UpF zsx-_{6pdCaSBuVH5#IQ3CW^^ZHI%BG#R-#A^XcS z5)*wh5@BC4tVtl@)S5MLtSt)vR$7HIN3UjG51ry&s1-nh+Gw@AESg2N-Ju?6f#^p3 zrETfQotuW+v{a`jfo?f5NdEnF_dIoBvS{WJ&^o|q`OF=o=6D3%tf@#A9dkscTyNh= z7j>`C$)b<`czAE*cY4%xI$N*H&@D}tb~uSWdEht%u=ki0$?vP{nOP{l4?snwt{13$ zj~QUXQF4eqZ9c-^f#zp9#Yvy_j*u)_bn6lIJEOsXM^)sys7hus>D4RHbZXSZBLEzN zmC!=R>AQO6YI{$cd(ND%ns53@`Zt{C8lk>}ohW!b^oY?#E2pTU*n!@WqV%IM8$_Hb zD^uY0;rfd1=!{91zNbdydf(NDU)<)q$2Tz>#vnrD)utb0FS=Qw%+WEA({iMIM$ji0w%Cp%G?3@Rb^=LVAGS~JfxMw0 zk}Nt~`MW*X+TWyDXaj<>ZZ0V?U(= zU5LbPSpL1c5%_0H^zPrgn`;3#u91BUZZ3vO*2rB}xUWf-DKZHHH*PS|ve>kqa!LY^ zUwq|*5073|R}k2{gQEq)`rp{4G}YKnVNi_9SgLergAsqMz8a!<43MRZObfH+t?J*L zyi}ZX(M4{*Re;!i8kMhf>nuI$cRLz|``=aXxc9F_H}QuC0#zAx330>4jE%TqDWJ9a zTK4Z?nYjD3mi;465;h6*`E&I!lCi#6&k-TNUMVu8sodR0+%Ls)P z-$J;(%S7G;b949CTK2!l)4J~`ChTUt$65W!ut@K%GW5|_K|Lo{DA~77RFt}`_;<|v z%oFr3d5Lk4nQD2plSUz`XlmL2;W@~KZpz%%vVSKn56^Gee;kE|f$|zX8#C9ook-Eb zNh|IYeGw9g@c7J(mi|0qmi;d&6CpCI5UFY_B+54TUlq@h|acSJKF|!whixWJHE5c%4w!JL?E|+iG9FIdka$Wb&d@pqrCgF z_AiNbW($G}Ncb$>zv-|quv(2V!Nj2k-=Xkv5T4_gV)B_bn&o)d?~T%-6*rbojj9?7 zHr_PC@sr%!B<^~Bfw`{YE;L=~*-J%8Saswci=|C6ivz_?7waX_wZM zuh6rwAUs>oJ_X^Ro?MRg>)Ed$T%+fJg78>92Nr~@VS*5!wU@Ew>U-Ot13r-_tzUT0 z3XfkfH8!yru~4vA12DPVRPYJMDMxWbv(Z{-wJkg9Ly2(Yw20 zU$CxlHo3GIt09-=bUkCw$l;AHNud?LvlZ;5N!q(kT11LHUf6Lz>1mc99 zEB5^aM*7n7YK*G{iJ$U|xfkdJVe$lkNtc;WX&gyG(=7 z@%ATPckZj@T9mgK^7^Ii+j^5}%zALRi%Cs0ite0#c>9KX?R(>`Bj{(YeW|zqm+c!z zmDrhLcjgV)W&;ER_8(58&49V>J9Ov&r}kxUJfeL+ns#{mZc_akzx{9i>-PP@jBQ?* z_OQ;9m6+egBx%XQxvonRk-{$ff8MY8CwADgjYWA`oA z*^q95XS;G6jXZoZ>9rtm;=CsPG`-e?oju%N4VnnA#%g*+?%;AmfXfZ8z&?3Jt)pF+ znl$y&37BNc-On-Cu|@aNfBLKN@6O7Kg777wYnW_4~M8KMSUoX7{jvYyaw7lnq-98gf%Zr4*V{!i8-< z_m*gn4BA0AAsP=QwnM|xdkuv#z0zZTY4Ezwp6iE60%_DcxrM5QAe20%?nh#4nJ`~t zdQqG?dj}n}}nBhcN@qVoH(Mi4dgpqneRVGW% zF_9bO*R1>jvwT9Rc4rLrvf@+8p-ZueqEgajH~A5LCW}g(0wd^rmVWpkwWi8%Fcq%y z@)`fGiK1;p`eQE@a-yB>f(X3MH|nPmd~}um#mP9yWL)B9lxn@?tBIoD6Q3=A8j%A4 zz+{`PF4J*sk)IeJHe^sHpR^MBDjM_OC#b-{^A)GqDpPEgS8TaRQle-fk;adX`Q}nn zU9xvw@B=d8y!{uOT1IS+>R zRanck;m|>pRhODFrY<#OeDpv+8P`&tignR>9*LuvZm3AHSN0!l`6Vs{KSWe zZ?{%%_FGfBmS0l3HL<2+7lO);Lz8sEoak!)skO2mXVjS5so#dlo!yw?LDXO0#`JE( zs~C5vuS=UT3oi&Jo*CP|J7oRWDT98qFx^ss4;M-PV)n>o*o{j(E$OD^`nE5wd)V;^v07vy5!A{LsKoB!SX zmq*XoeLDvM2IzmXffgAXlLzsU_CoUMVP5{?Z24clB!3=x>p{O(Eg!^IZp&@1PDvA8 zx|uHhG?2Qt@_xG8zv`a|I#D07m!4XHcFQ)xy80r&M45%xIqJaVq|HCjgmz}jJ$g@- zFS$@n6Drg!V2#S3JX!M3N}+2n^3#6uW_DjwN{z@ z=p-iNm2VNBM5jo}vK#Qp#jXAIq0}!b-yuX&km`74RIfZ2y3hIUv(bIly3aB0v%-Cr zxz7Ukxf_^N&Nlbi)(M0`BJpLi|PG#1+< zA7pN}9^2@+o!KtuGwkniJF~qk;GM9leAN27>ukC=r|&>N)x(QAo~ z0s=GEXmjZ#aiOPsMOl)r&#zLU$#W*7Km^S&ggor0$crTB^M#Nsq!nDXl!8S)N0U^!Mx;Z|%NB={KdRivTnd1hyLsk~ z?}FH!cs~fFF7ieG=`Ie&ieYA`(avZ;JZlJDxb-wodb@_!j}gU~P$!`j|8Y|7YLf90 zkYZM2hFy9W>F4-!>b1VO9U7vYqd`#B+6tXK~z|Enl@mtKiyT>TWFh?+IFUhsJJ* zeIey}ie^Fn!Tq8X?PdX-t9L9TQ8V|-5Ph2A_^H;(MA0`CX|Bv>yC630WY?bt?6*ZM zG|y7l#d(EUPGSF?r^2={gr=}doWf2cl0wv}`V(=}yQ8JaN4o-@-i8^I8Iw=ofmld5 zQiDfS9u0a4W2~eJJ2mQfQfM7y5Xc%`0n#*G77C9^Ky6G~l&QuZyC6L8AX zP5+@`(ku(1`ONrTqVeMpq7DG&^Zz=5r~HEG1}R%F3?^QXNOG}|s}>DD97hKzB)}_r z-AT$n9ENNs(8a&YOmiqWJSRlFk~>uN!!Rm$iMYDKA>u_J{#*CZbm%=*eg(q5Z27$! zQ+0eF8q3f;qsY85k&l)Nr_0#-VlFe=WoS108)(V<04hayKv%up6kFKSM)i6=>^@hx z!c=sxGW&qnuI>psW0&kFZh<~|GDr$fH~;*#&bm@5zlYw2DsH6ws1m?{kVpH>dE zE%3*UfqZ;@y%`?n-N&y>Y|f0xo6l&LSn=uPgr*Kc{i0W5Q;YEk#!=Un9`xGZ^11wc zEt*8h_Pas}om9cA&emh1O zDJ^rhD0mKk{ZER36Yf&*^26x6|4E0Se;TUZVcjDE9f&;9U77~_mlqrAXB%ZG^@m$u zRpNz?57F;>q20f{3MInmhNvIaaU;I6AE8EXJV+1d&3+vX)T*kW)VJ>0q>3nF07Y!0 z2)DR*C-Y57H~4a8_WG-GWiB@bs4WzLO4kavfWc(g?G`{`-31(8Vy|3@y^ZdRCojPG z*s`-Itigv*&v&7V!Y9u3U}f#qvczcqa{U=>`NCP#+Q}pAi~^FLVkR`v9_Fb(UZXs; zGC}?7?=$liCfQKaf%;69KMC`nEq?hklZ7eOE+;YYE?O_2CI}7lfzf31?OrH`e}O4iw-~jm&#QFmW8-hG%$c5;`2>{ zUh35;5KHY~@hgq2b=ovv^wZ=K{ZzVz*i|hBh0$_nTcU*@i%e)np`1lm5esc$XiXHe?D3Co$vLy zLQuG7ZBz)(8KInJg!>yIQIUNud=Rp9$qQ?H+-429*HE)aYdLU9HkvD?gN97rk<<~Ra2P6@}- z$^C8w2N8vE#bXNEEmO(@>!uXbFyUhO=s<$KFn1OZt(fz}^tCG`TA?owII6W%rCMwH z@;B?%%N~Dgme-eFOC~>J=LGDzy_hi{=6V!}3}9m26#g z`?8`5_iCmTokL>tJ;r>OALj&*^n#BuFCEKDhpANV&r*y@Kf-)dOZrgcRKV2u9M&H+ zF^Mq}d@A&D+R7M}rO$?eP2Y+|btB=*&Ho_^qjHkPuk0{z{&@s0-D{eoe=b zj8r7@8_7?dHFYx)BzuPm)xNFJU%X~fFDi_ca#LL{H7!AY(I73G01hvm$mIK`B zg-!Y-9cMQqX<48kTt#yR71)gwXx^l~ZY}lm$=kN(S>~LG3mumSlJflmvpz?7u{cKo zQbWv4JBCJ>e@Fe3^84^*VBgN#Zi?kt$i77jee}R?D>f9Ej8v}8cLemI)ZEHZ zAzeLF6Qq8O;_u}wroq(gUJa=^hXRQ~Xj&E{VX5K&Y+vfOuGpb|O~Yd^Rm9dk6kFHt zX%c6xse5CGENhwIPuh>oySDwk!rJ1!M&4Ju z{0`mW+SUxu$SjbH@(K2zz(3j-+jauYz5=&pJ13)uz12~WC1`f9d|iI*Q(8-nD6p4O5w7ll>k_@CW}`RTc+hmg zY<0mmrEfgDcU|ggQ08-?%!?JVwGYMC_VYiXMuIYL6G1coi!xJ9ZdZ97;da%hrmOBF zh1U_it)*8Aoc5iCb;WPH9nsWFcLqN*AgQZ5BxOqZ`*2i;?OsEY1Wh47!6FyeyF1+= zy1{dx(I&kvah(VAjd8LHl+g;+VSSwY}{H zfJ49b>e$w&uH^L$w=w*^JGKp|E9pY>H+&01wql`WLQErLw9Q%yAE`ISgw>C|yJn_t zU2tOqW$K-JsqO8LZSU*v*sd`eps}nkdD$P^#!$UpUxIhpeVR3Rf@+_nmxyKGqe9z! z<}-X}J-V^Cu`Gl8y5{7V+D{cdi6|%iSf@ydbC!rdZ3X?p3DPPFdHueEzH5S@#0%Nf z5%|+|vg22;}ooWo5Zv z&S!dIhrrGw#=J^NB3a^G!K~tR!@Yu8&uiWl%#l>-k_0CG{yz*#bIpE_w(D z49|UDM|!}3ZAvJ2K7A@D4~X({N-oz(*DS4?it3KoTGv=?XGeN)W#0k2y}Sdwy!i!< z%oTL1Urr(*_f-EFHgc=!EZhvq7k5(|YipU7i^_BdniLY1R^_W4$eMSm{LtJ91@@*^ zdM00fVa7t^hlqvpL&?SpE=3H+vtUEbb5^XB{*-I0F4dicPt`MZM>dpP$h}kywJ$CU zCjO=kZ(~FCK{3yPQ1XT`A>4l|u-0#^FPl5t!RoCFnox`5$w>`~zjgCp^3OP|!TR~D zP4z(^h0PZTr_M|bIkll?W7BqfIlY#@-y;18rGLBmm{1}^QJK56fynU>Y|w6LNL2#C z{EEQ3+A+Y4(bEx>MvKm;uuyNz5p<`gyt!pr71(sL0iZFLt-_buao>_eubb4G$eKaMhJ;WRpj{0nTni1Sc7j%DA8C!75MuMbKjVF zdgy2sxKw^9WiIW_P-4!QhQ!}<5mQ8?6M+i&h!aCTbfX$8C_I7^pVP;o#5FLpv&$US z#)Nbr=N!J9X=5)SZ;p$f79D}^J!S$>AKjR~&V=C)w4r7beYlC(|8kNmcAAORgob~E z!!_E+^xb_|wh@%JMth2!Udar~V4S)~|8W z$mI#ICf@e2yUBuA^Ubm5R~t%VuMB%HaHC_=;qU4ACL6}D<2mh@iOAx*PELUx2c|iE zmRzhV$kiLqHg)>jQ6a-ik$0Vfe%Ip6`dS^3pp=q7`KjNbkKd;&{i|3$ppPg>2{8AM z-h`j*5<^%^Pd-XQy#tB@crzrq!qA^o`P~|lRB7B4S4we6g3}u)QFJGust=Xc}fp z?Uh$*(}nh6$bbpoMQY`BEUgD$-l2Oe{Tf<#L`K>hh|}8$aqzTu2Its4s*+kCg07k` zK$D;~{ROomXw|(COl%C*Y-m2Mo8HYzRhBi>yk*6%q)dokC8VSB=*WETLoxHv`AFD3 z=xIQ7^CgXRb^}FO$gf3Ehxi(5wpcMAg}`f74xDygt?1)t!s3oD!YrTfGERUqz!e!C;0eL`!a3 zZI~~rbb3+)4jFSs)751OB`~;$twsB%8Xn4PeKRtsKE63}m;C^J5&0bf;g2ETBYXh! zob2LXU7vUk*7F2iK=k=y@0s1iqI00mAz!bK_xiw%PWG3468(I4(f%+90aAN7ehGD&%K=%d!s;3RTDE*sMFrxlE+|cgEjT#%oU-; zl*8yz<`9(meeMjXEC0C4CFCEO06b}LNk8a>;mNh;IZzQ-1Vw2RyCofUqO`!tBkSp` z1(~73w!HNloAWr+D+3dn|B3JS)pzd>CZ5x+`!^eEUe@9&9CG?$j{1QffHA`JpsrdT zX&&TxoT#!Xtgx0|i)yMp^FMkJza!}tL1Ox=q8y&>zo!a9>&TIK+!WSdKrt z(@&W&pkMe5uB$fGtdDT!+acQ@*zOo_>yU53iuBF*L;hiU6?l?;G=a{N%eU29tTa9P zv%&Y0p?FKmf;C&MrC(=58Lau(@!H7HoN+Nb4@2BJ23x@%lsB8lj&<7y65E>&;1w3ayUM;e4s56GHYY+^9slehGC&2 z0hPo?C3Ex&qrbF^5l&BuiLJ0&|5>8Ni&ZFaKFbW=EY_gRp)l#keXN(%bf3wNi``&i zD-@z|B;C4RTimCFJ`?ir0k3jw(`D70+p8metF7;><(>6En0=;4PHHbO;tWxok!*)K zG}ym&(PU`NB_ok#Kx1}5V>bGu`*t_ghysmtWf&bhM1D#(m2|kI2AH3oL)1{0 zScA5ZBP1DYolxKkunzRGNKctMKKm0oBrGFkAi?JN=EWnp0`BE$ekt=-kNNCRP?nKd z%`q~o=z*<^Rx~7DB7eY@SVU^HixmZWsZWF-ehI{>A-1ek2KPsv@hVtkehD$CG+JcJKJSVja2#By7G{CDSdKO zGikqO$mTvyXEqOp@ybl<**@zrdh_E+^VqRRPVzeY>nvVE3SHw*-9?=_{y5^M zj5PZ0sh}@*0B|}PZ4Oj%WYgeVA4+V99XQj9|EGrnk8(KFka(6+ECCBP#W&x+wtJ)< z>7+(_1__Q3Og1%0e%L+COlQsX&3VIo8O4WE!9qdOx`+huU)x!H*ivVvS*_ou95W|dcn8IoZm6;PC z@+K9V+CX+=<|IIy3fnw}TTWK|6gX}I$XiBUlL$|WsRo?I7aB^(!9e$X#CC<_S(`!N*w+k)gL!IwqOt{T=?|m#o&+WB`vE*+k#} zsDtIdR~cFvb?o~PxD#&=!Q9kZ@nOti`@0M(stgvR^B)&ZKwIEq1fy2Gg)Vi2TTJj2 zg2T7EL0>mP7fmDRDmUl~6BN3HAXpSrUcCvLuAp<=ps`LWm35LEbevO`f-Hj-@h6yQ z_Gf$YXIo+oD^hyw9h#M*`0=?MbsHTA-8s;KOFd%xZIdT%T?8XiFLKj|&$<#UChTrn z3~??*c8};@;X5XmtSQ-;;MfgmFm+?k;@{A=d-Kh@R#(yi@1q3g6Ocdce=&n; z|Lfb;kCDrrm7q6P1(^)YwX20A+2=*SchkEa+Xs|5rF;gaXI2@{Mj3aIFaD{<-ijZ~ z4$JOCbD;_2==Oq4pEe(ZI8Ndq&I`mb_SlRdRrv;&b6~cAz{5Gxef76yvvGTA#-O*+?s;QzCUJBx{ufX!skl3F7nHOCXba%I20T_MQk&c;YS!|uX zJYE?ED(bpAS5m5U@H8XKxyn486b^7V{=uzR@QTh=7&{U>OucscG_T(8_Kaq66IlJ- z=+d7Noqp<%-3{G8Jy)EX7*zWG={HRZVEgvr#jRIyPkPb6BN{$FRdkk@F2A`-`rW*` ze%Z4wqrGOQzhP3C8~GGe)3YG1+Cgj67v`0+gi<(;GQ;#e`pI;LS1m)a3lvNb_aHp6 zyFBo!z~P{_7|k&%0w{nyw(!o4qCE=p`RAN>{MgXbeKeFkmiNP z9Nb9|0I9ssH+D`1&>W_dF(;}Jj@jD-3Fo{NyuA;S5jadQ?lk)>Cl1Q69Xh=cM#O_Oezbth@qbei_y0oO z#&$@&bn6H@8t;b5A(aiLJD4%dNqRJYPTJo`d`oYL@n5LD+MIxIpIOljtD=sJQs#_Q z;V-Go414X2)TmzsTAo#1a3O)cuPZ%Nn%6G929(w8>nc{sVXwlf{7(l+|3s7@|6hmm z8+h8<_3%LbbGDFU#%_4LlJHRVr>l5iO@HbdZS4awtd_*~4fn5BuAoj+Q;iQ{Bdci$ zFI~|CCDyWmy(u-?zKbnJ0BU5dMAo-{(U~FN25af3K+u3z3IMGSm81i#N>-dr7GSN{ z4d~B;iOu#e`Su%*CRp9>e@dXTpG}9Vcl&kCM4pkcIrcgH%F8UJpASbSv{jqh#n_Rd ze5|CpFqL^AeT(42U2J*S$%MF4x_6ruy`He3uftj@Y73yqaja#RGfZy7w*+I)R$}dn z8`oHtv0CmR%07#YedFDNJ~V40qj-CM@R=j{YT{+C$GUgNEy=5LG6sY`6DtL}OP=eLO7!?&xasHDQX zQjSdDbk*)mb>4m>=o})NJl0a!$pU+B4%XcP>yKapy5O=V7F8c6FKIoPxTKYaudhq& zsM<)!#CG%!_|_o5KOF>uXALABbPM_Rg{r$4_1;ZYIevPIRTlq+SjZ{Xp!hF1+cezt zL9x0uUAJwYlK9d6LP>X6bW4H0?<>BKo(WsLz^v`n83KFw0Vq6--K;OaG`QzVX5yho zm@6Bmy`Le|2ZxZj1zPq?_|<%DW}3;!U>p|JbVe{?EU@L~qiWv!o}+S|)O=3y6MKaQtnb7digsf&APF*@FC68vms%xx3S+b6TUjctWu{ z6)2V>UH=|H(zGfOpYTaB>>j?WCS$gx8V$95Ww)K+Na|`{j8tM_5a(S+e(pst+73O- zv+9H+%tHYm7HA!Hkj(Jh{xGo#19e<2+Z-y{h-cdH1{NexRx-tLRN@5s~}Nq$AIZabV>f375qZR>xxE3o2ML0Pl}c~w|TZ`Eos(OHCcum~Ms zgU}t@sMzC)&D$E5qBY(2g(H4y_=uQfNoI8W?zVQK{O^3EV;>r(T& zbVO|I^hHr4dNnogq3Gv*nqI7pX6HqYN0Qu7y$PZ6ZR3p08O@sJp`4Jgha8kSajm}? z%?}|>L8d-3m;V}v7NbRk(L%HuIg!M^G8zb>B^Coh4Ze;B4p{>0sGUEK zmKTq0e;Q(ux4tX=T$4T=oQkeMKQzH;QNO0j)Ey7;GQ7Doy5={TAs&9E?pSR?tDPs63Vh&YxY} zT!E@1lIJpGH(_>JDzG}be|YmToXN?2Ny&OgGfK$Q$7}p}b zxV#R_;qzu^#HY|ZuQwkbO!gA8MIu8G1vDh4l;Q1=h^8|8K8^eyoe0O`yec7J6{H&1 zMi1<13cJY*yTY`$y&>6eHS*pb`0;vk75zEFm%7;GIM&S(*!%v%bEBPDhkse4{#vG5 zUZ-Dg9u!O>Ynj+ac!N%4B~07ki&q%L~^f(<{v zI;J&P-CtOWDCJE8QPAkc0a>VeO>KM+$H^F?Po1+L)oC^&WtY-whv zM(^yEo!5|9AF(l4Sqyj~-}>;B08@3eDSXMf#u#cS!4-O@SgPn(6p7tRO`%~_TVRKv zI-uSJpt4$H2E6w0bWQeBO7G`eefON;-c8H^*%NBuRS1n}*Y|oT@irzwjkM?>Tiifm zECq9(as?+IvxnLLAPnF$uTX0hG)=28+=Dst8}>6p3{pjtyCaaRY)WT;>O_-4WRO{qaY=S}1%n{X3Toan$*mcB^wsmt{A@aC$7)^uA%7S}$ zT2a>G0&gDwGP6Xs{|%526HXHYG}qa!#-0hFfijD23p|vvGtI-Zoclw~({U1zBup#O|)ZaEn#e$10my*6nyjjZ4gAH~C3=Jjh~IF@RPTt2pMetwA%(GAPEH>hX<@ z|JaFCT?QEGEn%1v<1ivJ5OS~%fo?&;a+!!{T!5<6%XTc;?ozg6l^o49qimBB#YvG9*kwF^l9G)l*;87?l~8+1qQl#{I%m!VwcBLBkl2;J?{)4w zu|0v-kJ0X6oY{M2PRXN(oYJD||4I6tS<1AZOj~X-lzRf_xmD5dR!JbwI$ zL-pR~i%9q@CDbfa!Z*HQ8dMrshrmUaZHqZOLhsPwaE;C#Sw3Sa_R7wSvL7Tjhxo&r zhx=peuBqdM31&LP5AyxhfRI?1`7_y9=4DS`@6`C9&ZDZ7x=N`Bp?^l|*8J(3*WL=V zh?W?%_y{0bn@CrVM_jbN~T=$T9P9MP>%k}QNx+pB4Cl81eZw*YXE z*O!b#g{u~6A4O_5RH;do#CESA>Y>2-(~6t>(M9!E{10kuEaPiB-Yc=(Typ^t(_Ks( z0k>3XXx@tB3}P&jZ+31s{e|1Ax?;$=(BoRC9DSCWj^-ueXiFx}3tv;0n$v~6v|rOH zj^wPltWey3-h4_m$`XEasBotr3-{R$4ObwsFSvKd!U@=nKy=I2dR_A)nbZF4Gq-4A z1kA9#X}?CDUJh)>l^|=gTF<3Vy_RT!etw*b+38-i#u>bys6EcQzIGbO{iZFN;N`-2 zS?RON#gG)FpLb^WtpPj&Aw;>xI9EBYi+D$#Ahs%S{>n9xk@@P!o1_~NM%Nz%=G`WF9Y};0UAH{&FZ_W5cG8qWe*M4?)mZz)n*V~nBCj@GG+7=!iE1_c69OoX0HpcA?i!;AJLBxW-775e=`2J_)l^d z|0S_E_&zQf~lZ2I{mBC=; zxnuyF-WE39fgu1;Ca;nC2;*sESF!yS0$9}XcX!p7& zkeo&T%<}qYsyDx<=XH=e9z5f|6dwP-f@g>W4_f~F)5S0kbdLwklbQcDG!B2^ckO?$k+~sn(Om>8 z`i=NX;$Eaf+<^(DPWfWAHmGOBd7$UwsMF@HKkk0&YS!w3D5RL>dlV%dzA&AsFqCgj z^Jc(_E;8Eb3D>JVR_jjs(^-owT@TIY0Ib+f0$Adjt=2ab)y)Ys4>44bx#n^JHu4?z zS`Ixotiml63{4nPqW#qpbGa1*Sxu+%_7I9@!<$RA<1LrI6G5vLWW~mli5(WlH}1?2 z?tRaSo=7N*7)Lr?%|AExx^i^(T%xexz`aTRFu#Lma)Nx-0@Jwo-=P+EIWajp!e;(u zCB&(N72m*{>Suh#D@8t(sFzVF2!F*Y(@wWcJKbtd6l5T$Hjum;-tbN7Ad`Me`fEEJ zO8qd!xc$0aN~VARn$xuoPy7j}{2=yZ>Fjs|@MOX(xIR>g((tqj+;8Kfmx$AdFq}Ls zxb+NL@E=YY@j=Ql#iZ$@G~zEwbDq*f+%zAeOp(d49wUf8mS|_gH`}BM_ceW#=}8)O z6n3~4w96S}w&yd9nosN>T0U5z+GTgz;TV4aLzkR3EZd%#Hf)j+B-}x(JO$A^QfGKnx z!)3M#PCImq?IaII2}@?3>McZnxYog!%cwp-g{>4q>vYmhG0p)weJqPUG|_53nE+c` z3@u`p0&yVGxu+AQZnL5rI3{<)@tG3FE}%vKsowKi+F*MvZ5^ru2$Mp`(K>H3TM5%4 zm#KI&J#gow{2du)$dS{;JydP|ch$xQFc9dE!hsdPfN!^XR(z}?Q>8OTdY$mdSDj9n zZE{`4L_-Cwze$BAQ+of~%;bFrrfC%|JEg*pX$^kOFkH_IrB$9rX__JSGy;&u8J5~m zqvy%$Q6tAXVjUtM!&aZn8x#qtPmw6nAU>f+lK1>OnG7{T;A5C-IBF}}La4MM9BS0e zmvaclhW7@i?{=9<>f+G}^sd)!MgpAIW%pJ_Nh;#9FpzZHe6$K=Xcnf6XtRq!=bKt) z(klqRG}HF@#}#76&$PRIUbW6Ic`rzRf+`lv6#H0;qm&!clVc|2c$jQL%Exu5eb%J4 z;=d%P(EnAQbZ1yI$gZL*%?z@x$<3fgNzjqu-izU{mS0_LuDayLR0qjqU8k(P7Nq|+ zUz<;(V4X+utkw>WUA>AHDz(Ne{VP(t%{23nB^q(j_I z5L8HHo|(Rtib$3IMn##PeUPFwq|zZ)fx6J>P=x(ZGpE$?NheJOXj(vOBo}( zop)3Gvrb?zSNue`_;(fI&AW$8D$$zM7H3^wONdu;tK>}fw+LZjH2yGh>tOgI5_yYW zb3Oc0C~|T>uQb`=l_q$+5~l^5=`a#r$X?djiW@Z0_Ty^%R?8rs^U*;tnsaMyA4il)4$Q)2(Ix)U<~t9&_6uXSQ zw-)b#$_-5}NbkPNLBo%onNM!`z2B8Ofm;Z4vtj+353>F_H?1EftNqLTB#$^rTD>H6 zrEA0VD-s#nF>-ids1au?p&6MQiE$zRnhNRO0^1jN*I-EdKxHzdeOz}Yd71CdF2M^ z0k@uLy0g)0Epie*eG&<^p4bHhwg9d4&|e6EPU&v78owZ>ekXZWC^!MRkA zk;?w96Z&X{+l|7OpD1E!e%>=#&&gY_R0i9><{W`Hk9Utlsv{Gj1QVZ+jk7tum`rUyoPIBCq#MRdhKeLnoQ^V#35!M$07^Tqkz z9a68L2Zj9x(oL6p1#RkPn=<*rr5^Or?6TIYQ@VFqUl$shgHCXUL;0gYmrHSJ;h+j& z5!h6cnSi8-SV`?Kl+?Z!@;QwQoL$XVu>Sa_MlSN!AIG*F;+gA?MYg!GHVz?{m>vTT zF8d+7;^Wi?v#^)a28Zfft&O6PTx_0fxW(LTI}bcHx`75cUo(Tp-a)pe<68tj`v&fX zw7$qY^+moPNODAvh`xfFHff?4lSdZaAHJ-+GI?&%HJTfUD-aK`P?u&FORaBl2-`DJ zf@OO~td{;1wt}a^e!x@19T1~cp#Rd)eVFG0*Mbf1Kn;6x<}<+VZ2Lp9cvK}G1qNES z?|jecF0kS3vCjPU%pLiBZ2TDDGj!xk0g8}U$Sulhmk|(svhp{))9TTDt&N*6AEA#Z z)Mz5Ax`mOF0N3K<{ZvNvmOyVBr=GEph^a&FyHv9&a;-Ezl~d5n*S_lpi6<6YWzKCO ztIW|6w5l;@YgJ>fr27<~ZR|B{`j%<#Qt}Ca+9FUH4AbYMOcmk2Z9aP;Vfk2amC^xO zLAo!AJS>=@A$5fLS8+P>_YsJx-prFv^_1t|WX?wNer#R^9vy9YW<6l{&y5^^JZd zMsKj+N|_jDzv>uFA0-ZE2BKi@j8^MKhWosQWDXHuhLv^Q6jP3ZFlP0CU%84mp+&oS z!fFS7F9fQMrP~Vb(MBd^+T6m5C=4TU*ZBCJPor;vot6!kNJ*%M3$5>I!&LoYs5jLa z#{&^Y!SpqvF5R{5M|(6nTSSS)xLra5%s!aw4ExfVi-brANfEz*2>Z_@6D`!rbl-5V zQ=TQ2%ROS6!P`Tk5^`kMqPJ6eYq`;aT&?`4)57#Cx49>`o_sf8I7vrEXE!PGRCKJ^ zRsy7^GeyL3HpK8Ujxf=~*+DprLm5YyqEo2wI7gW6wq%LQ5wu!=rWofe3FKshwx3l~ z9k3)1XVkj-p+HAiLHhmKP8WSe!<+0Qx=at;?3{Hy!T9FTkW<5AP7USL(ny|jqPuc4 zBP9v{p<7s)3S)MB8?UXZUL?)M_O=WZLZDp@Xo+>T18>)3p~A}KV+`zp;LsK;|y1QMeO)(w>j!7 zH~uU26}3sHj7KO&*fm0|yk)3Sv%X9nd{3h~I9y!&STB1JsaWqEB&uD0cQK~gzc3SK zS_M5X+}pwEoUF_u$myWT9O=wF=gs~XN$v_cyZ0wXO9J`)OX(kg!e~WI zkTqN=tJPfgiQ&_R zB@*uMK>8=Idh44N*MjtAGP^+Xa%X?-H}iUbI`N!?a2;e2Or}ch)6HUlKZ*3-nFinE z7J;^eCDb3F-pKM?`lW<23M+GSq?0@-WPHQ4@On30_-fJ|9PG`bhfKNQU?%9UwbLag zKT6$kItd$9n1(bnNI^#ap&)}I*OJ$$vOwh5iFYYjKCjr-4(Vy_gH)NcJN)P`nQ`Z= zJSW<|TjFV>@h4@7^%gf;w22sjrB8>ks!Lur%%A19Gmn-7&K@*Ih3J%HF%Vbfu>%vV zWzUi;lsc{%8aC_NA>YG{mOqQNs`bs|#FO0`Im6@0Jd_tRKJzHAFTU46d!%k+wGILx zW)0l@Kq#jhcu?G!5!deK4W`si^UN>nM2M&}1EzPE^{lexRwSSOXTIZzTf2aE?1y%x zI1wgjE1Eo+2L$a1LHjj1WpeaA6nj1WYlj(pHiIsj+kYte*bOr?}c8l}*8QB2D=TG}b25^IsCS$}UNQ-qcnDd-a01b#p|g3l1jsrCxe!9TW0# zI;OzBNJ+f1-|EUQ`z4hl`!VT4l?~G1?nho4D+|633ILH!j+Ym*%ScuYdrHoGXg*D2-xzMyl;AnBHD`aarLqw=WQg8J}DB z?c{TJ;3l9mulKYj{BeNSd$UMsa3r!xm9z<;j0WEtj^tR}k-X=6q>T?UznBAWFq!T9 z@{y@%KUl5D<(D>7u{fGj#k8To)?u=R2&x5g7j&G9F7Q>@;SU)pIP?keZ3@W8DYhOGjgUnx5x;eqQ9O%7)23 z7Q|&|Gs>DY{k1l5h2do3a$>(s5d3HZpo${hL+OF!q6(RGhR`Dn_(&lhoenn}R0F%> z|3y-I=WTeTqz#*5xR~Y%(UE&D?3AKrQE+ z#QsdN>Ov`Mj`2#4%yFPs;IRaPmDBc28&?>)Alhkk!snny_g6;*-O+p@@=$G3e#3Ae z1VtWNdMg7e(Wna8Qt!eW={5F4F8oQ3EBjIALP8PfWv)V`kNT#2*I{X~+3WNdWTyjJ z+P*1IOV!a=Gdv2y4=mp~$M4b~gK=Ygr@P}j;)wCp@}u!R+Zo?k|Lyo%t=p(OZ;W>z zHpbid_U~EC;{2GpFZSLcEFqpPc}%VG#p2jPL1KgWOrwOPLj5cQ7e#SLh z=?*u2GD+6dBR2$+OC%Dq;(t^YPwlw9mY#I9lmEkn|BrR)2xo>$H^nZ>m9&VGU_LMN z*iMm&Py2fqR#oTL6FJ9a9oJ4TF32F}bhMNtAox(J=>o{@GmD+^L@58!R7jDdft(8j zH3TQ^zD0Y5F{Y(f{Lkc#?K>6o{+^2R_Q?j*Af9ieANZ*UbeBC%Qy+G3O?vY0j6QW3 zvCjlarfw1HjL96&_I(_?^YlX}nchN;0q0DH$jjy#`}{G{@S9SkJ`Y9e^P7K?Q=~o* zMe4p%q#l!5hi3Hqy=hcG085wO=wM^fb^Sa9ZMxMB>geSL(G8`ALe|oA%>!5*jJ^Km z9LDz8Pqlm?F-1sjVP6&U>ZWNQg&<<2KSc~Cq&KpEab$#Chd{3AoYh zi1rZFEzDZ?Q>|=2SI7dw!=y{k`870$O!`o!M|g^l3}0e@lOdC=#Y8b06X;lMNu*op zSucx8`o315VdfycM-hW;9XcbZFnp;NSMFP(Jrj(z_X!`zOQ^bi(NWOBKC71u-!gA6SdrL>-5cU=@WtLW2HSp0;>KPb?_$hMfqBGzkvTqkw@euQ%K1Lz znDELJ1JV;(lNq*IEQq?14_ye>tPPhT8KPAzqqpz2|D7a8w*4Jm=;mT$ers``hSYpt z<_65pY?E0c$G*JGUuY;AjXfd82P<1xp>LW%Vwucmh_=ZqK(|G`#Kue|k&bEmuEZL- zIotDuI0*YXjYDdFZ|tj;tce{!iX=-3uDOiX+jv*MHyz8Vk9u$(61Q+Ldcj3j>kDMZ z!DyyTLlQaJ3;+?4W2}|ad=u%4Ap59LYLPFvZXK0mQ87rJ@~uPT871!U?a?*9i%8l_ zNoPArdyy0#1fJ#P!qud1Fsa))tvxB|+e!{kA23+6&Wc9?fIjTw^x+3yu^X6H32YBc z=i1x=QU_W+)UE_X2OoOuZP z9W=U#3cw^QK7jEALVG-rYLR00--#|CWGFz9vKil~rvl8X#dE$15Me^RmSq<#{`Wox zKpR$!^-32|yVjr5-^Q8eC6&{0A&60ey2^S#9tgPp%7)V)Dp{ke|A9cqj^aSc8qQ*@ z*mBC2s10g|EH{{w)`uJL`k zj(e94)g9J72YGkcx%+g|X}?PqWHxWnth_>A>$ zYs93to=PqR39TpaY^ZsjEe0>lol%@}tb7H-cR%(gkh<*DtiyhZUu2PKH;E*dR5I`0 zbxh0bs*QfJyXiaxoGxo`V?Zm8qs zG>eu0<^$t3hbu9BD8}-_)Q|!GN6&0X?5t;$5)UwnhF;bs?5NED*fjHE(@Gk&by1K8 zUFfuOJFVPgS{WkE&Ansq_U(9gux$F!0sfK~{3Rdyy{lz^XJds?kV1c|VQXyvG0pzW z0zS3csizVjdg0ZXnS}T5cy~aF?N7Ym1rN@Q=dvZWcnMKKPS~;STVoxoWBZ3U9Yeyk zvHc@&J2m+D5?XLK|FPb^vH9pAMrY#lsGZEG)56;yvrnR@{IO?S{IM?%HbdezK!q;b zKfb^|SINe1z$TM@I!5~)%lDgZv=hQ{>~iH8DRZntN2g1_<}z8o@6N*Dkoyx| zi2mq0H@f^_u0%y=Fauw-$;-m%wDJyDbtZ!pN;#a6bHDldYupktpSvYcG)qJfrgMc? z`a@nxs`Cyn)E0?_CRMm=sRPngUi3{AnE8YBq2_Dr3CYB#(`U5bIZr($Pu5(fBgrxy zP7b;n-tDpq-5=%}G4{FE^>LajP5${;F?>q+QS)^Sp;;sCU&f&^k0 z1kz#-o};|?rct9zD_n3n1z$n91FTv`Yaby%hv#j%2)A3_d6S0Uw9Q66>&xJOY3!HmmI@$o;2X)e>tEsg!{9UU_c!tV1^=-<|-y#t~hDqVJX&mpK|XSfIvq zbWX0DyyF(fz5@Im4k})f-cDmMc6)I__{5;>jPN}ym@ILqW)N)n&MEJhh4uo>>L9^6 z%UW4<$>$fi8*$=iy79*c)=igsQh_v-*}L;+K+W_wj{qzt0}hi3zX^y{{||R>0^U^B z{R=mxg%(;*8G=k|k&3M{v@*3aHPAu=siH3+Dri-#D4^ITfXGm2(Z&!(#px9l=LrQx zp-j>;l$Nm!B9l-CH6aWI6bcBrzqR%`CnsqV;QxHzz0bYA&r6e&efC~^&1>zo_XdbE zM8pqZg2+Hj5GU(vEfXB4XUqg|@a%?&1Pv88qMtFOB{IWcF>yL?8Lr`w3O$6LBFgTY z=?ZV$x4s3lc=e(@3&f+&q6D6$RQNaA;tqHCLad={oS)Ub9Tf1y z-g=At9*x5+gXvI~wBM{}h~Dr^I=Rhe+mvdv&FU=6^yui`1StF(=c8Q#h282j+ox1h zy9REY%>=}NH(Hu)z09`pQ6M6aG_;xfZh<+p`a|?J1q_Z?ZPwjJ+mtHw3p`|1Iw{d> zq-#y+kO`5S6Z^7;$vbIBP_E3a<0My8U{9nBA{cwlDL@r&#v;;D_VAve#4+0at>hWU zX^@OP3C|45pW+F#G!|@vyXvcr_90H^{cXgJi(;#s;Zbq%qUP0!M4xdAeXwuNY=0ir zr_ZBM>YVi%qwPFxfGxZUuz1CWc6#e+m!2)N9BZ4aN*wyJbPNkd^Z&x|rZGF_k{G{x2B;v{OLm>KN!$f8^^8iZD#r2(7vWpVEItQS) z*(BuZbX4Vo58}L`c-dQ^!oi7V$m5lB8m&?jPdLTdHYL_3Djpa8ho;7RshDnjI9fy< z$S1Z^G5+E);2P(*Z~@iR)^MK=@A<35pUG4vFq}9H+shyqS!~=W0)z@qC+?yT z9E`G-p>{@kL`!bqHM+A9$7!`~Bd*XHwPuKzkgx7B@_k1}`~6W+smk@?^(gwN1M?7( zSC6ixDsgu-799Q;)#|DIRn&i&>O5G9|5xGv)uuYlDN%%jq|>oG%X*ZIdOHNT5hh0y zsHN3WxYa%a9ckrtK%G|McnJ&VrPi~?f@#gdU^WUSMup+xJft7ua2yos1Sj4dUy6kv z9nRF>XXzjnkrDwFCjO&RVUIKS7NPr_$|Tt9OunB;zyd`_on;cEJ0XYFcpJFUSCNzK z$f_byY|@-v4fqzg;}yk_Qe0*gJWj7_BDECRL2-ORitTWB;ajvsCuT>cXIUq7>U6L| za_++UzI3H(ItWMlNFbec5$PT>ToPoyN@l_JH+xyo|Nd8Rf|PdE6*1)V6Y}Y=Y&qCY zY%$t~K;dTYCjDY`45@UUL5dg3dm*VL19U|(G);M!1(w}oxkoDc0t^BacKKUH;RR<$ zz(K|YjGQ84@uKtCAi^ScFsHzQr;EEt>7#mD=x$ek^dq;$Ww@{+0E?Va_!pOqP%h(} z0U{^P1Vy>-!FzF2GToVLpHkxvM^TPWsHNRbx2G*mkUfa^YnTE_HAtX_PiRW-D&fRM z=STcLHG!eZ=oP*)XMIGkQ>%;x>!EO`)PQD{Qp3!7M#l)KSnE7@^PJg1nnEPWer)MQ zIC>H|I%;{=Y#&<;OII!fU`})9VcR%O>LSh_cHYW^TN!xxPq2Q6>2V4mH|tK(__UAy z3oZCFWY9$?&Z>K8`crCLPmyl4XVN^tlgw;Rnc1eVB@&Y=k_&}LtZ^2hb`V;U<7KaY z6T5`TkpN$PlTR484}qB$tOcx*25^pPVUD7(crfyk3N%2F zl-mi+5FsvNzs*BguTr{)y(-QaU5WEgvE{@)hcWNPy89Nz4GDn0_B2D@HZF?g$kI4# z5Vh8(hgZha0}q;>k@g+9k72V6)o!Cb~4~ z&QZP`e!JS6clp{pAQ2jHLY%u?=mb(H&Zpp)isozZ9h=cEL>E(#gb=Y5m*+~x^Lxy# zamPa`04$Bmz0;`MmfO}yzAF8fZ%jgTv28*VoKsBal_AW!jVl5A z<-gg8w*5y0=-q^~-yf=0CIODopa@1iAJ2WotGnovh>xE~mxkhw7~FNKsZaba*XxbS zK;)WWaHL-;sA(e=(3TkFuEaU0q%sqv#kzu;J1uPrYT8>RzEB=V7^0r+Ec(Pn!*Szp zbdO8f?mCLEsA{l0gd!GtJmFz9i_RN@gJ^M0vGme^srhoKci@i>EWnD-f)eN*4>J1O zM3oD6tTl8@;8~B*d7GIy&)K%x6iw%AgJN6?iL9EkKaj@Xjqy8+@mCj=RRZd~ zM!37~1{$Y2?{^;8y)tDxen3{9S2U)tCav%OiZW<8nkoZ11xMr{TFJ#{IJS|k&IzUn z=-5(ow9`7a`j+$p0_#*~nn~pr@Pq6l;q(>i`K(b|QGyTcICV#lQZd+ixJL9jou0N6 zT{|MD_ZLqGp~dfDNO~?VY9VDvPW43m#h}y)ej7!PXcGkV)qr?-&xw>{8s@CHL8PR} zkmGz>NYF45J~;0+v6I;w18kB9NTg1bEYdVc1NH1pAkao^`%vyU(K!wsBM}z85XG}1 zZBnovnt~3b5D#1@jXumz^1-0>Ni^Ei;fU$27}ijXeh?{Ek^C@x-uq5l*=pe0)`>>a zLb>lWXMNq_$*wyLrQd(1}I9no9oxDP4Ur#Wm8PBK^fni>RO9t*olygkunlG@aJw*Y!^yh zO$rXt4JGdaUAWRxS7c5|p~rD}EPua?zQ=gKccSl6-tV31dxZCU7uyB?5}_-~Na$Ly zRVS_7T5!5msVf{B?g|uOgS_;zjF{vX0ZL4V;Z|C{>zX6q&e{RDvliV`zpP(_`tHUw z-P?`p`w?FN@P75f&;_3_iUNw8kv0+q6cKCzINnRGHAfs*X()9z!4)Pn%^%KUWtGmX z%>ZmE;ZRLEKVMkto+ytCbS(?`#Ul+RS>w^##5d9RrZLJ5*y#+Ga_z+)gjC|17tsRe9RWpH^W#funI@IV;9T zx$mWq)bhE=In~|5Ow01+|GeX!m7a^Kj|SUvq@9&H(!mWm(ztCWb0qh+9FsJ4N7l?8 z*rNrbNFDA#P-|&L=F9s&fs4H^xEX`)U&Qn|4JrF8Q8;P4!h{>WC>ln7bWjxC#!2b8 zs5R6SK*K>W#;MJ{`^!z9a%W`%=FQG(yfPIm`D7OLM5>q64VY{# zR15yuWwX#rytRj8X;Oc0N8YET2|8Y1wn7m#An2D+oCqc%0iG(>lyTK$K-fxE;^^M{9SfCHNZ_7~kP?H^JSW{MXk7rOb=}oAe~#nM3PYMLPO}KJY%~nPvN%u=X)Xi|X{5Z{aU)VjO>?$##-= zSmAxM?Vqf)E7Hri({C_NNlwJxNJP>7rgYJ0A(c5Jr=<8NRFY6%Dl7*f=zQz666gab zz9_#N9rr;m97abQES)SVA{(WVPx<{K<^9#x6WGR4?ZyGW`FMs@PkJ@(Cx})0L!xU! zcPNF3hQLC3j&y1Z6vI|1hEgboa#9TCq!@4!s|yq=SRLoy?4u8iX{#**HRIznqxx9S zr2KrP^^6+__oKwNGu_Z_)~y3_q=I8efnzg!eN*R#~r>1|eXQ<+mNLpjD;iS*c5-0^|wBKy++ZiQ5(O*SaCxa6TE1>cYo&;7L`hE0A%BVDe zbxj53xHe&6ywTp5xE8|!U2iH+_%^L-JSSGB;yC38^wJf*2pu8+{t*4nvTyJVPH1LZ z=Q83676fr0sTcrnJ;ra5MpZ_WX0}E%Knqu)qfUzJ3#CG`2>-Vu>AH0Lz+}`B=WZ)>A_*vPo$ry zt(bzdQvB4A0{KC#W-tX%FbWuP<%3U1xW^GoO~l(D;%#;AnCPQu;I&uzFGRz4GeueY zF4STAP%m}QrK5rx8G0iSolZ*bQMCsw{CXev=f@CxLJtlKx0T{%+qWpXh1pY<*Hq@n ze<2P5ZrVazt5<~Db`S1q@1@}nv4nvGwrQ=+Y#$#*m$QN&dV(L2&jW(?9cPBvK!2Da z-YS7+F~Ktjn-V|B`&2&`IYrL{&D?L}O>3gk1T%RTFMDypr=mzR>8@lNjcE!~(T|A= znlMoX2@UpplHryOO$CKUf@0Z4gA+!fZC$26y~HFP~Qsz_9p^<%AL!U!W&56sJ~5e(!la>wlzhM#MyR3f&?9DWkifG z^oi`m*tRSbl71t|?iF-W*1UM5lCdk{RhI0Ig%uW%N{|ac>9jMJX}8czyU)Rm37Y0r z$Fy*Y18t`N|3bDDj6@_1K(<&?8(Oj%7%Fm|!GNxlUb3+w6m>7KwX!IQ*zZPlCaN~w zv`N$(EOwzTsUdp9_i`ngb>VxMclm+$6pW&@6QZ$U@%Rmln_Y*#B~nZJkjfvxr$%zg z24&gD#dGZ|pH~8DL2^ziq|IVxdoP^j6K6sIYaZ=PO*uhFS|+CKo1JB^M+xWVG+QGv z=^&H+ff`Jbv}+FDgfwJyNJf;Bjr-_2Br?KGc5{a~`r3@R^HyTXM#yDEAe3E!gBnd~ z=7=auL`ntDEwV>M812e}1^L53c(TbJ(}7;c@|WN1Q$oKkd`x;Zp2kBzs2{or)gBQ= z@Gb^AFvU3BHkC@(=wSc+%$6Xf8*2^Yo6*9|ShIaEBh%DU|v%M{Ds+AF;_!sxu zGulNFMxX%|j106lX~!6`4jbrb*AXi!;G2t{AsExz54WAsc*qm4F{k}wU4?a)ea7yO zMCI0ZcMzZQU~B3cOOF5%=#g&!gf?h`Tj?{JMHxKzk*c6toA4A;slHobwdXT2KNxWl zC#)(K$Bp(CTzpix-Ex11{fW+*wm(pyrz@s?8!Ks_ij?6r=`I`X;vfUVxwR3N3>;h@ zFBPB-`F4ED6ZwL8iftpU@d*VC6|NVEUmVZrsMnS4(N^1sbpQdf#~L zSVk_|K-Wi}cG4+7Z15@2O_yfUv6AounxT=a3%x1!2ModTq3aL8X78H}j!IqMH#wQ+ zytr>FShZVO-&AZ%9378wlriWMO?eC_`r$F8nHy*ho-%K|X!LB63TYD|c6KkLF3E3* z2Z{c4eaKHQAj-W0zmqGdpNl`yEyN>&M?^+ZOB$(5df@Z)YfQ2B~eAiwo_EWu+6E>ufw_yjsT-O^JY1W1WgO!Q|G*Oty2T^9PKg zh+U~ac0}|-bm6h2se=Fj!ngYlI>drH0r>2_p^uxWKU-foU!ZbPUnnv+avmngM7jsnBpiKAH6{;Y)yPjh3Ql%V73ozW_CoN__dUh4Hw;Q z5KNFGiJu&~I^|PgFI8gczX>h6VZEAv(SPP@^1i9tAkdxY#iQ47$nWD-X z&nBU)m#$Vr^)kLagR0)YMD6lr9II5F+ZPY-$JJ^_aN+WiM&6AnD6dw>`&K{_;iCOY z07)*kzLbe#>qo>Rx!C%518SKE(jx>`6VP>dW?{(-0}S~!Rk<1Xw>q~MKrF!z0{|9k zi!nIv3O?Lh0HI!GA0uvb#_k!~grQz_jwl8uq9HDpqXYe=k|}i&3`SbHaBk*yqm+3X z|EHQNsgRaBk@PgBd*#zZc17|9@{$lLN~^)M4nO2`qG{0X=+SD z4g}q(TMe;I^b^}G+htVryJPUzwCw~OY}2+=C`*F)K0)GZ@~qS5zo0Kop3N4CdLUB=TNS3WC3rCvN#r%x6F=U%B80~Y|(SRbPqICBuo_Y#TJy|>T#9C9o zf#(R#7v?kdbC5DM6j7$mTg7W9IBL%yXDDqp%k!uCiuupw`IDzY^C$d##dr|jk05TQ zAnq8={Ke^|sKWq@!9&0W(A6d^jMT*>`G!(FRpy@sj|pe1xN+j1(OxJr8gM=01!XFhFpOnORK8D8Eirm8e0g*d~A73+a1K<}~ zF0ND+^62G9A&&|_nt}h?{1^bgGCvCZ3MEbQI3DLnu{;ufWqFkO@nQPOmmh=Uw}agH zn((WW8z=h_qZt#SkT0brVk8nVcDk>f80Yr}B*sC0d=+BI`4QIT!p)+k;66}aicOe# zj%s6z`l4cvQhF$C?AuTrr_TkTs$~!#6#o!g54Uhq3RTBHCFJ8htqdSBrHBEA-SPMt z{X&6~T>z6pZ&o``GrsVvw3zaJh#`j}Z&QK89r>*Gf*PGQiTM?o8#=sz4!;BJh|(Q; z*B&30Xcb3-i{DCiX@0Yjb~0Ql^s#aSpf z!RwzGFh}?&yh`syDE5uyW5*LtM$tdQG>Ra!!BeS2WnvC}20z56TYh*FMMK_q>64%R z8pWQ>Mw5MFJd!m?S#sii*{yirWLxK{gkRN|^Yf#$ULQ)G;mSS)LrVG~oq}#SkP$fD z0cjb!_uh7ZqH?h4F!$}W+~JL9vvhycahAiflCGdG$=DrtXiJ4A^klM~mlk)x7S4$= zCdUMwd%W;>ZBA^EM$YE}9XxUD$vil|2Y#-DC->4Od3f;A+jy%c_Ih-XcSj$h@FIG1 z^g3l*pbJ8bw<6rF@h|O_j;_Q(A5Caybg9j6Jq7|q5hOB`x-jQ~1FS{N`BEXp6y#k! za7RYM&>pA^qD`J;Zj!2`8K*G-tqV3ccORLMniqprq&9So>mEFpX71o$5yhD?UGZzD zRnr={s5l%K>EU0KZa=f|VPf5MVOVDtBDlua!9Xgnn3)N^i9PbIqZj47+sW}N;?Z`{ z0LdU2XW$a)164a?dF5BiLG?l}`Iqu7yAbJ&Ot>rK?vc1E?`eZ0BY{dC?lR>6i_-)s zo`V2Y%16v=K2i}!A3~In{`K6(h)7tVv#iS zIsAkt%%NtEuYEWZX#}D}7mCwUX^&M>72kwD{w^ZPs%h*p`~3t1Hk7N>@B2`>Us&Iouz~8(=Wv zqFzWc`g#;@EIrixr|NqS1#;PTVEH2+p&(yOh>Av*La|CF>sLGKl99UvlLEQUwEfJa ziTTzi!5AHV+pm{}PPWHRf@s=_nGY64kBA^yf+Zq9hTqttE zxdO>#Z}lbD$0X9NyNoPAM_4_lXzV=b$0M{|R87u%7w&Cr<)fCkS_*H`3Zl zaatRmw zigIpu*HTxb{EBL&VT`w-?|W_K_imS$JRx(aecOf;>@;+ zylqSKsq3Ute{SvfaM*TP=S%NTS=6|!}{(2@X%A1n5Te@eZtcQ)h20jC`iFg?DBt*U-W8D+dV$nh-J5DLYW9-$_jU9=oM} zO;*aTEJu&7rt`b9T3<0mA27|lVkyVH5)=BOo|I2|$#UH1>62=%4|}-HdV*)|hHJ1L z3{F0-SblfJ#)JHDRfKEo3};D)5F6?eJH}8a=*Dq4Wt5_)3rQ_#j_TL?h5IHxNZHAxjfQh;>LHou zDRm!E@||++R^AO}AS24$pjCa-%u5y*I>=i_`E;t^nz&G@-*UyHPak^V_=Zk~MY@8^ z5tjA^m+M%D7F@=uHuV|O=W!){nN&c*BdpO~s}|{`SBFD2x=!PX*&+YDhkiykcNwQ& zs>WxFVfrQ7=xH^=&v|X?AlFK5Ys!o&t*h|aGGzLt6ZmU=5UoF&I@3DNdIIek7>)6~aQPS+L zi`zHD7h%VaF)E{ISX|MthDtpf`mbKecO5i>)uJGqaxE2|<68MKEoa;Pu4Um9h?y;Z>-ZvFg{i`mZ z=)W!JlDfd0WY&e#M;F#s4r6WQDArbv(kcr5v+oF2 zQr6;^WBBC+e)+@a7i{#yPC1k(ea{On(zsGuc_}5eUP6bz6w>Au$S2qy=+u=Mqz_8X zx^k{*T5WZ?s_-*P&m;2cr)-DHbG?EoWkRnP9FE|*Y^Oz_gX_gyZj|SO{s48Wh6MBx zd>Y=6;dlSf;9m{+w+DcKwYw3>45%9t)N9PTy{sO$SzTrwow6Vp*fm5AK0Y^PCs42klXT3?Y0No7EjW!cV~3jVrcwq3&VZKPSZ z52W6Qd{>rjzoNg+8l>l%B+$RemI6%h<(NP4_ir?<&XMwV0sg$5SP^vp2_8KJo;yN~ zhbP3*A4@`Vjx-i42hV{g#(*Qo9>C`_+IP3pySwl%Dqx@cNBhgK^b6kE2YJ{DuHSha zEq0&<>SXh_)3`gR1=bw*VI^|s@1}ya>DViJMVi?kc!k*PAQ9L><#OAo=CANmQayEn zVY6)?wvJ-LduGEIYK;Fs9EZL!w^LR43s_G%(fzMHH+7)jX;>POq!A+$#OPicx0lA* zOXC~>iEtfEyfJN~^>bGzj5qyHI%)$8`DbBsjOXd>-+D$kgU0AmY|WPcGqx_pAgj-rsgE&}r)A=2yQa3lqiry_6n6M)Td}1sX ztX40~*t*<|HCAZ>woEvaA?#9O=LDG0W@JK@{DN1*#R?5aTVYd5P&n+T$BwKKvfr{w z=rP&f`QN0!EH}&J3Hh$2zf`x^FCUQz0mAuzsM6zjNWP z03l3zphRj|4^QKA*7t9w)0Opa5#~CE#$t03*3V^74Q%CLlqe;l?q?e4h|!TZVcTp< zT8AI+aWv6U5qR2}yrEDmfcmsluza zT1A`SW2T+O9fyz){N9>jYN>(g<_YE2w(!TX#|e&VmXxtOOUf)KpH7Ddd)&*s^EEjJ z=;VO`?oRhdDq3L01ZY@MZLO~Np}?gDuB|oMTyT@gx3{^o(p;AD104~KjcL_+W6ju3 z4>5(0m$Z#GoDsfegJ`sU3D0%a#-vI#lnQ2%y2VXlKx9N+Lu$kgxu05Fvt>efUTKmt zN&qyrQ2%Py{cgfO(YM&YSHQz|sJ-qPTw@?Ep$7tCR+zSgx?5y^&vG=mlRCBimX)*> z4bWd!+9}I;lOy6zhS!Lsg$(Z=1>P#Q3Oo;-0hv_J@X}ROX2%dOyb~B+L!*;CTFb*}l9AQT70Sa)ae1fJ^ z;o6K(wB`hth`2syHWtfcn&O|qO>ytkx8?YMCBB)PhSN9xREIvHvKih$rL~fl$6J|o zXMi5Y9}bj_;kN9#lv+{WvCg!-^)ZT!9hTlN&RO0`;@on%8G)5(VB6y$+OCxAA2;kXnxfxoX$%Xl#NvnqR7Kmhq z`*Mm5KMm|7+qMbWIN6ot1Sbnd8Ey9>8h#Gzu>Ip9_KA3mIOfr0oJ5Em(*x=9Vy{nz z6wz*Tcwgw)>1s?V4LpdKAM92h+|CamY-gNnm1m3KRsbLLEc-_J#U=dA<=m<~_yP|& zlW@k_ou3J38UM=BlG)yes>Y;ULP35-2&a#;WbB>a`Iey?@AxD;XOfFmU>_wz}f6oudz>4td4uge|y1zm=_zeU(B|9(JP+|oGR!vRn4=^hSv za5U*_QwO>}S{ctu>qm`bPh*n%21Z3V)-2S51p7zKp+gzgIsx zZF^cDGfFYz!Q=?_otv9-<`NZ};9Qh4A^fhtqFWgBg%JZ&rp9a&OV^O*@dI2mfb|#e zb{cA!hNAd4u#vaR^tHrJkrm7FN9t2{ucOub0eX>Mrj5b0{q^M^@BvaOy+nsb7?Gl) znNmh+BD#6wM*1vHATv7T*#iqj+(w*0MrF}pW(_%{VS1A_-Cx5NO(ym}lb zPKKZY)NYSZfRqTTN-nXITqbMv~RX znVROL-PGx-sgXFO(tQtdJ{FTnS8m9k=vg(jF6|6-rc#%i`(3?pRYn$>prHHI@jxdI=6Lfv7BzH=sIVA6|+a;+>cfoE_)MSo#skt{5F`Q7KBjCQ2C~OlNj6T(6=Ts_6<2--0H? zbtw2c(i=5k2gj%4dxnmy$P5Kly)&bC8|a+fJ7L*$>M_Vww7QfLU8){~Jl)+GOHMe@ z6S=+UQab#&GQ(C1SrWsE6lrcNJ}(}}QA9y(CH#fR@|pg|g1tEQU^Ov|V4yh(RRE9} zs)qi`4E0JAUxw;TFUSnFSA|G;d9j#> z7WEO}#o?t|QQ>t&$jm4-@)s5UP2t6#8xSF2f0XPd?(-|LjG@&JtU!#jZ7Dq&b&n$= zofXX*Y4JpCVJ-=Wv(!C3wUhPkEF7Qt@=lC_jDqy?L43&4ZA{rG))y={;TUF}AvLC@ z*>=`?(v^>&RsV28R2KGaAdm7D)gjPNWbsGRI?hD1ZZ!@DSx5&6sQz{qZkGqEL}lWv z?8acBjHHSelH6U@{s4fbGa3xifmu-)cxajdn^iNTx1r%gsWXJ8(z@JT7hXJeL?zHh zY`ORntXZ-cg5-#72o#EQ4DMyD;89aN!a293R2sw)rtmDBpW*yWNk$#pa5`_H;6gl( zT%sbj)HMrr1sA5}Me=9COL;v(raQ=zgJBX$qa}AFb&3!1x3FH-e}LEzM-%;tKZfE& z;KcbP>=Ugwq^_Y(!o#?epJZB#PF5?OtR*Bm^pi@sla2UeC~ilc#H*d40+IH&m4FUc zBH#O&BF$5gAM@YmV!!6UIpxxzZ7C%GK(n_B-x1q!yE%~&E_LiG*Qd?hK1qdZi0`R9#);V z&)ryn;>HqXg~3+hu7mFxwsPn;-)t%TKM}CdEFXqam5;R;%*R@=3xPx_rb9{rpQ7`O zbfBLG9?Yi+&WBiy`CN>iFxnB3Z*WBP;R7Nnt%t<{5f$z+;QvurDzXfq*cJWc7IXMU z+r6nf@BFYVVyWQy8O|S(X482QG{xpPFG7#$(RmTY;Kwj`bB4~{D5Zq<0HTDmv?|IN zN$!p*8cPP{@%F>KTcng8j1Ocd9UuMwZfBa9*f6gn z&6MI9&HSp2m|&)DyU9Dp14f$xhd;Xe_)N&FKQN!)aW`J)h9>QN-obq8qp%(OHg%PG zdoe8319rQra4QZv`Fo^-rNz2?TS|51Nz8fNlT*1Zqi3cBQh#V ze2Dzk9z&@+A~S45M$sS-{1ybBIatoju{M^-l>8r^!fky@Dj?e2Je%AM~mA`KX}`# z@V*$OpqAlP=x+ym&SGaFrNmGyvnTAap%jcM^QeYDtC>HMt;Tsjo)SiP2>vuPPD>a0 z!uatJ%%A@g_*(nHr}Kx;`J)0~*IMvlx1>J;kw(jzZMqixiRJfg zdE0{txIkb&#@7-#dxIYW`>O!HRaZu!g1>8pFChM|5x%M)eBmp>T~9s==u0#Z1pX&d zfsg7RNUBV>?e;#MzlsxAuYMJe6a8Te?9s)y<42Su#Nn?rqX^Fo%juD+c;JICrS4ic z7PSwtqtG!_LIzsm{E+iiI9{&7)2rzf+m@uVr?0#SAG`Ea9 zB)FQ}p$JYc#GJ87V^EH5a70%Mk&sHoYbdfh2`KYdCl?LI4hB!Ti%ymzCJ|aJMHFg4 zLHXuy4P37wY=Rvx1|ieoKBbdV`xmI5W5gJi29KU=uGg-x;j_qmw507*!-FprW=9ze}Z3r`93JWobu(Dzwwo&)`wxR zRzM7+`X^Xytfim*>8n)t>~P-`tiz!F1>zUAzt9Y`?Ym$MLpNc#>IsJV4y~@8VY0r~ zFiiG3e}?IY&IH5E(Fum3)41RiV++y9T$GHKXE;zU<%lT7c}p>d(d8o(aXe88__i&B z5n;%I12A-H0&tJ|0eAG$w)ligv7%zIAtxpU+ejR-m*x}1O4HkjOpb^ch<=KJdC!!D zgp9_Qc<(EU-DD=8j~nGFFdHVXh%tOibUjH|_WpgYiiLtc^T}zDr46<_H8(|KaGLR2lkjNGRZ* zFt0YX<^>esz500#c=p(tS>bNRqeh;G;L=#>z!x3Qf-|#1;^3_>H8}VRX$u7hqBbhq z{6sW-e&hMws4qewWtNO3KpCUc?9kgV8kWt43HT1P`GuxrTCP|CjXWUd1xMYh|1)gs zlh!|dkX5(4@#r-plh#X1ps4zh0ciD5j%|47F8I`AQjTqM=Wa$E7&5(v)IVaW35!_$ zcYuqz8n_D2e7ZzITjuE9paAYs+KzXd+)uh6yVOdsQoovXf8LEk?_(2qxx2Y|_{4-I z?jydfGqE4@z17%=i6fLt(hN)|Qxbw7)OspT{qQd+TU+6@VC{r(mW{<>bukqloH%a| z@sX_fV3HpG2DnxX=6oPZHkix2=<@0hwwH+WuE}0bWP8~jv*EYjcEXE$m22Ks(a)b5aWx!j70qW%eRWDg0%R zMxN9J{*sJXe^EKBBlL;NS)bPCtl9rJ@e|#=bTxj8`AqOr0+!@L@{?jo!BF){fhi0{ z1!%PyO0^&VZ}8KfpJ@2$!Y>+r65FbA0IQ){pzRu5|7~xGpRop1>UsoHt7HPiU&>$E z%1f&n^b8A&EXr$&+#k-&EGV5`aG^D_AW@Z&@kEL+--IvE6$G5xcFs9}J11PlepG|4 z+<-ocTZ0(T4#?gerPu&b^nv!w^s`FpuwT+~!0A-ri$I>0b>}&f&b!bm^@! z1oCIn^RMVEdyod&f6>%xhME^$Yi3#-6+J z@=^i^D^xhUHgY6|9Q+-tVfUURB;sjTdP-=5(r~8nQ<+SzOULVmX-Jkn#4yxAXL{oB zr7^S(X+$zkImepRlysv#@|U-Ig&8}o!_n7KMtf|{p`Kx#&YA5O&z0&dtqsL#FtQ-c z3rp|7pV%|Y?+Ekgk4DgO$FZBy6sO3e@aQ*>KKmW?Vz1#+xgPZ7WbD3v zLVaT~HWJW(lChww+FA5Y+c4vuRkRH<-d)FNKVY_ZnT!qr9ACj|L7{sOG4|zR9(z2G zJ&MO3fwjjjS=4-{XJQ{zsabJ<>Ag`N{Zb@_XxA8ycf@3efq_Q=EL=IUzSDN2eWSDQ zCv9;c-g=WACw*=7=zn~>7iwu(POed5$e{|Okv+wrk@8$25mbpwVoj9S03{_2@hE;O9^;V8`t+Sy9GLo1I}aPdgB9r}LtKaL1Ez zhDQyLXphWyHMk+_+Ua$}94)=Yp3VTp(ZO3l$-X8sb zs3#ngr6uq!gqY9-cD-2Fm%b#6@kaXwkN&+kdxhC+aCV2au}8lN85u%GR3}I`b7r`c)TOe^Up__8CLwv^Lz_3jCmob zFxvG++;l6CWAxmXhMrW7;o5h?7hasTh?Dz;4#8PpbmG2kL^gEDDCm%J&>@pv2Oz9N zu&}Wj7Z5|0)|!$ z!vW9jfME(XeIHG6B?FGxJSP?XL?Jww1pD@g!*9pL6hV8BesWBNR)XQ35|t&me5>=j z4~WaxLXm>gJo;9c2tY4-hML=BN1%5Z7o!9m?nR7?pTNH!{ZNJ@wi{aE41b)7l8J}g zh#;~${@#m$n-q1dVj%1d83S~mv%Sk{KNUP$3^+*)*p~skC9hT ziKMg5uLCD`Fu0v=?FNH8o=hg4Z5Uw~PI}w5uiD4Hx|VnKmzNOs_MTT2Ss{CyxX)LA zj}SI5`bVblU65Rl-g21`9(#E&kgeF;>ep!QLVwq`x3%?mv)L-0+1`@=o{tW-_BLCL z?f8MmUJPdU=xhE}i9Lmy`{{2JnHFJh1M2S`|MekoA3*K3x0_hyLa*&0l#ueCajGuH z+{9l&w@;~oRsnAp4@dz=?xLYRcrS7j+c#lvXTQd@3u$jjtwym9_UMfY4EJJC=b6q? z=n$-BQb363-}Q&~tH$F=VLYB%$XKdgOIX@|iLj(!j#g|dpn?_6deEWKtU|@QHa79+ z7q5QJCjAQk4D9FCuPtUNJQFYUEA$66DfDacan`SKN=_Xb75dd)4)tn3>(M_CZBJV8 zQK42}0SRSQ(umF=cIf9V;AwnaPSa?>(}*2OgtjYc^(9Q;I@Rj84w>0-28_R2t%uGP zwW=2|v=T7f#xT5mkxjs#cMD;52j!Jzo)&v??GF*Ny5`g35N>*ar2F#fN0 zh30?QDh>a)07uC*pDx6B-h8HcQYrI)4b%MZ-9G&P%JuXAE5Z5y9dxenf1!Y(m4M;% z5`y7n1j#c0k3mz_t?=i6wh33^f4HU^w_+WTsNw%V(YuU`R|Fh$zGYmDjTU;_L@sSCI!qcs~P)BoA~_B{=>2UsYT*5O5TJ#kh!N^?d3qI^}g@Ag*myD)etU}Ar5SsLR(2B$8szT}%BIL0&_u3B;PDe24BAk}}Z?+$s zW`>p@t^ZcUDjU$hhJl>9f7HcjkZ&6g3#haCcYWzr73!CTm;2=x40R=V&7*H5pne~% z{Qb9E(32V&%l_NL7)JB#>hk)~j9~JbeI&TN!hib#)_{mB`)?Pws66_qm`2s-JdJ3c z#=z6eqdU>cE3ah**DbH^0-0L__-_-?xgxJ$2pEP77-oWd!H?Ah1N(1gG!16I;@HfE zwqI|*>Xlb$k#dr`loc7;bZ4Dt~no8qjWep*Ydelhj`(p5=^LX&bdGG`toN0VW zNGc9dM*@q-^hR1^$tcj2K4Hs>Y^IW*_O2(Kg{!BL)W@f?q*_4SIFEh>FsUZ6PLXa# z0&AE@zmwH8q<9~p8hl{i;dJ(j=G;{!KY|Q@iAE&Dzj0%h;b!uFO(p(X%U$}&Z!?O& zW=&kC+$T=@6oB?*D zEN>!l2JoWayPr8D-apIR%rDD(7)qHinvG;IB;3AHWfCfrKt~NfVmkd7`9_a^@-b$T zC(%lFxq#I3lds#HwVERHiOBNCDOuh)_>@uTTrp?M1q_Z48HT0|Lye1Im_ki|-vE7N zf0E9?mx?|l2ilwEHL$f2>ZyQ!QnS2qYL<6BykN!s1cAF^BEUt_VBv~C;KfC$fFn}C zae&?6aSTUnioiuY1O~pJ8w5dWhM6>Ep1Z|l9}M{9xes7k3I^7Sk?kKa21fG8=bVfI za=;e}4DkI3MRVB!SM%Jx$@~#*3+XwnzEPfg3Uq$8ih*_Tf;AZE4Dbm9_Y0M=@;8+m zHV8QC2sp+d)#lMZ%W%ZLgI3@MTrWs@Zr3D|AfYls=DC}_sOpMzBxLTRUNmZAvl#G= zxjgYpNJx3~m;a)PvzoXS&EbIKE(oXz&S!hoL_e|^G;w=yH9;P&Mon}F)G+8HJo<_g zGzL^b7cK7UTUZiUd`1(_KF#G}*D zxgrjC3m7KcMj#o-yrh-mX)*i7{-YVPL`o5(DM@P~K6J=IXU51{s0 zzpr4W4q{glR>&ppy*dIPka#HLCm{3(+(!Rwg-U3P0QBhFLLOETlI~?d^+vSf#KTkk zIulx5zkic@@>{=u)XKySjpP0FVfl`b`mhu>N23p)`9;+MyG6)Z z{T9#pY48W~^M{x*GSCWwBJ0CldDpEEFXhS15kMdQwbH8(_X!xr2pIkVpTIw@A{ba7 zu0YdZ`Y@i2X=r`;1^iZxKGb6(8hx09-sOnmkbvXp9L7Z~v=r#iaKxsgl~*5bAUa%& zKD>~tiU;Y#i!0EJMjsv(1LlbV=Q8pS9Hfb}WNbw9VEXWOvRPNrhu^_L)ksMzK<(9s zU$CNwhJh#(N^Om_(3#eDV$!O{ds(JK@47L72rOYLr zUk|JgM^cXg^kF+fR;c{I!(Uv7KJ4|JA}gd1ouHpKKVTQ4e&G$CLpWASJo=Fb2=lQk ziQSa^K-D-erLRRFMm?_*T-AqTh<7wpe^rbAL{6k3L+=svg8HA*_%-ls=dB;bMLQLOZyPe(D-kAO2SWy7P5L(oLMm=*@uY zhoKeg!w2|vUwv3WJ^AUwd&eKc7`c)6+r z#t36yHJj(Wl$m?rerAjnXyw(1WzSx>K6F1TGe-b@_$WG8{KMx248sKsT^NS-`v?Zs zhn>+hm_CeSa}`=2z7023qYoo75sg0F<;8_nz_If+#>H6VKogx4N@Glp8f zhtUN8FqvNutPclMj{)>yD?(NXeQ36?Ue+ZHm#uaBf%B$nz7&}mQR|Ve$-i}YMv)c& z{M(9+EGq%>Zyu~0L$MQDzZAiA6ikwAEz3j-Y_Wr<{pdF|?bdsUSg|BeK%ty}n>*Ue z9lrqHtND~`M|+us@^4gAG@E+Va7u+3JWULKn3pL&+f9Qrr#yz{u$;)hfm4ptm?E&I zm8}z`=4nbh>3QIltvtB38csP3+!3d6#?G$Kt5RvdMZodHEJng4_HA1+9QrJ@qLAC8 z?@p*^@t~5ko??8;*xkw&2RxU=EwTV}8I#nRy?`>fE%-5*?lfs#Z3Z`|F0xT&KQ0_LRay@qYStUPW+yi}fZ0;3t&J>rKa& zs9c0)3rf(9voiuOa4fuU7ZEacEn0c??a-&MTi?F;w9H5W)|;L}=Ze0?dLhAZ{1t}5 z$}l{@Fz|X)4>VQvtzW&wJT?uX*PGf}y!sXiy0=CNW|G&N7JG5w5pawYaP&laz@y*# zE8}9ez=f=D2cU~9Bo$}38cq5;&4Mv72`MiW14}sQQyDC{LxKVw4!Wy%_ros3MR4-5oSGQ_(@q z{rpK6>FE&uWFFjD4do6$Nt9F8o5rw`ht|r&V|FGRO``hBG5i(u>dU=r3fyzW172?$ zPnMCj)fl#sV!bJu<{7%&eUq#E2_Jo>U9aEGIu|e<1eu(T(2&!gdx&VnLJNgXKJkSBcf=MCsx#>HL% zM}mN(Jv(BrRWdG|3y7pjeNBCIaZUO&?Fm)<$Y1@0deKPU?_$73g*@>USXS`pZ{`76 z^77DJ#P3M&`_-F0MfT+?`tt-FK#dd*2loj5d5m>5^ylfvXd<$&8j~XG&5rUzU}`y< z5%asbc~JeilYaKi@3a1#`#8&Fc2NDfalDWI)XJk#42k>+fN_3;hAfXJ1`Qy^^Y8l8 zC8|7j6k6=50>)+4%Y@7ATZnl2jcDaBj|a1B%j0Mm5RHsxb}BL3Hy9j)(p?R|grr`* zo~Hhz!Q|6f5?ns1{tc?0h^f@SeW&u|$JuNcX3yYhJ?b;{@a z*)n$qh$kg@=>)ixO|ZR4{Jckl>PtJG+AN4&WQkO+%%qSb1amiegW&WuwQd|vWop0iWy(0 ze7rb9=8gdNt2a7V$C0mS;z9iXt$>S2Ix7r)1l|?f9uBxhKIVdZWdEODrse4rJTfC42~`b8GKzGy z^U05e8M}#?jrOhm4J$xqEP>x*Gp3hrNym?3e{2&5C4m3`aA9$e6mxPWR4;%S~& zi3ifX`(3{VG1UF8`$@xNGErbE?S9vvSo1?8FQ?X9o%65M#TbBl5s{L>dxcx**L+68 zHeB8B+Fpdon*ab;bv;3{`k4-Y-6wR~%Bm z9)fw$=+}#YO4hG+vslFA1nkYRX5-PnxQ<|t-N~>k`t{rc*R5Y$4wIQNfPS5T&K3O{ zEnt}Sg3zy6_dvZBYJ!w{UNjA+U(?y{h1RcS@KZJVwF@Q!TqyOtQ$JR5AqhAl1RPUd zBsiX9IAVvPl~=zWBRX75`A_o)RB@#Epb_<=(XWlffNxIZiO2AOSJu$PSrU)TqlpLB zul>pXTt&Zbe#}QIdjM*oUpKH02WM{^LKBhW1M`hSv99HZkjnSbjM#o7H)p8~lwbLY zehv^HOdiTInjI`YQ2p;Zt{=KX)4J>{{PpWq;^j&I2__HaKZlfuZBVruc?kbR<$>pg zatxcmB-z6x8NHfF61!jUfKvZ6_`2nx!I0qcFb$n6@?a4#OdiiL3}G1lLUo=j4};M( zm^>u24GAp|i{TV&_@9-P@8--|1V(}BdRombAjGhOOhcW*NEe}`suU{DyjNeOs49@R}KMz5p z6LRGEv(ZN?jdzJ)BF@4zc0m(C|F0sH#~%NXb)L-c=kB|1es6idOzi;i=WFO(;rBfP zhFN(G!;=id`CkYIjz34Dsmkwu@n<@lsv4$zu=ukKPOif52#va6BE;`HDTh@>In&&_afHT>QKP}9Uk{8`3!2Hwu*ducMV4TxG&k7nl4ui~fR^0&F2 ze*IjaNyMKg1=PPk&rtu#={zGtt^XLUc-cRjUx#c2sCO%*9s{grng@lJ510L%k3X*Q z?<(%m_;>%3x(?vq?PN8M8SkUkTb(`79s74X@SXj;Z@7j2$bV@TUjJ^O@b8X~;|Z^W zs387ZfkEv0Vs5JXcTb}y)xV?l*WO`Re_izEHLSmWZ&qa6fBm(|0+#In>#wx`0U#3_ zd?D6fiy$kq_P$dDZ(Rk{2RZHk@p6JX_HiNE%KitQzL25X>#wzAjEsA{Os(#JpdK}x z-9Ze#^f^Y^<2-l*56+x@=mX|#vH!sh9BFo%k0lF3Q=+?Xf<%sI;aO@p`|&Kn*&ovz zcKv^_x-0W)Cjm!_fa7iy4&eNbWlXyEya-L}ugeMblq@Ns_1BeTaPaW~kNy+3J+KR3 za|>F3UBe`GR=qBKrFZ!U_)5>ADH(;2_!abZj?V890qC3DqfY?J%dZb-F~g@r&jnb1 z-Q?PM)|cOvvv2~&o6inV_=n=nN~jKPy!n`5;iPAo9*vMh_2}m;WoG!Cw2V^E6vy)s zyl^e?W~y1`1vTCr?5E{Mim|^N%VWQdEFi{+o-u;y!kX)pb+uqS-6&3`VS=f zEAi%WR@tE1SwaaFGtD?7O!zT=0BV(@2~q1bH)U#hi9(=hD9oZqJb~YX}fYMC5$g9q*`8-(7?h>0=n#CMkUb%ihRBy)h6AbL`Z3@h;lEyF%?gg! z5ko1qd_}a-QGfTRhrrZEG$XFR#Lb!O1I2Sk>E{6c>wF{2Kz6Wr&edRnPyFWU4$t|z z;VjhS=E3Z5>1(vQ; z9=i9Jxgmgmy8yIS{M#D@4D&}Z3^SQ6Ze$qPzb$08kdN{5^KY}+R>}I9OuVD^`2v5! z$yDS4{_T){LLOxQb|^d)*&}Eo;7AZ~OyQ*CYl|2c$?V4{@mzg$aZUbhT0b9oIQE{e zJlrS-T=W!AJcb9nnFnNfSdQkw{M)CAwUKWS^mpfckO{L%o>uqoaPL-t^Paiv8PsejOqdz`y;B zdJN#-j>!xyKcVxV0{*7T7DuLDdlKJRRtMxt=V{d+v@immkPUW$g%2TMhUww& zXY?h?YR+GbW@`fC#^Dz>@mo9B#Rm|!Ek#t!PquU`41zD&$e4uPvdNB{lLSIK96ldjM>-p?Nx^=WYZ2Y)~Z z2uWCEe_+NNs?0wu9N^@UOq@N;%!XWn@(0oks(6q;@D25%@dus~11@@;Cq9b@yqO1N$#@aXgZTqbk$oVN zhVTbYz$w-0KX8xm2ad6hg+Fk*H%&y2?I*Vrd%chHLttt-nvp-?=H@~Dft~bo0DoX^ zI*UMdP=CPf_P75b>gT@isqjAOw`{v_{PMDhA)bDWG1&(ajQ#BMnRH#yRMl^Tcy6-2 ztfk*-$FdW9s{~Zzm!q%vQt=fr_K9pBy9|=#(GTOXnTkJCbHDiIYcdxh;+IbFq&1ZL zq!;Tq`8?ouY->QhPI%19?UQ37ez}7mfO0xCAL6Zeo5fLeb>vXdois-sjE${ zZ!`VrbrpSevAaUEct3r$`@`V+3jW%CFb~AsvcHyVQ)P6M(9!viGO{0psDeMgVM3eH z%B!z(z%SRSuk1Z#Vh8ZoP8E6e)m8z+zmG5sze0LF`llEM_Se>;sj9F1{I!K_PGtTI z;;(guAFb#s_-mi{5c*2?*K*Li?63VQ;IIfdvKWqoUo$S!(F(Yb_0>b@LeY|%sJ(VQ zjID>t?xe3SzU<5CyTyQY#DM!DY}o(K12U&?MDt+&+7i;|MA8ucT2J`P8m^xY?!gCBDFh{ezxFq2rlCfG=}_Xl89Wn8=<$NvJ3DV&G+=nKY0 zv5&oPfiAAe-kZ{V za{T`-O$ru6M+~LN&hZQN_$Y_JyU{~nY9pF){LjtVY6Oh`>E{6Uetv3bdAK^iZ|D+~ z-`@?+@30rG0TLlcwiovosx(d)!P=k)8RbdPT<~i?V;Z+ZD=)uy1s1N8-yiNKQ#*jY z*jnJ__r3y#O~V+5&!LA<|G_Y@z4#1GRetxg7x`>fLfebFaI+PDhbpsn^|2S@y|Ql- zaAXKLdLr@f(J%OvaWP29zHBe&AFY2;gg1v|(rc!vmW^O&28P3t|Oiy7i zb_q-H+cec)3=>e_B%mJ8P#1kdXwv_HRvZS-pyfpzenGWA;!!)0SIRf8exB+GM#$-W8@&3J@1m}N1sr}^zfRi%in;zg2~^g zw}Q(b?9Io}-b5_f-rVYyzu6+hsT{&A@B&scv7hZ@LT2p0;Crw9E$(#P^0%*(%zXju z%|{yfdsDz*7BKvSbxDtY$vlFA?Ttk%e}48RjLlMLd-D=}XGQ*?MgIX3i4A3YlY=51 z+1|V-;8;7Dad8vk1^6utM{GJ;0T;6TeM5A(mU@XjclpTQMXcLvbxiL?A|MDt+rWj!)WMA8uU#sPm>BY*#YGnnBYM7YKa=uSSQqU7|Bz-KdtwT(s^rtEl4+8He>9p@zJI3ndH7K& zDnZqJ+FW#~rD~ZNdx{wQ3utrf|Nnr-W~z>*=6?CKG_p1!@@Z?}%4#Ti7oe8c%ZB5; zIM&$EH){wbST6%g2O(u^DBcW6oVRt01ON;8H&F2QCYc@7^jVKv*w* z&jwIbYvv|1B|}D^*e~^My01P|);k9U+OIsdy+S|#_41!)vn~s;UXK0Bzd_Lx+kdVD z>wxYrs?w`#%FI;vJ|_9Wp@jD5=Mvgu&rD+JmDkIUckt4@_Ii13nm6gF(wxr=r2WeC zs7H+@jSz#|2JzsJ^WcBKPlGefpGR{@ve>VDjPe@Z{mMPbbkUTy)APXlmDj*;)zTj` zAQd)`-rz0BMZl)Lnl8PN;6IW6#_u!p@jKSbS)GGFJ|&ccKkU1lVZH0(Bkb%u{0w~Y zEVt4x0i<$V)<3^CnU>uJ1ef>jT%o_k8)wTOa&!JDOPyuDawKah8$NhB!s}RS3Vq z${d(@5A6-b$Hj077!I=F?12$kD;98Xz{x}0UcdYWVxQq^z3^%A-rRc_G3yvH_5Mr5 z*3agqYCTDF^rWt!xgI`wo$=*EcPKIv@0XvM=Ll)v0tH;*WNE9I$Vpr zcirJt70?ooQ!g4VFZi%1&6-hTiGR-+|i0JVrO z|I5|~_Wt7}nuwfF{`W1Bm7K#5;TeraGcxq=b8|NIf#S$xCFVergo;sG;;%V(=Hl;4^seqi?B{PD68H4{Dzu+n#I|O^HvV z2)y%V5j<-RrEkRyKxz5>*vY`8dVcHzQrP1B*g34b!3FOVs>u%QaF)A7j$t-G0uMZe zM#KZ}aAW2H|MO!Dxy#z+Q07FYe|j+euEtLhuE)kAe!6jOcJp`tLTcXh8qnLA_|CVw)K72{GWmY&f^PK@(^FcL@ucLG>TmC?aVn{RcNy zBNZ`#TGoH8)Jgv(_{TdD&R?Gq@s0z(alA7Utw{vt@LRRxokDsZNdM8~L+C%(z)L>f@l$Yp4!6^v_vYJf6HtHGm(lbR$I{IhYW+4P- z1LWIU5wb$bOUoO5{eA8IHsdI!Ob2qaHRlQ6af>1^iNapQD<_Rt&0u-C>V1+EVG0P# z@_mwDk5!qalZb}C?88{dhYG{}AFmSaVhhm9D>#n$>lU0J<7Kv)OjGi`PqHmKR~+ZA z0){pMhJX7J46ix}1~wd*#%Kh`?>@=jSg#Ai5$rz65%Av?!GSBV>3?x{C2%&D-`_UI zcAE)TW6NNYY)x4jp+*gj%+zFy7)?Y(r9vvo8q=lxN=cT4N`<6kFWE)5D4`OnnNYGt z)ct?Y_q^+!d*7M)|3067=Dzpb=bY#4&w0-KJm9A2k8z*mQjBf{j+RQt^w#9X2J)gL z>F~V_DBEyGi9iYxI2PA1IM9RlNw$+w9ENkNBCMwfI}+h*6J_EwoGP5S@uFSGeUd*) zd=Zg)+$Z@UGFM07_~vQ`4&y$_hWKQqQ&~Ei+$Y(FfeS$;4FF{U~tnc7Ag(p zl!jm6r*QrSX`opg>+dj&koDwRx_j?@sx9(bhgmEI6U8iy^<*7;#qo*KG4>Yn;$Ig2 z{>&yXis*{Nh$jz=913C<)2dl!A^ZI+2fNMUGeuZI5l$q+=ZKJI5de6kd}^~ea1p6T zK9zp0%Pdw`rCH!UnLFwIq5AjWk*Gda6Qy#t->->O3Lir6s{%~)zCFRI_u<;P-`h#(fk69;ZxGCmf+()swpT&#AO2-hTJaM6PDIe( z4MP;jAxwy~96~Z2!j~Zq;e;YArU(ZR;Uh#yhwzFzgs}Hfd=@Y!?r|SQOCn;OeR*K*cFE<4@=mLhhqTASEt;!22jpTt$B{ z2+M?F1-g%7)#IV@QTrFI+%W^WV^^3`7Vat~Rb;09f} zpJq~esm4M11o$o3H%Gt`z4=PD;0supkuCkBtKLVFsEw6qkNd|^3#I`Ic3>2uI#v=M zsT~w#W8&FLwlbIpsoo(YIx?q!75S-~h4GNr#c z?XZpB^=i5_Vwzt~VWa$l8xwzmt=7gwEn~!S@9=y79_bs@Ca{t%@QX?QRHgHAwEW=Q zj?uy-{{r?6rpMvDFbt-SLSFRSJAw2K=^pg2kU!;RfwdwEvHzuyb^l8!)cr5~<-E<|Q9rdW1KQUW`F56hySLozt^dnibs}_q@6j*& zTzOO9WdCx)6YhT5mb&I@-i%@^kAiW~KW~&w(w7NPYyUEybGtw><=wx`Tf0oHXsL|V zFIx@+I#uRY#l5B}alcN#U6;72GCxR}Af#XRX$dbL{j$Z8-a8z}6BR^F%=i5+(=)?) z6vtx`Ud|K8qv$mL5gtkB({6x>(G{Y-r*y7pY~wWN8nl}`Uuy3+BHF3`4F|A7SLruV-1j$Wb~{l#c4m<3Dh94(FYWgJzAX5H3ek?WKGk^9Wdv|F4aA=R#Bg@E-C0t%9 z3T5WcGmKDKf)Anf2jQnh>&p^6V*Y$q+zG%_o@48LE-yEqFh3hDMaa83Q)_xt_4C<(+c8WbFQ!y&hoDh${ZY8*I#jGD(+^) zz2#Y%F14n|BBsa<}aaU9Wk>$DU=K@+)^%6 zmDI7%2oHTfbaTkB2rl>;-(7Ogr_2lTJ1Q)Z_&9n;G~?p|K7iCd28c-QXM%>r$G!3}L|(JY6+m8r zzTxxdjBx!ti%OgF3f;e5@CajL_)OA~+s~6y){?Q+&l4MBqt`3)6%B~I7m+6rIc5Aa)De+E z`+1fNPCIRWL;{FRX*M%~uxaxdB$Ez#_bS84@C1a5(!gqPQd8!#LI0m4INFdd$am#W zNpcSgtDy(TaC07%40jJ7K>qI&Iyl(q&(r*tztj4A)P5n3`Rxw;<-AMar83lrWJHTp zL<`8+efuZ+yXrp?YQOosU-V|QsT1*``O*N-eCaQ^Vn@DItBa)-6?@U}xT+se3v^@D~x=pBzRKDe5rnELoveSOK)Ltv%GMX(lDbQX&6EpqDceurNID=lrLp4 z#(3vT-y(N)!=#=iGjyr`~pR8%@nGIxA_2zikVC_7*JN90hDdgFDaY|}u# z^bh#%^nCG(aPD=S_;4b;f(U69+W;OZU%FQUoQTw;-uMIZRfkoifojc{4$!;81O8l6 zCSueZXFR4}a4#Ri3w{VN@qz~l9x-3qAYX^cmnKHj0ty{p8A@oabZL zRT9uY4B~R0zz^xcuOq1-u?WBS-!lrr)CKTl%?j?QOWv+Ua0&XCJSoET*9R1qK}?x= z;$>>^nlGXpnUJnOo%rWJEx!cEJ_1}$2M{Wb;{$x)dTJED4s3G`I17)=m8`Lz-8MGV z-aX>=qT;5lOTN`L!`+YDRAXlUYdO1hEKKcvLTL0g1gMp7WspL(kEI3h<-?*Zg|+%| z58dt7+9bt&vJP>#CGM`oO|4xh;356E?~AMV=*Ml0)Y_q`b4oB?M>k%ZI~+vgz88iH za6A#;Fl0YJCK`WWqqPp7Kn4DNN~Z5`1oVaqq$r^&O6W{3`agP{P^E;(0CuxC3!6jU zZ$Bd=85^uX#s%;fC8*3^3*eN%I%I+?M}y+rQ@K$^tb96beBV*jly7K!FVQzrd`ExQ zwV+MR{wa;`q8CPdU!V%#oZ7Z>$?$9c6@KiDQgawH@@esaXeVu(h2K+ z@53QF@sW}LClL7(IJBTYg~+KB9|K(DJNmP@^=vyIJ-ai zD>^&tz^Wti%>>`zgqK{5L*G z%}8v$q6Bjx-1^=4APT4P#{J%P1DEhA&Mu-}9IV>%8!D~PgL-#a+A>eqh;?gIU`632 zgZ@_^rM8p+lo9KYJzW6?6*BHOE@~*u;DlsUgt@VD25~PIcUQlcZpZ!il!ke=NW%#D zvYGe~$XC`mFy=+yJ92(RUTVgDSbBO9 zjr#|Skr#C^x?wpBm5ypkM`zY+#y>({6af@?VQj1v!w_08jT!5?v2sHZ7YDepA{>z0 zyBDU}99XQF=hP$z4x(6#_qT|dojaoe3J&PTN^POr=0F#TWnwmE<+-%E%Skvx5G*bj z7k%%@IfNY4!GZQrEc{}^_w*h91{mG&lsFw$s>M~5j=7{`+(6-gza*ewJc+26{wLHN z22yE?e^)#{MjIDUPxNbhi=QiXwC(Yn)j7Cd)W0~IZ!Ms}Ph*>A2}U#v^p0vk-aeq8 z|GTD0YW>5hleC@T85zY<0l;DULVkBeIF<-E4G{7(L2=Xe0EhR%HVyiK4vFR1tBV+8 z8e=!mqQb5&UPB)1@IEC#wXpFO`~v+V3@Gp07%q7rAPZb}s9_f0&=X&G;ga*-Fv!7lxQF|zR=t6Pw)#OHV z>~+F__ZLz6R#Owr`t8um!tPV;)|?9Re=#%$Pph1M+0dde>yi60xVav=Uuh_(G%UsD zANn6i1J@%>02*mMvi30{)q6eC7J0F0l?Xgb!9-CfqkjACofa?pC>>*~lNXs-xMTg= zkGxn6D8onN;lm<_f~-fTU9#**>bDQeC=NU7rwA)3!V_4m2mQ|xVJ2qWv<1K;tw%PC z-xiU2tVhyIy6kB6KQi%Q(*HoGk4SwF9${Me5B(1V{dzu23Lk<~RRJa;x;?=ou1A`X z6xV*I_CNeXd&r8o9%=t{A@cJpE`U_(zU1f2Q{4G^H%&daR;B1_u@c_oA&PDiK&||I z@kN=i>WjkzMtomx|3yoHR({?R13IPHLvg1o?sw7S74$FfE4V2|pMZzt=cOg)c;x4= zBKviCz+#}<-fx;n*A5T(s<1@rX~j@^5BewaBjnXv0N}c;H=1722izfiT~M=vGLeB# z)9nnIXMXk1st<(9E1&wwedj@7Sbw$lK2Lx3G5oR9Ux9^&ziQWu-urN63VH=x2K2L! zFx$6U7;Wu0ZTee`r%?Xt_}_-G!}%)=Zu+YF~V)DBEAH6gd>cU*(>+)Lr~l2N}iT zuR1Hj-imM_5$@}wV`f{M!=znK0fWLbC9H#|@@K+Oi zMsrCqg%9Dc1^`U_)pUYK^jBl$YxnAc{whr-@71qZe}Aa{d(;zpo&l+rzgpbGUH^Yx zeMaT0D7tmYBD%4?gpSR(%F$hRuF1AG9M&$jF?3PwEQ(8a{>4F2n7L&=j6RvsUo&BtUZl zQ)VYld&?}hy)SY;JSbeh{6Bx1GOMfkaJ<q^6!@}yw~3-vuo z0|QM}fLehjq+k9$#sLj9k^1EuB0qNoni;1w&=~#lnJq0|%uqT8C><$q95~k`lf1YI zP3uQ+&0j6>J4c{-OA-EaB`5w3tPbZa5g}E69l)(Xvr3j`c6n=& z#3K>uTzMY8ywwD0xkLTuLX8k;jDGol|7c~Gw-R+U>6iC2(7`OKiPj-$Hv8qLl+nDo z9G}B5j>4IWVN~ERXc*3Z`4Sw{l`peje*2%akF1FK@~Yj1h(AA`0F_q!nb6#wFTbNP zU|K90d>U<9xc{pMC7KCP%b$$|Gt7LsAoc9|e^_$0^5t?E&?(&cio3ev9!lI3x(jX! z_lG2ahvduOKR}@lZWQ5sf!;`89Rl5RlK#xDXLpm|OZhPi-!KF{wkujD7W8-F6G*Ee zVf-%vy-}t4R0$m%Lnh6H_T${%`(z}4KOs`;*?$Y0L+aVJNv$3rU^>4)Pg1yE0W0_5 z_)z)glVAVyJCKLXuP5K_nP1<7@F6y0)C1}vgc-Q_u zXaxnY-#15$5hfb-`-huZy70SJ4f~a)PPV3KzUe|;NCA|g3#i}Um0M`Lcrw?}iZJ#2 z-1c`~Hum*8lNUwk7tQ+pZ5RSRf_lj?t(`5kQ^%~0Y1d-YQ^nf_Hl~g_ zd@ASh92W=N_4}J_4xCraM@o|et5AQ&J_9jp{T`s;K-l{I>k?r^wjTBSYRJYN90)+M z@C&nkKd=cnpqt&7l#ct9j-x0g2mKp62?zXb0R^Xz`u(wAg_^@aD)swcC2(LgvwmMk zMpJ$ksmGc|IUTJj<@yvy^A+J}X8ry&Ml`*fV>Ot!eqZx9%g-dk&#Y{W-#PqDaYZ=2 z6xp}|z8>eA5@9ANZW;hM{7l&T{oTeiyz2M+kls4{ObVzLHfsHT2OT*=@xEUKi@Sc` z|8xnNAo}3(CF}Q73GQDj6(Hq3*dz7(AEQb9RpfoUj^zEDtN=lGAK=g7p~BVg$I6gl z>i22C(mxfre!mhMF-3BJJzTK$vdQMbJ0tgh`1-SXO@xPK@?+|7tPmAEOdnF1b?KTne=;Zbj{jkMh% zuUC#xUUvRmnNbEt8;@_8KgX<$#vicMN_+w_ounW3|A+FCVW|g{&?ZV~E4Bo^b+<6d zzh8<>l0PpKHizWTM`fgtevprjcncRTKPyX#J$Ct_VD|X=Pe5$RccjSIaX)gctLS8& zhNn!OwW2V!!$RcLOW- zexfP&FzcNd3~sJ>K2sXXDGk5Cr(pk+ zG;qChtiE72?&k?v@2q8v@Lun@H4x)cFj2y>vEFF}bu#jh)k?=$O%@UwQ zq+a`<$g3S%zxoH6IQKsp-JtRJ;E}c7SS@K@N^!r-R;T&x1UIGnwSb4jr;8F5JmS+B z(dDD+uip)2%?PQL;O|7EuQ}BW4L>Vzq%0~z_8KnS{XfjnS#xx$+S+_ZDr!r>@&4x;^FU0zbYMI`S`1uNMIdWUJg_n`=1O3@K3J1X_z?bT0KmjwO(%Fne>GOV4!8d)llR#FTv<%=tMlI!EWhgcEl9QeQ~WjV z{3=y*oXY=Dbf@7eu>aXcIO#hFrd$502zx_jQC=SFokgzrlF$CZbTO=_CIf@yxIWN zl2-;NQ}Ff9uy5V+lJ(Bncu?Z7x;Vvs@^9k)3|*tx|0Hh8YomaN#FO_W+<3&3#z?~* z@|v@c^0L=E*D+inq$J`ShLo6v(f9-FojQC1G5t%g>+cEl#(F0~2~AN#AAxS;{e|0v zN&X}ulKt<(=8*Ny85t>Lz4OIBZ{cFSlRF^MG)2Df;D|?_{mvWqfCO4*XuY&dlCU_v z;Pukdpj@1qQ7^q2s$j&aM6J>!p<)N$d?h?4-rsC3yzo^7l;N9WgZ`_*kV3|(+xHqu z6Q*9e42(AOYP^RHM-9@zdg(-fMyi+gV;E7t6RBSM2a;PePGKdR`HjXY zqh8v`=0$U*qk+<~v79LI)MWCal=31T283l?c??mYdTHx#TpV!KOP4x0fMa}w153`5 z1MP{qIx(|e`l50mY`wIv#5IwvN4@j}GF%4-xw8Hc|2bzb*qkPu;Rd!%jVe{v@ zjb%3Jv8`7~EaeLrcrzog1utd@HOQ;DD4^IQ-6GM`smbZACbo2wx(?Ow73HCjgI>KYu5FTSV%y-p@n=>#(EkU(3X0y?-B_ zJ~FTe@Cehwf5@LNH`DcgCq4wH>H|y?uQto|n@dh0)YyhHy_+xlO$B|Y)%KPdBdEcTbZnKIw**8lB=*Z=L2_5U%4{+Cc1 zswoW{84boaxAZ>+pb_<-ZayFVM_%mIe=yOZ|1Vr+>3VIf|->`<% z|9t!V`oXme*NpzYY2dJtpbphl;MC(3{vgVt*i97vlYj!3j2H1oY%R1Q%-L!gLUL$- zUnLA~27;%Rh6+lK}K;H!e~WUMG>Ci#K#dK z4WSsotw69!0=(Vdw?pEEh}5IMuM^T^has%rOhYjG`>NxU_4;atjwbzmO&N$_BrO3T zMq>8&by}|r^#*(nJ1GuGv6II91?|My-fUv^#T zUZ1znrRUZhO7Im{rkXUN1m6LuwLV|GN#<7Y_4)oymK?2mZzl}s6y`08J6&;CBJSml z1viCxjev)&&r3_h@mQa~iqz5}z+#{p`^WbBJe$!1N%3Ui3X^4l>jDiX zZ+$;+zd+6gx4dP4vIz!s%Dal<&Q#oWhd`Mj9Oad&wfKZ5>d(w zXoHo8+mr^p01pdWc)ifTmCZUMpg|fj6WSER3}96?Q~8Fu#2d5rQBS^_Gz{-oo2hdpyPJ&<>~ag=vyGb zVFMu51o(&mzQb@@MxroU=k(}N^7STYebE1XBl2~nxHfB7w3BE+URyJ&4V$IgO}RPd zOUuZzQUgr~8~!x;{HCIVuW7w}oFe@92oY}jMG*EQ!c2_cv<<+m;8;Y+wS(iw;_^j3 za-eBxcJn(Jn-L|%`D%|~Bc1De9-qZew?#`Dcb_rphv ze2jdwTa2YN|L$#{8{|Bnb$MBWtU%E~t=KB;-hKj`EoS9XHHkYHT3}p$k zzi=-GH>2ItN<$~5p&@DbqOQ=u{e=bqjkLc|ia}BHvPk<2FCoP=%>^~uf5BEU7h`{6 zhs}%Um5%L)$csKGvLpVH4&Qv`g|WY|1VflHmTK&X_pW~IpI5p#;M!m4?BKv?#oR$L zA4h#W=wEX!IUq-`)Kd+Coj`j{bGR`fkBeU`i;%Mgn zLNAPHuBIH>b>97j|E+MjpL#Ni!~MLh2+JzMCPX-t2s1%((@Rl8c=&$oFC;_=8$Hfb zX@g|f;eI|{u58r(gejih{F z0&Zll*k=ZybG7z;h5g2T zzNKs}x?Pt^&AumJf+vJ8ZzoWTjzFOBP{y(O)yNzTodr2IKV_MvOxF3IlVwDQMzvMs zEA|ulXd+J_a%$8As!@9W=kJo)X$~nzJv}0EPo}g-o`=8B_Y5*vheq}KOf_n@=7{jR z%fU_S*!<(-moehFk@z0{+;r2>xNn5zSkK`c(Ai@RMcd402xhYg<$nk{hhgMhbWXo~ z$2ncWIc3xqhWc9rii*~cKc}Ku%l9cnpZ7lB9-mRalHsngWXpSEsHHE7qA&4aFLY)| z67&T>iF)o6prpP?J!V1~cRl8PEpRngTFd_^!k<@*!p{V#wLXt0y#=qwq%O5&Z`EVU zVL+$s7bxyE-;z(SBRU2Bb%~p@|3Pw}kb2D15-mLHF~yNsJLLVury_4hJ?0{PEks%b z--t+a?#?v?dS3V>*~!=HkGmAN1iD-at*C^ilhEgDQlN=|qClte=Wc~;;H9#%- zCX;-XuOmW4Ja4AoCwb*N90NM#yGwEZu$QvW>BF;Nll@?mgJ6@te`LxmKBV7rzF(LXalg1VW*{!l*e_mJ)XD`O z*OkGbZ^-P*ER7$$nu4AID0p#Wo1hEyrI5?AXFoQC9cI7yRt#?DnS+&v6MIO*Ypj;v zOB%Q=s|ZkQSr*bCKAS#Y^>4J)3hb(iacbSpoI0yT_#4^ z8KvVvrK1(hHt643oxDf{l#z4e;hh+wK+CeH7hCEs`^CRsa%=hsMR;a6C%zrV7WDTd zLTdUdfLqJ5koRHVlfWP%_1G_Nh&qB1ECg{o)>FblsJ}hgf%A zf>RaGR-fSTQRfGT+b^z2Qe5k=c&Sz#`iM4=6>sFruUL(u>n!RssZ9~cANBM_GU0;ztL2L<0b22>1O{~at49@gL&g2> zCBgkhRl!Xu?kfWD5Py{`QNY7rJ&AnUA-N+9o&IVdLkRrUlXy&jHF{_ia1P{0$m@2F z?&t@9LLaane5gc9`m2GAnd+|+WuE!ei*wr}=CQJ*|L0mSoAu)i)Q?#)&R+V4WJ}p= zX3IZ;s74=xSjL;Kj{0#b^3Mma6roA|xFmm(mXM5#o6x3b)Q^)=0)OKpM#lN1_yZZO zmW}J$W#cTw2eF2wI1>lzaoyjRQ5TI9ui$@q2Q_0kgcS7uQ<<7k98l1HX{L$``iF>u zK{Zyn%En&`NxF=zA+PnaY>cuT%f@dmu(Tt?xZtVPqVu%zIMcb6Q2a59KZ*FCA^yxb zEFqro^)>90@gezYQrA+Fux86ISu)<1(+D(at<=`^-Fkzv9 z+cOEIr{eqze3#uO-lzyS!{FjT#*G%xKzauHcRz5}l>H{a0|fAmgB}~%L3y21i?7Mk ziU`y=zcY?Jyo-$Iv z_m!;z2}(zj(y^O#%&kNw%u^Le7N?8;R}8_Wu~?_A0tsqN>z^uHLXz1kg0C3vh(YWLQzmg!zI_cVODf{3RZ6{&>#$ z%MQ#4z+?XFbqD4j_1=TKdcwdL7_uO$o%g;nGY^$32a0)Ar@!(symW{ zyWp4N@m*X_&11TO_dS6z&|>^tLg`@+V;A}NcX1Z^yGq!6XFeDZP$wEtCmL8YTc$Fp zPnNUDpZn~j(EV1k-^#N;dfq#j0X=bO{c=uO;c6lJqjRgc>X%i{T1K*3t0r+cjTS8z zf5B7W{iTZ3kF#fJBy!g(T*QCxio^<4?yvoxp(0`Gms2sgX)9kS4O6y|hDS(4u!7LQ z`sF}?Myg+?Vq#{77pZ=^1L>`4E2v+#!bHSj81>6r>=3k3=_sdkL}B*~|bUz~=Z zcy$=3AsO(3O6pm^tog2s1FrhzMnn{o16vgHE1SuI0LuTUvz8|Z#9O?n!6$6}vaQ4@ zu@;Z|<#wdE4i2;c`N9FCep&4_v_b2aUn?DDl#W-q5*|W2{OA7?ZIJrqlzB4y!$2zi z(XWeV$7p8#@>{?e4tS4_wt5q1^$Ywk&avlczQr8PtY6N-h^7N}tWNXRFL%!~_^IbX zKP;nUXM&BoW4TWewpWCMiSV;4g^ih@xM>T3N2*^2#WxEZJ?fX^kSIH{y|Z(bjat8a zj?Nv~-Z(rCtzSN!9W4_K`Ul}lRw3>nxIgs|i}yb(@h@#8w|*nc^}3bbm5rgTXS0B{v-gx`hxyx_{3=q z;`jdSbJnz8>n$G9zib1im3T^&pq5UnH=uZ!br0l=V>ZO!kNY^T$4HLcRsPHk^bTEr zd(=xFoo#weS$`A(3g`RuA1XE1DK&Grgq;#2O!n=AQLA_QHQwWh@0BkS-?a3Rr>p>m2%z~GHS^xGeIiCps|O328pdh zBYV9q8fo4Kd4g^n(m5k6kz&}ofg0|9=L3YhF99Oq?k|FJWIgb&zvl|g({67 zA(h%3-LXFGpbxk{>>|?P`Y?^c)AeDj%rn3BVf{;y@{vgWuQN@V)zvj2b17(~e^_x5 zRC>Ps2L0gn#k)SGS$a{art2oxcIEoiwUl@~yG)9eqr?yTgfC`cYXlUhkO|0~S%%cZ zoNxIY1~SgM)e)dpVQVRqb+ilVg%q0^UQ`j^l&``Rw$hO* zo8cEmw;J4(@H;@0^?l+il^6Szj=&e>#XRKfLI3$OIF1OZ@;3wADr~K0md>S`9QCn7e7J~|1+Vb#sS{FUhx)Id zArl`a*SExDUlgBY!6ED1vN*3y#~acW{j3ZRa9lSNq%&w(kKdHadE!E}`~>#`@eA;> z2ti>h(Ub!{m~}W$Z4T)wc(DQY_zW6JR)m6A?!kv#@z3&S8D_0F8MWS2W54ddX{K$2 z?$=c;LfZ(xUw1DYzi@A^DnVDt0}Lh5F!90~DnSt4tnkmJs024M4>0%Z22K|Ss_GSF z**ayqr3==6-QklV3ZckLEAr7qKA6a<5FY~^3ZeUT(%a>zf~>j1P>5afJp6v$?Z}56 z3bEu(wS-yni-5mu1#3&@2c=`wYBJ$rZswkd7AE+ADKFEO3;xRD=gI(4AfMtN(h2=u z^xDvqiy|CEKCBaSqWVhl?N2^|!fX;4Y!*no)BF7xXLLI!>VgbL@A?P+a^CN^=uIk5 za-`il=&$@3NpFUix1f^DD_`m@vo8IFS`OZuWHsP4Xam@hJAGH*OCUh z)foV_+-k^v!5~He)$K_81?Q31I^1fXH&mI7{eoLCy1|R}N=Fl=Bb{`-6-8de0Sde@ z+-emJQ6RV4?hV_N;8yn>cU#dWMYw(iCw_?Wq!AI)isk~`a;qWx1y4!X5s`ZA7yOH4 z(_uvep*^}^@DE)#9A{BcD09D{Txv8s8PC2h58*Vo0Zg*KO9ZFS47Xo!Oui0tKEr~k zw1BJ#?i25W&kfz*EKt4U(c6ss>W+Fy4$MN<@h z4)<3Sr!JHLl%Wf7E?0nCg|v&tuNztsrrz=15!)`Jl!kfBNW%#DIP|ZQ2G%=<12j^- zqbnw6YG|Z-$B)PXO}jw7BmFhC3-f*O-z;8~RXVCE9UFHF9pj6U7o`9NUKsU`Vi=-8 z^^O}}b8)~`?^yb)&4DWv^PJDff%e4gBW8Uc9H8Jp*m_47iAG`|9`%kxZ@DN;osCUeJRc3z}NO}L2L?Mi3);oSZZ1FQr zN87%XvpNUYi~cu`=35IW@YB5i3L~14+p)ULTkrV!Rm;yL!_Pb;qd3yHs*13?A{r-;;JubIOlX!nGK(XFYlRt-t3fHfdB14Ah*D5DWD@?s3&@(jO zGyPSB^OVX=Ha%5*NW7kK-ZNf5fFK~cYsBkb$1L56dXRo;@+ag*X;uI){fFD+0=|}j zg68v1 zEz)k&FChvo1rtS`jClR%L5mkxC>>*$kQYCocMN&kzvM+KpbQ_4hYyP!3bG8EHrcYH zMA%U=8O32oS1Q5^if|wiK1YPKqi+t-j^dzfF%#z5S+6XEHjCdDk$S}IbR^ymJ6ip+ zOq}Px(di>z--Ab(7XFj>!MkgfCWQ~dsj2{zc-@}h5#x0elHywKaDV^u%e05A$nknW zXuhiTo3QJhD<+w`AG+Szeulaqe!cS$yt}Z;=ub>Wj5D&cKQ&o;eKDo|6WSD!zg(uY zs{jgYG5QmSza&g5_h+v(~_)Su)?E1uk{n+oYazj_ha!>)IR{pIODYl1{!x#2(Wv-7$P-EYiT#7Vb9 zKo9y?U8EK@(Y(&^pUp7yLgsbdCmMP4cixzhK-2Ii2tO4{&Rumb+LGJ zC}u*)dS_%%NcHxgC6RYK{O6E>%YQce&a$X(N=J&)QT=0~sQ)a( z-~|79r6`o?KPMXRNtfV5_|JoI<>Eif58;_tN zYHY-}2}l`?_;#}<7oWXPkzUW{!J6kN(q4eF4dX4DTJ^kG88O@55pAW& zn=A4q>;Rf~R*+MsKYt%NzMYhiAye{*Z%@ABlJ61l4!>~3wGcqUtb%0`g%NZv_ zy5n0#qId0&GQJ&pfjW~MF}}4p;>wS5x4janz7b*nyF2ab& z!hB!z7fZbws@2~69=VZ$6gKEzcbe+e7*J3zBk;8XO9~nIdW|zQY5 zbIo3h7tNH8_DV-ZC_T<^`-{Ao3Mf19-GCtq6!@~nS~ix9z;};~;xMn~itxZYocLU5 zB;H>lLYh}CfLnnt8BQI&C=Ce+c5(Klw>3fxq)P{Ogy16#x1ce-YwekI6%KJmmJtf-$t0tVr?D)o&`P ztdzW=Kj=Wn9x@D_rhFEN+Az|ziqLxBp5JH{1+Vv&2C2eJ^ZZ9_=o#KORjUk1^C+P! zsS?tUFHqgSoQU z;%84C?aVY~-Ne~xJV&U3;ZcfD^#z^M04 z#+R)3Jw$MSSDW{bDDjJClUomAGY02Bl6e1(V03h)~mVCR&vGng8Hu#!z1~xdPnKM;#;pMA?{E5;aw-K)U^*1iPUBe$p^PKq~^&@?ZPd&~3Fx%s(ZhYIv99rtS8K zSnIu?MiXr7MNFCrwu;&X1l*ntO*8jdXXkrW8C*;=OS?)gePglhbtSpAlKdvwwjh^m z+XpDy)m;m0p03VhR+r%}X1Q{q(HPQX)-=Vuc_x_^Ps}$GGjpMP0Sad6)`m8ITg-Y^ zVuGlFG=4KBVB<5^iKi@P6-Cl-x;ijx5EvrNG8(^k+lup+(s8TOu^;g-=>H&x9QaTb z$8b*9Uyz_h_c{XI(z3rwr!sQFDy>&*1#Ci1$X~rH{Iv$|CQOqn4_T-&RY> zvl0kc0^=oy*6G=Bd_$BU#V3XjA;;Y63TKpQYGJvL|BDlMu0^|Z_t zeA@zONqjEwS4?~=$J7`LykdYmQUlF!&yIZO&VT4{7Ccipe`BpTF` zGQEh@1M0#PI{V=&Yc22T>E!0R4I;&3zfy|-inllW6|*=owKInhBfj4`;b}{V*85Tm zLZVGI#r^M_#NC#-`w=%KIYPig-j`Y-{@kMdPQ@-;-kFy{3RwaGfH1c=}d0c{|`$hoNlJ7{8uX&&& zgNRt~ng5hqzH)wA1L1|kQg2h-)fIO$;+}9!*hcyO`<2MoeZSN9;`Kf1J-v|;JLJ1( zDCKLszuSW$0~XpFk154oMN{| zflz2vWs}5HzX^Z*|J!Uihl$F?n_i~`XLDm<&d-Dz0I1OZ^N*g)(|_*mzyEvOsXzTN zq|<-*RvTOK8nG8cpJmXWKo_|iaO%%+#s=um7(Ax_+*X$NAMqpfrz1yq^fQmv2YUaJ zNRIk5oHA7XNtSu$Z{PXs*WWkDlu>-he*NU{n5jqVulpFTSP~Lrzv+k+A+<}huU38z zze>S=k319mvp)%QeXCi7G|O(ApdW>-D;$5^5N??Lru#9tnQHb|8hR)Vok_#yAB6^{ znoR&|mEA)2n_?Mby!V@4N5<<&HKQ;QNi~iA`b|(DgBOn}9eZCPFREkT5%(XF4&Q81 zGONFCrO2Tm`}MhlEcKTC`ujpO8ww@6B)t{k0_^#rANdEFI5oRIz^$^|Jjv+nlL@bq z04E~#*l(JN4A&9G%7JR#Z+erSAO7ZTOc~R{f7q`d-c)xjrtl%6*Z_b@6q`{& ze@w)o|8>?_ym(dV*!wbhu@Fmj=s)T36#S5r~U^39#Q`#_~fVm$bp^u52_9QXY>&LAL!8k)z6e*f9VuH6#WMn^`GF8^L!$B#a2>bk6_CVb(}x94a!aNSE3)hqNIQ@$6@`7!}&#p77crQrE?(m+dK z*8XZa4Cs{FJBoYZB;u|_+;PNBsr~Rdz(exw{t{6<^6fK7BOQ|JH9#a~?ysJp3x>4L z2umcNTi48Z|BDYGsV@N{lKP9FA^G+(d1%N-9G&d1E*?PHcrA~%=WdI3`6p-o)>RRq zegqP7<^YiSTQ?E}LK6AC|H`E>E-l$^)q28H6UnvN5M0oIZ#vb+Snl7!XV8eN3FWV0H|@^RIrVvw4BdhLQSATjqefh0n=J~-ISo2abV)PDmzKIj4 zG}E|OGyNM;8sCF}vh$Tnm`@?|^%i{%LkyFzM`Lg^U)ilREErE3{G{P3(!hM>(DKOn zN*3dUcfRr~@hxD8f%(;KVO;fp9eu(hD`_#KYfL`p|wVy=T6D@-dee>H+Q1eC2n#Swz6U zddozNe0@fuM!{ozh$y%UU=jt76Fg$RvRA$ildsHpkp3ep(tddEfa_fK4Da}}=mAsr zL*q}%)=2T^Jl=ll#1)K=_*LP5# z)&UCoBpXZdIA1kO*c*CcOxWY4+66Z9psv5NES1VK59)eE2F=clH@)a~#ot%)-%9+u zzZU$N@z{;L1>jiq=|No;g?js-t}2+6x!HHIgfQAXs0+U|PF9+Y4A=Cckbev&At}vQ z0v_-seq`}skJ9nuDDq+1|AY_iNQbWspumSj@F5Q8af-x@+OX&B&)lDP_FpXG?5$(U z_9@nWinTSdezTpkmt)E%101tYgrAC;P)TUEXJ1W1jTqE_NDJ(9rSP*;*6imz?3(?R zAYEp^UH7GHEwg5SQ0X{4lC$rRN(|Qjq{DalGtOQP*Mb#p>RG_qpX-@-_8-eoj-$nX zRICpx)-#;_zHOYn>_m?SIA)*3*~baZ_UsvNWcEc|v&YZu+0R2p?T~#1kS?>|q1($1 zFuD;zk0~8Tp6Bc@A-l$VcBI2sQfHrx+2bXFEtv(J{ok2+XTJ)oAk5x6Q|vdzI#98W zBi8S};_Rg(Zz8}k`()0(iqLG&K7O|$`(k)*%ieXS*t^Js9kcg?bea7wMie=BZa@#& zeK)TvnJI1@0ORzk692yU!5&?+ol-*AKS%bYu`tt!g!(@M6nrk+a5_dy3*?AXjtTnj zHb;9v1K7(lnwDD6>1acAv{?uxIG<~)OxxF=qjgRNv+=MyMr6_tDLXbnBOYNkria0E zxlJa}w3-ZtbH>ag%q}S2e@Ac@b%?hg@s0qRrYGkMyGNvg%P|u^6z7cI6kH-BN0@!Q z(_r_jcpl*hvzs0gc3Vf7z1v;bJ*-dA-$Z^ayBaOa%fxLR$8~ zgt{r&58|qlz%nhsR3JQp*Y9x061=K#B>NPz@@OHmuPVus1^rLm!GnN?nt+CyfQFh$ zeFiyCF|$+n+!hmD{WFgE6(OHL&=nI2o6o;n8O}@zsb$IKP7knbj3%5DK5qPn8%UBK4@h zS4Tqa$m%9Sdo-V~!T+t3Gf+?J3eCyFd8$8l4yXIriuP|Aem273h$z)5%FdN#s2dL6uXhw-+r$x_Pm9qyd6FR z?zNmiN965^oGOq7a4WI@na8!_gm3s13iJWsM1d5Z3RJak-_ZV`4IDVH{!Hvb{mDT7-xXUCSvU_e zQ9Nm;QRK;I{nyddm(ca!@Kur4e{%l=h!LI|^~cEwPKI|V-iMyD*;AC%Tj(ah`fnZ8 z{OKubSlTVMyt0sfks8jFS-^YEn{>uNX??wTL`{$f+i|@0n_XbT#Dt z%15>sYT{9Ul#JP-CcQeTn#{J;WI4EL)gOh4CU^Cpe=+97fGl_F8{n@5V z`16A~-JOhb53HsBlmV2jKZiO98!ynb3sOHQ(b26xQa@Ne$E`m*6#3JNyaSOR`$CXY zf3g8?xtWj`EE-Bck}1sQ{+#{ z&!!8j#fyl5){B60iY!)FGJ#*gmD~?taV0PFM|36D`BY;#rptk_fY82!r$XeGJzd;c zQT5h`o_9yohh-l6unfLjm}k_JMozc%AxVS(uTM}PVqgVW|9>tl@!ba~TOYP(6iy$` zX5`g}QZk~$pR`cq{T2BuPz%&^)(CRy!}o7G^dY34R9&KzOv$63G#A;hLm$dx2G9qi zo-|fCi9H45g`1h{Io^;iLH}s^Q#2x*AadT+H#vPy73a3-2tI= zwamsh4xqBG;(3@wI0?1wy!~x?Q;52ETe7tFLz{4YW$#TTD(;zshPjv8n113QWf0|Pp3@3i7R`6zKWBkr!mO?f>c;34vQU*d#^yc#3bcF1c^ znk6q}YYiA=Ag{)FZ1`C+GN;OaC23l<_yy#45g|e3R+B%W+??-^sC`u=F=}5Jj{Dh% z)AE;JZu<|y=lfyp?T>a&`Q^ZWIqmJ7#Uz})UD3t6AIIn|U|d`N%b$i?Ow z4RteE16E~tlP9nR3$?(dp#OgeJrYu0mTDW~-xMoK_R~PMb^ryP3!dZr|78?(6F?zK z8uf{Hp)ZBpZ`{_-5cXi%{vG0a>+ZW(?fS$3rJ<$L(1$d<_nFYZx9%1I)T&Q>EqNcD zn{lk^Df(fF^~23cN7R-+NQ!khhCE?|X7vQ!RCu`o!P=bRU z@2lwfl}$*xYkk3b#^pO`Gg%OOKdeUwnd{NknXP-sn$$ZUUERjC4apz+h4{0M8pFTu zN1E5MAfG~-ed13nf3~)*FvHL%;kaJa5^--ar>!MmD}OkF%n6kGe3X!Z2i#qW9}D5sJA|RyD78y5P!Di!^r;Z4En(k4#b}s_14q> zvuwC#191ZWQ++AutyIqLON80J?SQiV*|#Z$_Ggz;3}J`qpLh&|oAuTNrD34b(1tX8 z_p#8xdTRMYtUs61cy7u}qwiyEwqr zpXEKD>{^LABGQS1Km00qA(B{!KdT0+wch#xoisH5-%@V zW_j7l_fV0qeUQQ%G)Z{*%16RW|A&AI?I(Pzb>4o$XWx!wj|JGj-*KyHn^|g`C={n9 zbcJn|c%QbJ(RzjSTFKK4-mjHp?BA#A{aW1bPez%T+xD`NpDeIQM$_xcAGj(uJzoBZ zXZ`pOcw>=&P&csewN1L=E#yS?-sHr2M#%|_gcH6S)THC#zvF`b;^2XVW&55g8SqP6 zq4VCjRkyXJ(AGx&p~=*0Yb!fZ@z3l<{6mSq6!G)Mt%U%GIma_fw{~x3--Ah+8~JtQ zD{CX)zH#e2q>83FOT0~1bLQP$_Dll4&Tm+T-ApMes}v<*p%e5ET}X~x4=7lGv^JnL z^p^L*y~1Ww#0~2`tqeBl zhV}YM!XbOZx})MvQ@noSUG{-+XaxRiItAbe6G_~#J|*bv4eKJtY{u@#^9UQ(FCghg zm@x0$I@eM;^sbD=d+B=PiCG|nA`O=aB^(;75M6O@KOn4)nI8K6kbYPPGMFLIq;d#3 zTtaT`LdMxSR{C3wPFHbm*x^azuJ^g=8iuO#CkR7l;l(8kC2%l%*Sp&BVjye1afmy2 zy>nZFkp7OcBS0~eO-nU5G7-#KC)_QG;19lS0CxaJJAu&j=x z*fd3~c_!YhiZ)9PZDzK`i)5vvyV5ZQfeigd?~xZz0Sde@7M86sgz1kQ<&?Y&%Rx6= zjwl%m%Nt}AM2C-qu05yl=Sc4yds=H{B=?yt zJR@pCb1|^Ud+25^C;wXO&kV68WHl&t+xKhCYG&F}=zeI$w`fb@-^chH{#Lkc?1wI% zXerI}x@@d-A7vObMwI4%@5oerF9HgjGxkHvalQrL4{efU>5jD@nj|AS6lk;}f4>`% zzcN~oS0r*OP-%cefl4vw3E2#CHE5itBWCJ|-*Ut)b4cU=IAU5ta?t;46Cn_sUn`fSlIS~8mV3}h(X1>UU42tvl%8KqCSn)*o}I{)fnBVzuvEOG*LQQaar@$ zZ1Up5^W=pQCaYkG0@W+pHMU(H!sHSe#o^_8DZ=%gIPvXV(KI4Ldbu$Gk5sRCN`j7v zbfV~c_rV;+W z^kedMn0m#68|k02{(tq<9oL(>F7?z?kdpJfi1*Z&W_Kj#=8$t|XHireMP1DO*g>3& z>W3qtiMYUe;|5D$tf$I(BZD!ZQ)(Y5ZlB_=L)^oNn^J2d;34NlY!x@J^;8rh%r>qI zRy%n|uK_>vp_D?TBUkbTD^x^e}u*3ML%_D68^rX^IO=;MN-4fjYGDB#ff0_Z%Nd9RT zVjO_;h#2wiQt7Zg^CDH-I24=ufTpK&^Qk*vPj@K4W(912oTeZP^V z?ovFR||DBJ2%0%+((E9BSP5*Qsoj?53 z19)Wlr{Tv-(m!?LL-?oq02BYzo!}AuQwm9O^^0)7r<_dQBlpg&+NzN8xk~*=`X4vN zTmRwo9r{1#X-oeD8X{)jMVUVhpCk9VQRc$|<g3qW^eg>Hox= zH9mLZL(zYLQU3`ZS^r5&82y*Yd+5Ktf6xwj@#d6-RHPbc;#-?GDJ>y2HSkaCNg3^O znoWo4K8imKVr!vgOmJjYTd|i~mzaCJb`xC*sdG;ra^|bqL z`7ATtPRo8|7)n%kTx*(il7=+yCP;}Yb23f3t}dInqo8f+()nO*D@;Y45H*+}1?hmV z2vo+%How+o$)-CwfwzzY;#@aQz;}QX;3>mci!K1^u%VEfj6RdRPcv_OTfxk{ch|Kn zI~n!7Abk4^GG_J&RMYj{gk6gM4n-eN^h;h7{>fpbP45LbbUU6a>}@O)^Q|2z(OhB( zfWBc~i{&e+((njQ{F1K+?#vm5%-8hoP}NglqZsult?Hu}J0c0gm3U5m@3na*e~*lWH&o2Yf3HaIRHS2wbmsG=J z7UrzU|0m8@X8xHx&yF)@jwE%zHTki~d>xZNQ%5I1mdj_~cDv)_C#7RuDktBabTlL# zzIV0bLpBPa81peifhPZ5ojjB8AtRyuZBG7(B28DMztWvAf0dKRteZ9jI3}M+$?p~| z)AF}SzNk6*74qDgJV>)AKOU*2WAf*((aDd;FM|G&2pehA0XiO!k;|e6n;s{1ceoX4 zw@KaH2IrU*DMHtBa7?tmpHOs2B~UXsI<+@|v#$_O6BS6WmK}rp4=_$US*%=*ky}ga zM>-?Z1@S=WAjUxpRZ%yWXV~ZX6Q|S~^=%$eT3Wc}aDiz782zL^$ zh=+pZU9aTrAI(WH#N8vo>i^jAq{!RuAN^f%XDaTYTL1W;;ARwiO~6C@KP1R`^?x99 zHf4+itURc;*DEuo%Gi+cTww|OKmOFn^(G%cSdRllBG=mlg(q?Kf5^ko{tuaFe(RO? zn?lzs9_NidTGJ`7{g1oXmoqil0QcQsW`pp4|6)3urOWxx znziyzAZk$!Q+^23vUdc?w1j>L%$F}PF!yV{q6~kLmXO6$#j}k5fUZ1Mob3dtq^D=d z?^5vx@)lGA@kg@!fsmFC+m8I^{~GvdG1Gf+9t_l?(I6|b@6xpK#BCJdHHff5|Gh7P zO#xpiKp~-%kQR^qsQ5zX?0?4_3M93~>=E(iS>*B9+Wqh`J7@n!Y3Qdkyp2GI_je`< z4I>0}BtT`eoOf)!9A!9py{f$$1CZ+UVEM|rsy*I1UV9F5M@Pz}^bR2F?UQ{L>?Ma94@}uO1M7TKYM?s!utAb}$@mviT2jWZ)prfJH`xw$(wH#8+ zeHHUth<4a-pGXb}=yL#-eQ^reV|If;Wgjp;yPk^!F(6+! zaJ&2h=O18ng9AsDjvtfBfn``rY zn&h?|XmQ}I(sAGxa^MU((1vvQDgg={NCgK#+}dj5g7d`xyq$1=Rx>!zBViC?$gTkx z#S!!WR)qZ(;br~{v0v#Ee`0PfMm*8 zpkCDwmNUu!YfH-fe(K&m6GR05UXpT2(%PRtXZ{1l+L1GDtFr}Tm{e-}R)wGg8Uq6w z0|OcZC%rQgbFt4J$bbLnnK(0M#)s5rca8F_Pwj@s7L_pek9zgDG`m7y&a#NkvNE=j zaQ?-3nWe8KprF}Co5in{Y1<*ISWi!1wu)utiL!b#J-wLjPYx@uq%;g~K~BGh?VF(g zw-$qU^^0(W2fKFRCdWXKyAQ z>0Hg-Pda=P00mwc^{E3Qhl13nN>{e5JP~Gln~dVH@*0Y8j3PY5mE0fWWa6~)3IKC5W=gHS$_Kya}iRMS{jmW+9Z6Wgg=lrJb%la&*k2~LAuQ_+~<`ms& za&q2S;iPX3K*c%p{l0k4P4&fbbV|hiq|~b{0b2V>12LdeiklSonk3>LO5Amcn^J5g z;34_`(-J#8^8MmSza5f$qLN6?aeu@`h61?1BKU?W|3~{u;*V27|9Rn)NbPIF_{A&Tl=9j7bIb`kFj#@7x8O<+1#to>KD^a*!F9hZeIN(|z zIO~N;<^*m9zMR_tNO#=aBtBM&?>59DzH}8js(WuDmotzTBi|TJ;u`}hv|hNgVxD?o zZq;)xdXhU@=TD9Tw7vq3^CuUGlZS9hanC=#JIi{y*sdW2De9L_nVesO9*VhuzFFVFw;%5xy3Wg8IR8b@2c1@-zI&2m*(BA8Vd|!D_;Mp^nvrS@_E+ z)v;5qXL&k|tVrDi+qdT)-(84!@Mw%_8xjxp-|vnGx$5e!YfOnANfU`q!F&L^5TI5( zh~?}G9uJbPwB%~VgB}>r84pem1O z{>KTnQKxEhRp$nZ;a2Q3q5pBX%+A+KjoR#giB*xMKtN$@p4cw~Hw^!uv zCldKOmXInEId$OYOd5Fj{znOFG9|D6N92_bedut7dbZi(5_qP^d~nn5e-yWl5yy?h z_c$+`p}9#@y^11?tn+!@w#(sk9u&=vZnrsKj;buJNu2^ z)K>;7EA6N0aK}DFWoRg}F!RGAq+fL*Z~Z>+*+6xDmM&QS;7|{@KbWbwXEq|=h7xxv z;-)Sv6z~v#&`pAmhd(%qwA3m8a`Xqr{Zoe+NFd*%!V+-?wFb)lG>7;RqWwewoC)3$ zeLxTXtDvR_Kg0;A>E7&e`I@)g-;9z&-u;!&OFQLL_dd6LVmdIpd%7WcbmJXjtjC5? zKL2)e$R~?)D7e3#P&Ti87GOZ9zb>!1|7}3rpJAH?^$+5vd`1X(hxfUolA=`Q1@!n`t(ufA)$ys=T zQuu#AOiylfD$~ESvL9zu_TzCaXJAXvUkgD4Q%=<1== zlM#S2GPPLr6N3+hY$xkc+RzovT3MErtW|2Q@fh69TDK|q zBOQx}kQciF1zyC%uOVx#k0A^zxJ_mE7hMUb ztJosbEpwLcXJ&=of_%h1gfMad9C$rN28l_(@sM3N~&nTkr1DH%$Jx+jz=5jy|h z`mMe9dH25OoO|!{{J-bk)4{74 z($SUAg&5Bj4jEH`vTs_a1<8ej)RyiW?Pvmh#PQB>@aJURj2Tusj zu--gmPige7=z6mo87U1$&r{XM48&llfxIblIv8(P+P6!<5EhNXcp>X!#t&%LN`SBt z<9J_T3L?=Wk(N}FMrn*W1}g1HG)U+3OtDv64i3Vl@G@SpDXm!v_GYCIp|3-yeuJGOdjiwmT6n+iGJ+lm%)rPq95I2Qi zLco3f8|@{WXnujoX57CyinP;k6fJU!z@2{cgY?7~k^c!xB>&sEF*iGJ_wxZNyPp6= zB>O8tAtSSYW4AoC>$y(4Fgqt@6Ki?5Ex2Z$XZ>#0`;rwA?!N{J=~Dp6dS7D_1VR${ zyLDq&#U53zJzknzOQ<6f+xZk#>_juMSMT?be#w!s-gn?JPyP~IxYI*lY<;>R1SD=h zP#)1IwBh}0$KL-m5PW?bshfk04EI@+y1*eZW@kOI1Y|kRBrEmieL1}PB>g25#G(vm za!p;>(nKpoahD_RRegjr)Td4Y?#oxNmlzczUwsW}vY}5oLA9seJifmS4=*uUxFRa` zLaLN(;U&iM2}Ib5FxFSHx1G@>6sHFbe7S?4A5nzh}?FL;@4lA@Jc6 zklxhf?87E*xOqXD8z4jU+tCu#P|EVLu2l%E&H!bj^s** zlP3-icWlryulJ{RXlNTRPCfA4ty5BRR~#y@mu)P<|O+^RA9?8B*1M~1_XG5 zOPg_@Qc50Nxtf0FJ9Xei`4gCZ`e}9G34DnT+`VqK5XbcNi!;MJcm+(0nc+D*75d-c ziOwGX8QWj}d+AdZmt940 z>n{T^ps5Yz6?X~6otwDF^>nqNp@94Rpv6h^?e1b@9n~F0{v%AL<2Fl zE$TlIv8>ofCbOe;`Kk@J(FeID)v;QSqX>_6Q*`5kD4ExWw zm4;)tkcI$hXhs^iJ+&L4?)FriccDLxu3q!VKj=R*Zcmj&zU%l;M8b&|)s3v7|CF7Y z%V4x|6H6f(6WkgzT|I2&1}?YWQ%dhuN(+`0ZoSu?+{z6o+ry$1kN_l(eJvG#rHh-4 z7eq9>=o(fMJnZ`Vc+c3tny(1IE=tzSfoUQCAwq6oy$W!51Iu^5f4F#l5&BMg*oYfg zxsX;H_SFxJz#Go@7U4y=Ua0LXXs(K57q*PVc(^Z&ejcWG93WzPjnj6AtUTR>8Aw-t zu+0OK-1sesklG7nS3lq+(n3+(YLIC`}}P$2?a6y?KxzBhCX!p zoBr0Wcb}v$hs4hbOC&iRSyqZ7C;2Bty-5Jfg6LU&p#9H+niY|gj7N6=^WT(REcdxB zxbU-V$m{d7ro2``?acMWgX;Q+6eiDFAY()Q`!ULEB0ybvrE*SLkB{TdXOvfM@d!q? zl%lw=TExAVdf$_{DX)Nl`{cD+qEZZb)en_1<+b#jFFw{}RD;Np@C!xu=xRGY-oq!5 zT0kRTo0hJDwpT)1DWNH3(if@1Br6e6TK^U{`{H9RQtOS6-=E7=z`+xx{qhahzuD7{ zG8al*GbhuLt(eCDteY+WNsHTl8ide3n`^DhX-~I?eZwf3RBtu9tsx2Ysk)m#b#~D{?fuB$?FDIPHM$ywD8x^&*M##Mk5Yk_0}2s9N}&lj zXF~>Mw%$mtWi&I?KWi(|Fqy8mXT2>3ch(z^DGkdDl7=dzp%iHto`Ax5WnFJ*b#yi| z1X<(ZLsD`usV8EGQ=%RtKe_7-ylEdv`xE)A6EBehcRHg%p^bp2p?lfo#p6mxWu+qy zekf$U*_ph!Sev}Cd)9Bl5Kc7ouedxMsCUN00Z-5Rdl=H;z!Qpj=}qK78mt-pxWqhM zde)x9}3#*o69c$a8bgaf0IONBXr*TNk518J?nf%bnX2kgy}N0M9) z3{g5NC>^(wj@LSp1JwZq4kW=Ipm{f7h%9lS&R-r5c)D4CtsCaRFvYyM06FjhwhBU4 zQDWw*dnG`@fh2N3H%D9!bm?MqKsHCh96(D@m;>oZUJVYk{Zlz$Z;s3luewJn9p#jc z5Npn_b|42v>Z&_g!b-@>k0G2@cgChBu2{2)Ky&e^Msm?FF|t576^nqNKL#?I9E#$RfNaMbLwMKYWkg?zhb*?&h*N^6n|j zJWU;anmYP4b@UUvr-nPYJ?Y%GV26kO@gqk6!mK|)yqnK0so~8J`fBKFe*<}YKiZmb z-lRQ+IR>C^evrh;Wj#OWdD0cBo6l9pfM$NsUvVD_5cgNi=aPw=`9Yk3`|^Y7;`L+X z2c?l38~NOn6Cz7v{aln$1NlJ$eqnwP-`vg*3iAoXc8Y%0`txqsye9B3D52Gr(21h7E%euuo%|rm zebt|(136`!VC;WMk5luF%n1tATMggGoFIJvKJKf&5fqAf*!}x|faP}FU#q3Ar2G`l zCC+(aTPnt85sX`BEQg81oU+ru-{cQlIU?Mz@;C-}eEt_o!`ghLVIXNJPa5d)Y6H|= zC;RTJ?#s}i`Wmf&{{nJY!{c=is>ieY_s52L@ukvHUFis*bbxamZODsM<%Qk9e+!1l zlE-Ttbj>3XtKeH?6eDxqst7mb<-})T^&PVAAVONkiT}~#6`{wQCvpvYyg?EXM5HnL z_pc&HHLRpJv`72*|D{)j$Gb)p%IV*~GGB{?=YN-naB$xOOdQ;0f@9Gd<^Cu6+1~H5 zcZ3tf=`Bj938caVuz8#DKK@&J`;q(mZU%9}CcD3H zS~XYmXQ;I|x}MCxliB7cttjn&fC5|W4c*G*hw4~XHgsG49u~T@p_?Eh8j^oUk$;_s z$d{sR3H1*mr{vF6rQ~%(*I)m5#FqR{TDnvJ0Kwq~-dxDI4axWWO;vujyutpyt>C8H z-*;J@F_<)F1b#<6qi=@uJSr?lJVbwAjwZJI{E^R~6pIOE{eGA0K0nqu{e2zhv>jH2 z`bSG)sI>u5TL0kdzWN8zd+Hy&->~;@)So2iPcrleTH)*OJ5e<9_q|Yb&)7fq{85nL z#>c}gyz%int=-gA+NU7z4O#PAP#IPL)Qyh`q+fMmsch4hyhywBs%dA zff)me#FrWYQt*m?uj82fSNe%eWcZfJeM9e?YB1L1njpy9@Bnv78Coe%|9Wlf*jpw;JjZSuwL0nq(%F!O_8eo z=8$>DPFJ@DhvxRg>)?T2p6^EmD;3S-vu`J#&BFH{em>;LH&t`nBw2dFHCX5M`-|=B zp~NQ^fZH1Qy@%%Zu27PG?}3*!AR6jD4u}CMkt$%yTt-WaMz}U&6otM`--VRbV9)&^UDz{MM&c(6rX7&3 z1Lw5;H_dGJaLJXHf?zU;0EcbLN=D zYk0T0=JWk6S3Vtfkc^kYql4HlyWk>2O(1Ob%B;%Z&)%r@xA16&~C9=tB+=kF{2JoP%K` zK$LxBzsyIgOAXQ*CdkrSoEdValp=EFKn1ySAR*nlM(a#{2#*ll03%2U9>9^pb*A39 zvBLMghMK~ItbVV-&A%e%%Ma}Xxo*C^0}5vLL*85r9GYlde}z)qh_o5>JwPeGC%Wjw z+tWYEq&1hym@j9{rHbr#ZGrJta;a8o3n&-p;m2DP_r%M@-H5m^HWJ*7w`B#~*ALk^ z1wU)N#bh(~L+(QQYQ)?7L3OwvavPm6B)Cgh0tu!c!TyPKvwgz{5Rt?Q5z!9>WtJ5F z9_nU!=7nC$LuNcp@0P**<9IRlLx zhLJ@*&pvpcS3c5T*Z>2Xx$f7B`_v`k-pgFK9dT1WmVo>6p#|dUW8_2CkYXG1ne!v% zb6vId!C^2-^yf2DKq86wg(7;VKpy-98}{Y+1hTnGcWKR%NT>C_JxXW;CG;coBA}nS zfiTG$3@9#Gw+Nek^}cg5lCR$P#gCZ^H28K6&-y1gw6-Uo%4+}2^4%bbmI>G4IUh4; zv9LTP#`&0Y+y=~v2}lx@s=@yNBw|Om(k*G%ckv3Xz#sI^GwM@sR*2m63JV1Po57cC zmIG_=wRLA$nIvojdbWVtVQ?qbl~Wo%`iJ_{gESN&4cr2%0#L*{Js&em;ay|m{s z1`<{0QSy_!4d|SY`9A&k!{Jy5(`~ayV_hqa^n=2@sH}99RXYB|@*MrE_mdY7D=!jY zM-m?}gp+>xH^Dp?;@`W+!vW70(0`@F9Jo_4FT6kwj3(y7#LR-|E`WjqdOl_bqrJ<4 zM3`zJLy4|7+^uw!Ryro2Qiga|j~w_E zP*`{@>~XK zem6$0E$SiBM<$*o&m%9BPa+XD+(?IAGV#Hk@Vyv@54iZ#I|V~SnHpGz^D)0y*9Gw} z_<=>yl>il2{~KSStG~I2eLg|g!@K1d?|PX1JTrFDMfA;TKab%LMxE^IoQX-rnV6n1 z9}E-s;SLZ*Pf$TUL4qa}6Rr6l(i6nE-$6aWMfhc5+91{bAthbepI7Ht{yardfX;DB zUCO>Cpd@=y?GKP;+1ePWx-+^RTqqH?gMXBUx#vj31T-UIzm+u54!#8_>_8ikS9tB9 zEd!2v0`8K!o*;a&&!K}JJ81fY+QE}*2i>vcu)X3{rK6bAQ5~s2`qu9wFY4-&$le&Z z218`Y4ibOx*ukX=c+aqd97%M;AD-pJHzDiCcQ%QTcJK|rwLK1Yzz^_-%SD|ffQd-C zVG!94jv-An?4Tvo2zDS1#tHbY-S;wweLNDC5B+fBd2z=>JM=-(3ByXhAxLY`unF(v zNnd)mREH6MSMvw>l*t5znY_t(N;7dAjF)jpPlGY9co@2a29g?O!yve(t*72#*hd!X z3(tRtY0*}Cs;!_EMe7U8KcKB7`|Ary-ueOz&vz>%j;8U30WCBnFtmOEH!a-Xq#ZWX z!b+5)Y3tt8l<6d7&bXJhHkGKKDv_+KA%L~pMF83QjO4G|U3GHn3ngUG@tqQ!u-aVl zw^97@#J{1I;O~@xCFGyfDZ95MPN)wrA@gEVPJsJEN)K**0dLy%1<7cgpaQvvz;5ti z+!_HlJ|ih>#U}V|e8UR%T5-7ecYuzWETFhorL1drk0{A=|02uQBH@SqljOh_K*0w| z8%mLoHC}{k7eFGGBAo9`uKF$`qlU>)Mj@t?Vy&WB8xiZYd&wwi!bt(RyVgGFEk*pA zq;na)8PCIOZKDb2+w{kgLK}?QyGb; z*!)t#gaTbunAc}_)s01Jtb)rZJgmf5eW zl1wIi!T{xd=WeCAb76vXV~3gGDa%O4Y%pQrH_C*^H9+OR&1J$6rQ^AiWI{p2Z1gYx zk4*UORx+VEn1F|=7$Q4Gm2uzLOwgjrbQx@XxTrGBp1~+{3zVzlm=lOa{H z+~o=mt>jtn8SyGgf5-l>FdN1w&?_suB6ftaa=a^&O^MduaTn$xx@7lvi~>M93H?cVztU&7!{j+Rcjq~+)Os2QjG%i|yM`7gEj+H>BW45T3*!>;vV|3e9JfU>7QaY;8TED1H zUW`y)*lFCo7$Qq)T(2#zkC6V3du0?Ojq9TbkEV0tYq6-tc@rXJ8kdg~k93?;sb|gq(iNb)zc&B_no_)7ahFisxruvRRl!XuHWYAQJ?kfl z0Ws=XU6JV;lH0jiBxm%mwPy_32Y-!U#J{C~f4kj)(S}bTwJLIT5o^*Uz;ghRG6aouRRHxvb>-F-v%J2eEt19 zt!4Ddl~@WWsJ-34)0BbtC3}etqQghJGyFNXxeO z^Yh~`cR#&25i^PuM+I`u_KV{r0#J>irVxBCl6Q_wjnQ4qnU zX_+K!H{AOcHKl_8#oa7AT=NDxvoxu;KgVRmiM3K!I6y2>nNdm~rDL<3;A>*1Oi$9Q$xz?Hud@$;*M98M_$pCjNA$xPU%M7Uqwz8)&T9!QF3|qM6USz%>`K^;- z!YUerYD|0_gD#I-zw^0aY&*s4qZWeNTS_ACah2ar%Q7|}@>%=0R=Dq+!2yOi2LMt{ zY#_I~!oj8O##Q18>APlXAeQ%8Q|y8l#3-lm#c&$>avw7dtsz0T?H4pcP>|`NK;)Y- z;_Xvwf!vL^1yD*e`)P9BA(~`Ws=;-+uyF5td++e@NcjCgwvnX2JWyR2ipbpBH2*f%3oo9`^t{-t&m4KSGwNITu8CFV4Pj&o>RY+RK*X2wyqHtps-fq_&@K}F zV<$WARQEYj%UZum(xLqj|5Is&4pCY)P`O9Fp&~V94U-P%;Mnms!rjak7#{bTcde~0 z5e|-Z#^BBZ<6fm_%Ng@VgNQVQh74tyF{17o8E=vwbk5CFg!GR=lfOoQl zt)OCMn*(zY@x#R!qZsvl`o~C%4Gxq9`NDy|nj`#mt;>N9O2?_6$bqkZ77nx{9f7X_ z1rA6>4i9&IDt~EWzBp_J8FPf3t85PF!Ld;?ijgC9R)oV8VQV7%y^KtpIYKLdBS%0L z4!b2A1W$OkBvImuh<*W{N68UZBJVYFgtDL-%j}_u6wO1{3oDKMVCn4~ZQ!HW_mF=| zGCm6c5>(6&jEwJSeoW-`+cX^*Mo8r7E%C0T1EV-bI2{<;-Ao7CNji}HDL9kGgJtG@ zS{Lb|5%WSTYNMa!j0_B7FX1n?fbZb%)=vc>Rb5=p)l%Qh`zX~N$d+;6PHCB>wG2?m zW5OT$#LXa+Fp?45yHUNXKy1t`2gjoC$u~QJ%4)EuO>bF=(Rz?FL*C~4gh6)Yd`*A!uAP%mYlAm-qimn zCcGDqjLFG-E8XasZ|r>R=cO3i&ByjZXU%@AT{_$8dpX;FNXt_%utYxRT?!U??uZv4F%4-n@H1p@T6n7uR-H5pNm2%}ZT)=(uswe>}hP;*` zoi*fj8>qJBg=*s>`gX``nXm+|F3iaEA_dfPX7eWqZV-UQw|&5uC^vuo;dS}R*DseU z^NuY(^rz?d*qdq3c@!P$03am21pw*qt|wU_=P<*C^+Ofczg$(VFTaZtOr^z5DJfjE z76QueU*1`g(Z4)-v&X*}`Fxaqj{S=Wl}Yk%1eC+zPKL5oY1qYU zo&sx`quoauSmwBVxt3%o5&Jn_VyMxDX0(2e0Fq@RLmBq5W++ZSN0=Aem5wG##{h&7 ztlx{17j=~vb`|3;4B?n(%nT**shyyu65XUJkgF$o(9JkRu!BISOhN?&tXXBbkHS&vAo}Ck4ZEbmB1Fe+gpra}=`s zIfDEFX1kuCFqAC}I$nQ!RDSd}Jh7i+;bIzXYP5ci19_s_YdhkD$A1(Qq%Q>^?X^AW z0U3$>-MaO5*IsWfPLDh2d$M>57D6HG$SopM>vF}6_WIYNjP}}Lf@eMMy0Hg?59c%E zLGwuGQ%f#%Y}a4k-Zn-^id5eY!5<34{7D={q3C4oix}RIiWy5K*3<` z`t}4&#o6=7%I^O1MXs*8-=9d35smuxVMSh1kuRmCzFt(gNrgT0pIEA#SHp_hcRuxy zgc_OBPAY7~^Qm2twi*h%6THJ4<7UenJfB(tPu%mV9qbXujKJ?W=fqeB-KZ}tmpb>} z^w}@x79JoU;4^5*4TQ4lUI0TiV?3>MYW*Dx)oBiUNw;Bl|v-A)(&J>8Wdp zKI8e+Z40U1Nzv-zvGa#N=R5i$`(5e(*7D?gRaBc7Y$L5Bk$U004QUOm1E`ztO(wk; z$?vS>d#gTlW$)&Dy)mFE`$WZEMRDgQ?rAr>vaciHzWgC5PCQ2b(0_$T-bWUg`9p6; z0Jx$4cncF@I=9V!Y{Jg3LR!{Nc%={{AwlpT2lf z)GkB&WqiefsP4s;|G*Jrg0W?fLk89<_mhgKl7PWz71Jxp^O#qX4?+|WW6`5FfmP>S z`%lwV?fbm#DewY92kvnwEMf>u0hD3?qDl6iXO`@LzN-UC&iV8t8PTx+R}^_gMV^z$ zU$+eNE zR&zY+5r0SAVYtQk3a6h7ND020!VP=`^Y5~ru-+4gG8saxqtY9jl?y$%J1Ie`ImdQRHc z=>2S`eNVn`D^i5}J#NO}PTJQ|X*jrrG^{|@h42582Bv){|2EP-fBy$#j;4K4`#(Mr zW!jAWf3D5Pyr;@!_kaA1<*Ch!E=or$rQ^GAg^n+7A}?0SBG%o!x)(!aDedd^o@+{p zNc;N9D25evSA<8u;>0@=;X_2oC|V!j?&cNKyKrIZO>y=j(pdc;NV| zT>-lBup*kAHc@=jb#eLy~ z;NEwGE3dl++_!&NQ9_%_D`LD_hLqWm*KMHM)339jkPMG-vqZQeB5PJLw@eJ*Kjafg zYB*u6l~5NuAuX(gZsy%hffN#YCkeGCi&Dvju@CTd$k#|n`^!ka^JjI1F`3A>SpP`* z&8U+R*E0{za^&k@&r}~GLXEVZLBGxi@ay8X?0%hui*6+PLQ{&p8>kY0Aqz+UdqDUW z`1c=~t+Sq4`;PGNBE4T$`gM-IvRMs-F}@(;{NqG#Q;VE*!fUlwX9=yr4N2a zJ5>Af5e)qS0Ev$tL}1#vzh2gjLwfu(`*kV{U(z}yMO&W)JGAxOzY**Z=keFUh2^s0 z4@%B(^hMS)v-5fT3C3z9{OJqz2jqW)d=&mbfV%!*{Y+s+*82(4XS%Yd{}z8x1_PS1 zAFsGODeenc*5LlebJ`1!COzIyv3zuS?dW zzpnW?<#QW%cjjF$JPLFNs4JfY&OzmqmHx`)85!kM2m_k(xm9tmTSwgQqqQhxRUmHK z=JDSF?vu|D2_-S)lMBhYA)kJ4`~3AKdRd4l2Y#W59?fa@S6&c4iN$@Vp7_~6Tz_3f z2`!|AR$&$Ig*?I}t2vJ@ibGOsi(a1tfZl(*IM%Q zEO*CtUq^Y~4NzB}%}H+7?QQT|8RdEGq*tDIDDG2hi2GUMZb#gd=L!M$$#a3kff(|v zhCJJl=bY)Ly;WuqfiSD#vD(|MxuHXq`6ncqi=!I>w5mR!z1<_ip}ke6z}4PPPtR05 z*x$p&xyF`XQd{?X;JqN6w2RUihVOyTkT`?M<B{2Sg?x6zxefq(c z@(IU_@DCzdQNafZVYOuE1m3aphUMzeCVWN)m&MW!eVuV4T&n^>zn9O4%ckV@7|EqD zwmx;9YU*?{W$0f$pY!6G(p6<(oV;qkIeb5f^38!?DBq_q=2rP$5I)iWt7qT-i!0xjw*OZ``*0EZ zLQY|lH6Kvw|M|LCzMEtupL{31k-2=EAQ^P6ciT2|KeGmjgRiIyeCfB@S>wG#j;!%U z{Os#bxCf7n!SK)Efd&5l>=^6w`=*%sv*Ty4e;A~ye`y6}xD(yFA*VsRv6Iq56>y?;flKrai`}H+|-}40`AkFni7s;=+CBE9{s5bsy*wy z)wyMO=+AoLiui{~^RJbOVIPrC;2$Ou#@ZgvAI2)7yO)zmSGlEJmxNmLo&2FKU-#hD8Kh0jtTz`E2A-JZLN1r_P$i5j0+$e58IN6c8e?L0uNtr|D`_a?jr)BMA??)Gf zEbL-jKQ*Q;%gBr+Xe$a?RYUTTw!pbVVoXk9@}pO?U6|bYs;xD{$|U*sqo-nUr!YBC zX{fI>R3;6J{}UQmn0ykT(e|VNpt7twvmoYvbTMH{^aE=~{0YB&*A)Sr{-_lmQdX9!5v^8SA_f4G=jSMTVssm zI_+Ru?QHn#S0*^NE9>zBSVWoqWV!C-datpPu#=VP<(Gwo!13PduBq+5he1F%qMD8u8?wCkbirwE|sdwc3 zEMmRw=a(IM`Ri>by9=Wt)!WcN@IO#4)@b(+)cDbLDswg3^jJ(b*F{$_?kBrM5#I!; zaJ{XmXi7Hr4+l(eW$gA3tl#UE@%xHA_z{tBL}xDQzeG+MzY1`7|IpVzFjInnOeseH zKxt&hhPEBA7lcjTd3XNeQYs5vG?N5MW`ZtZQd&Bo;8OaXc_6{QJa}(02LrGEV zb4`l)jq3;J!#YX?T*a36cV^UFq)?juUX)+ro$N zCa)0;I`kGpD&0xJ9+ROU$!Yh5tmPcg6P~CK!^UT#4;^;<&j-cG*Iyay=mYypj(hX< z^0xo~ko=v3G7;$do5EcOP&Z#s{$xp6_Zm&XuiOkL`^CP1)XV`~L;RU6{CQ z5I1F8N5Fmg`gjQsG4l0-$c7Dhj(o}E{~22#pn`Zz|9{i2oS1KZ{s}Q1{Z~de>O(gX zopt~e7HP3Ql%HbN`p}M-D6821KOYhTH+pZA`fT_Oq|&M_ub~t3pVgPa(WY z>t1#aQ%wu31r)4XQqBVS9tHGB4oH1*I>i6Q)3&}8{KlarUUQd>t2#yA|5?>=KRNTdmPcs4xAxf(1FU%7KaoI2PxCRISw0t>%)+15=-zEMfO7b=YN zuV=}&F@OTw62LZ`?)e8J3fqMHYhp30+!znDJg0lAVn~Nsk1OUk-zT%yLvA4}Coyxa zaveayEWHzO{xu$EHL>S2da^v19W0)2f?o*V3HZY#53`a$K1d(eS>8wsynDdqKp&+e zUg?;RU>LHVJ3|f(1r#_?LA(d- zdz^nF@#Z96dW{egXG8>?@xu<@d|`OFm!gRT4iSWYXfI+0`2!MH!-FJ&cr01EAP=}8 zbA!*{Gg2g)lA~VQ9-Qd~^Kd(0MMP+E{TuKbn@^?zTC#_&e2bpHXnd*Bphx&<`+xb( z+b&x}`YDEuqEG3Id|+^vzV}({Y0rLL?E3EWBOI?H@nG;yZ#;Of9_X8B)tpD}-h`YH z^}oL;)f9lb@gRW{Rkb#R8uh-|S!4P`>thuQ)>pEVeWrQ@9&D=cbw7!UxFE&cJbs zjBh0<%{08;D@5ep_1@tZG8Nah;N=n7kk_BXOnJ=)6U_dZA|+^#3ucpNBVm@ve@{|g z0|DyFYqCf^8}-yx&wJ&?{c@kYiYe|YiaR%PPdg#FDX+i3&S;N8al|p~u|HB=|t<*L`bLREacBeIgv+Jin zZFS@DE_FsP&En+yZW0YS8>EIT0~F%0eV(Te6fK+Qd8Q1rwIo9Qv<(J#a+1ADLoTJ^ zB>I>_)>EW`IY}jeMysEGN(ZljBwGEn4w7smfm;M_N={3uq$)K5z@7Qyk|PLOc@bmS2+CYV=I z{s0Gfn*JA7^$*{n2XyPF1v#W=fy(;nf#+x=sZPtYui-QJc219dnEO@Zhz}G@8iM_* zegI@nH6DL4*rxJ#Yx*|Vxc||p@xj}aY2s$lt($(QarXz5|NLDkjAX2}j(B@*Otjg-`?=n zA7+bJvcEq*LjFB|#W?T%~BLLH*-5sT6sz%*1_$M@2?~U4XKc0)>e;1`01T zJE!WoP35zJu7NbizM!Wt@hk>+45XRTP)TVRjU{KuntDWNU}2&OK&3DNA;ga>Co_=3 zgno$p7eoPP-Jef>3Ku5a+f=$EX*LXGH#jW@a!{)cZ>)ED(OT)4JC(c`27AT1HqsGz z8c^VcU2PaI!irLD@Ni(&01pQ|)rR62(&0cm#avM_=OpIWe;0x1PHtpW>FU z3M@dhz`2IQRF?tDBD);X10y;<#8}y6ylmu+{;m&cjtj}|kWt`6oD0diE5dk1Sc3?k zBSKy_5+Y~pIz(O}H|#?;iJuqFoQ0)Dxoo5{5_I?w=PT8#`YC7Di*2S^H*SY+=wkE< zrQ@a7sT)aHlOq57MJ8^Y_)c^qr3Uu1@Ve@SoR2D~_y@{G?@9Rn^E22Z*=KLV{v&=D zRc@S}I!G4`Z*>#^Qt@b*wi&9%iih4@BA1xGg2j%c6kh>|rH`3-jq7H<9=^5Y%LMb* zl4PlLOz9_{YUT(|O8rin`kjg0o0~^SJP|$EVS}gsZRQsh6e;2d$VsmXK;{<}NgP~i z4*qWa8s^`dT2Ff5HS%vVZG7p^gBlWS#3PR_J^NP2qf+!*${O^C6i}pe3LnKzlvV2{Xy&dSGN<*J~gO zcrW_Bur};9Rw)hVUL_6N;5_i1b<)7Z;#+{aiN$i-hFj46fG%DW3%L^H;TYp8;x z-0&JRo>tpwWOWVDU5j9 zbqYyX4{X??PQke%WrHI8cQPkFiU_+CArp%!0Cy7$R)fP%VX^pg5$RmPANhDebtK+K zVlfwLg!RBcm~jHWYt+Xu<3t^8V0(Nof`I~NTwJscNk;?wYYn^O<7m10`5bx2Q8;$7 z+=6_Ac}Jo6Qg}z}mDh62jLU&-Pl*-Bxc@h8uRq_8v48pVla6ip_rE7RK--9LKdkJ3 zgLdJbz5l&xwQCUh?-wnydQ75Bnz75`hy7H7DS#4>riJRJV4xE`vvPiRKp$5Z-2Lw) z8PUiz;}v=E6(Zk>1|#f$6FC*)Mu0;hBA%b0DZxahw37-E@jOy#Wcr3eOzEwbFk9Zx z{cmtHy#H;FIA#QX$No2?1YCD6yasUD|319i+5Z+Xh%#)~SaRJeH{z7iIaxZVKVe+h z|NcoBYW@1DFcim?rtx*CkWv2JEF;5++iR3(#YT{Cpp^=%mN3=Elsk z=~gQ}X)98M^RtsMxRZ=EQ5t4UAPr?n!*!&AZnYagUAO96uQg{xi@jdki>%mis|}w} zWwO_6E0?>xcv$Huq;#ADOK|_$kL1N(icf@132ya48O5-oR*Gd`)BoVbYJ#&wt_Wg zJ$ayVvi-~Cd0ZsN`@?Yls<^x?scC6E7XOyMvxOY{ zFU~(9uXEyvO%HV&(dmAFIgu9k`-@Yoy5E2Jamp&zcFne6hbr0FkNdNmDX$#Myz;t7 zeeHsAtE;KFt0?Zm#64}7;HJD<3%E~S zK?wt~>i^Gp%}kvk@dwd6j?mJ9e|19yKZ~}snyX?Gxke2AT?A%N54cS z4M*mS@89ecLakIlY5kwCdjnE6QtPY#ch6M7!OMI7_LxaL%G=eEae^-%oxV?Kj{H53 z%cxVsyNmOhlv4tFV9F=15B^g#&BqwkpJUvT<1*3)}mq-S2r zG{3K2w>!{D^S7rrLayz^Bcv27z(nw3+$c@+?|`M)wbXx?39BeBwyqcZne>EsqSTKbqSCk-b_95^BS%t?i-{f09`+3oG$4*};pYc6_&5t@(WcNcsIr$|vYiBK55xxg- zt#BJpwI3=WT0hkF2s>g|L$vHT@?%$*-qLbPjZtLMt4wa^ZWks6Is(epC6paYf>YVF ztNM@GS{0!mDzrFkS2LA{5(psdxq{y6J~cdong?+@2vn zh0Bg9&Lz%&BHeWC3fW7iR8=qBF)y<$xya?kT&1J3(h&zU$9=Znkrx*ik{5Q_@g@ub zUeKB&HaR(VRWH@U0Z-ZSJq+o1miHC&(ih2rG}u|lDnZQ5be{t#IG{~VE9hBV4)l-+ zC9-7(9J$HqB+^ZT10A4P;#uqs#o`#<_AHB(j@y-vT%_ZTZREg(56J<$s#rjDGb@>H z-A7%|k_6APL`E?(-H#RF>Jgmy6qqW$=Rt(@EH45ao<+Nxd>e{=B;v`$V{9m%L#k|N4w(M*Q<@BK!EY@8%>p#njeLvA zu)CqSk%M|F2<&)zxidXT7CW9|_czVz;CKnB*E#ek-4XW04g^OS85;!Y-R&3^^lmrqTXpb{gWDvh+;kmr<+B2PE} zWkizv7mt}t^-E^{%ReRm73c5Ce~He{e??ZB|5B26{@am~ik<(i`O@R>W6SH$_NKgY z%!j-#G)?>0Ho%Veix0CF3|D)YBl0TrHRZME14CYuMe4Tw8Ie8e{kf|;c;zMiN~1BL zDX&KrcNN85n7F5H72KNt3b?OdDJWh#M!!;jq}_(Rjyz(@t2bRd?5sZ?tGqU=aXrBY z@YVGIBF6O$L1|p!ex+_i?(J7flzC=yUqmns>7`L&k1enJ+L`j|`M%e_zEB;%G?elh zIbY<}Z42d92cWKf9Tur)W4)5+5wE}wM;VMAV3LACe%CtWj4Y`t(rmY8*4vCoIE^vZE zBcWDLKrs<(%h#ER!F_51HcCda3ur)=N48L!wa-+*!G#a_*Q1%NR~~8O$T-2bUTIfV zXpXvG`Q%&AdgT^avu((wHTgU|gmYev^a|g9{gR4tUJS`yuYA=u+j-TAwzhIaSg*W^ z!JVw4oYK%yX}Fs-Y}qU{aJ|wSplKBlNU3guaH0K2qY*k?E2YfB8RN3SAuO^^N{t*ewdo+$?jByT@_(vBHX@7 zW<*c6P%JabdgW#bP?A-|Sg*`PUTauMeo!qF*Y(O&dTW@-%+@j)yM|Vzp}nl1#HTQm z9)z>rk>pEvHft%>9}Oa#F3?PhkZNlPplBwEd_D4drIn26tv9njqPQ?C#(o7Ze{Y)h zO}&ZD8wDR*hDerqf6(nMquERIJEPmnxsdfD!ig}~t~dWN&()D}8hn;K%gK*NK8XAI zHj2msn*kNJm#M9?Z7*wD+1e7J-uyTQckCriX{f9;#F2(KHwX>P!fON6wHIH#`7nLH z=1vE~f8UqRBuf{KibXI-n&P=*G903|R4{lJKMM*R>)ko@`t7UnUVo|#x_+#bwEBW-Tm_(RKCt6qnUw0w3R%PJ z25i)N^Tmf<0lNA2!I@sKm#(<`DDDgB4#xd|pSx20NWgvhKt+j2G4g?BNPi8<-3F>X z`M?5taX7mr!WGE}9<3866T|&~d;)O|CyZ5Yw(IE5E1{eFseWTy1^o*o)XD)UI=Tn= zx;G!_FC+Q#fx5z&*a=^7O z{2$!8;s53!MYCgMJ9Yj`o*_>zam%OJIuTxAm?Uy;zA&{}_WfToTX`b*zfu_7@qZnZ zhRRCAK+^E$TA_jd?|dx(M^~MR|3gk|`adwy@PD(g9JG1yn9?z?FL_Y{>k)jvf^-B1 z%c9ZUZ+ltfkR|{3kZV4YFI4rdRJ$p{YKm~tFhMwLjZB>WFBib0?YI3demOJ$hn&^0 zqJt@}|D#hE|A$9zu8_Zu-u>N;4-qM90Zbgj2dCcZZwG1hek%@}#%|bN$`PX^_29JGwz} z4_Dl|i93C@E46h3?(=swC8)*lcbkw|8ltEi-oWaj+(D#|m(lxG2wdy$%-mHI=CCSG|;{o#sFok9w0$xrw_7anlOF zqdY@{@0Z<$63G+gQ>VQoYQ(5NoNMioXO{;lPv`rWbg!_!bHWl4=F*;;a{R#uu)GZb z5z9M6P+DHN{%}kl+WXs*waD^x$%C1S2j2seEIa(a*z)@P0aIQ(-tfxnQ_b9lJV~B) zK_6DgI<}JXdJmwk{iSk7S(n$i#u??+3Im$<_nG3p`UG+RhJK@v)swg>ud)K}s~4>n zFCIf)^^vI?_O~?Ilvizr0LZI89#dW;m#Vz(Jii@uj)kZtrz8xdB#p3 zwguNz&qjWDLnBjOHD341>n?Q#U-u%yj~NQh<){|7RL^} zm-ztldJG^UuU84`lh62GTanF35xG!LF7P9gXH|4c1g1p*GREZ(4qs=|?YSGY? z*FpMP$m^)EMC5g(liJsQK7hPF0f@-!SAzQFwObzg?&_nD5d z>yY}SUOm*l*e0<16UyrifV%e8oHNS0yaqSOD6a+>(Da9g75Ay`#J!j80quyJ^0EZn zXI~3GjV-Tg$lMKoIH$fTugdbWoY1d^$CTHck5pc_^8w^_4M0R*cM;SluQEjL^@peH zXF*euf#BE8Ooh zgsy%c`bY5#Mb_*tyD<1HpFmbAgt5j>bo0llO6cod$)rB;2l#&JVj2e@>~a@$M}?fIU6~5V6O13F@=Q*X5zlf2PVjV~Y#lQ*Yw&pXT`xjTcb3 zc#x3Z4}kO-*OMR+a(F4#=$Wvxl`F{=UHQi-u@O%T*QP8YR1+$j_j|YR+?VluNRtH~ zdSd&BpKF`?bNXekf5=sz)J#t$H6z)Oa4o3`dOerDt@5~g+8zw)Z6e0 zL{^0`R*&(nf4E5r9q=fblma(_@ArO4ktG3&{^1{Cvo<=p`)j31t=B*NRVP!03$8(r zVtDzI$^HBP-D}Es$rP`AKeGLQXOfc{H)gxw${!l-|869lhO;+x4LL`2_MDP8e(D7+0Q6l+eu`$fTJt zThzZvs5Kc-l;;C{-7C-jGLo+zR96@iTb{vU zg^&B?o7w(XHAlt?zWuNH@j`R-{V#+9F)4fhKWErW{G>5%NgK|&J@zoM|362B6F5kv zcKZ9LR?q(aS9M!CBJ6*?fWe*puY*cMWu;*cwkOg5`>xQy{jXL4jk^C&_npc9S6xvS z_j`?dz(jEt_Wpn8=UtC^MCq8i(B_auI2){eL9ehL=28RVL2;e};jJSQp`uyZ=?ZyS@L# zhgdb$0+_6to+LPQ{=$HW`(Gp_!v2>`KF0o6@W8{_Sg+iX=;*%qw;Chh-;Di}E_VLY zlA^mGOHbrK?@)~c0CoM_j=RE=%gX-A#k*Vq(!a@ickK&aDR#H>AI1F@)5LwVTq#Zz zaNl~jqJ%>AZxL^YT!w7XklbycI=tRpM86H`Efbb-z1v*tPapCDB=;gfL~@@Hl#&bY zpUjhozV&WjnP+TwwJmsJMmFU2{2iveCX2j`e6^Xn+L|pWuOrw>#Ql#mDX;FPyb?I0 ztgkmi`G6OPVGXdxx^6mlt?f1M#rvMLCXl5o7q*S+y* zlZ@nxN0aW%RKUT7_j={qQob*R@1Hxw*9Wfju>cBLNeG0nVbVp@JpOQ58)o@Pb9LytvOiA>g%5m-o zs*onP6ekFH0&gkq51%fs^D&&_fiKDboErf?)f8_|Gpa_VVZ!mi+n7*V;I|>dabAE^ z1m9z=lI>{tQ59P?^;Axg6W1lDU4~v3!4bCc7~F}5pD7I`m4*+vG#~$#&@fy;I|I}` zlk!e3%m9+MPvz`n>`-eNEkC)Za*DX8a@rw#H=^MduvMZVz8EO8?1|Cs^}~9lW9mcX z#rN2~LS3751nyT}$e9$JP#T6IvUDnEVPy{oJl7%pH8{+HO^Ug=Vs1^$FHI*03V;Kf z0SXRO;JKukIXxWMAwFMZJ4T+nr*aA)^>aDU26?x^fiEj52U^M-X@Q5Hbvf|0((!r< zIUxHBSpQF>HdFu_23KzaH(43Q-cEU4t+fahG&o`GQwY*Wm)DCYjeJcgK=5q$_y za3GN!c-wm}X}d%o;Q;%AT@D~kjIc&j43mk1{iA$@aufFmQS z0iBN@H%DAX_+pbi;=*O((hnTvVv`Pcd;Ih_6=mXsJBF-w^#6#dkK&PZMCz5xt)Vz6 zMbi5f)_U@T_>nD{%h( z{&8XjTQdeo5Ew}RD5rtN={3gSj(_|}Y51=(X=qCtdXa{K0$LKFu7CW2{?R=Ryp*o| zBDG{C{iAal*zu3s(`z7Wb!-Fi^#iaKycqYA?H~KQ-eH;2@vPF(45o_x+1JU7`vC>- zVEf087$QsFA+5ZJ1N4u=0dabN^$T-grDDF4Ob+aUt)Ol}%me8k0qXk4@97_14lEG| zF0$o$PB|7V92f{Szi9i%?dkVa^>E<5a>@aE)U?3%0WJsDDjfrqj#F4RqyGIGIWQkk zVgL9DhR6~J#+UPOz;hzJHHLI_;0wk4?*rsOe`4-V%sgRnJ3w9k=sRJtSOSS~faf_~ z4!}Q#IZz$hu%QEU%PI%#6BZM|Upq#AsdV&HI^L!Z9GXH7^Z*n%VEe~*7y=%ch>dke z#uMQ$m9;sb{xLyDG5q6JMR<)OyqySp6CwTMnP(jTnDIpT3W*;w@fas8Y9W0#)*T;~ z(TVE`i|PzONMdW@aRwh*vXPz8mc_43Xs^(3TW^TT=t+y+N`3uC6kBnu_e0j=SA|{H z(=-_v+*hULb#Fp@Rz|WDTDyWqkNQ~|Fe}R*HMnMSwEQ#5{b`@w>iELnqLbz~}U&bh4p9D`p&Y89q^*~TAJh$&pdnW8YhS$e?6RrO>Brgge z+Y4E9CR25qsQa)lRwx06z<3(3^L!8^=JDtIOWR7Msir5*_!AoCn9&HOVOayxFah}% z&YP14rWu<63NtFeG{bj)+T&A&R8{C`_otmg#_O077Ns3;Q*E;EPiy$JYer+0j!H^L zD?}IEe>sV~CLE5gs}bK*zg!b4VBBBU982ynOX z;=4cXDG4}b-EZS_Fmf&+CHvULH<*2x_or>$BOM`3ipZV*I)#@>g2iDE%rHK|0LNe4=CimNw^0`1UtTAJ5f^%cb_xdRj!w;+~MIW=y2V1xbHaJ_i4fb z>#!90(^8T{)}JNBou%8Oofhve#C@!*uf!)^c~;TU3hQWf5i?NN;%I@qfPy?FzryP4 z3PyCC!l$vMSgB-2DSq(;rI^Q&VxnT5U6(BR8s0f%wsLv zD^1a@?756Sis#|$R`J?tSBm?Q%fmJ==ZWVQUUubZfn&W~Uf!#teRCgYbq;&DA02IBv9?gu#hY$8k{e%wbQI+P{B%_iVxZhJPP-@tQnlbI^u!Ocx#6Wh}#AYq1| zO-}ofwXn;@=w}}fS>x%;;Y%mu5qJft@35k4hd`pv1#RO^$9Kam(OMM3r*&??$F1eM zn;v`vUbYU#5HH(@V}<#c{IA(hwCWXM8p!+N7P)U0FGAx()@uC4Tx&9ax9UCaD$o^ON&i@zB2Q%z<^FLp zid76yJnP*N_b#DSCtq%FhLMck68UHL)}OBw0V%v|Hpy3?8~r!^e~kK^Z~eIoUK@Js ztUsIfboKaeO(1jXq&hHB=<||HDo_qkwvR6oveJuYJ825s;;M3zfBpG2IOceWi%P@u zwaC~XnL7l>3JqL;&H||Tc_vN1^=DN~%<)vw)}O18(>fjk>2P^WL_CDO{!H)Y^5Q?G zQcC@%|B+oYu!zR@21&j3 z7fl8R*NCrs*Ps1lqzLQJdkceESzmuH9O?1zvHQL5E9m%B+3#%rn0LQ(Nqw5&rF%G& zBj{+t`M;4Ohd^0?N-%Gn_9OaC3kfqWQsIocL)80f@>s6;-Tltpsa_pernrYI?jFRQ z{-Ub`?+LhXzq6(Uo*4U`n~+}{a<2-i!~30U>EIFVHVI2)zq8AW8mm9!1H|fA0V1(_ z13|eW3h#F=mxsRn&Jl$~a-9<4v~kJX@FaX%rho+MPMg9(FxVltCqBFKirByP%8ib^ z{QXRP#JYAGK;{^JQ98erc~px4>(J+G5Z^!hd*CPGAQzqL9_)d8$V~ zKtVn1`q7~R*-nLW-e_w`g!<89n75M%{HiqcR~njTj~sM|30mJ|3KjO+?X@s_Xg4SGwnel(h6W~?7I zji-gA!a{mN!hL<8W^pY*U9<4rXH$T2RLvsVeKu2(q&nFlq#1{ah*{YEY_GI+dC^Si*nJ0i zQHAMFUD6Tg2`KQwHjB?h4p}jaV1Cyu5@8m%$tZ?dv`~ay72#TzY_<<^&Ei}e!z_IF z+1xC_MMN5-pKT^`Q^PFsgKC%s?z4I81;GK;e>b11KB7aO^eZjmxT1fZ55cJ?0VaC? zHo>X)k^0$2%g=VcU`L1qS>-pC$;Yan7AxY94>9hu>3qGT`;y=FZ12tQ?$J!OXcdaC zAJ&>U|2kM^8K?tLH^0llxn(`StB}tXpqt;FZ0D6?O~pO4GI7iL68jj$P3N{wz6!8^(S9>T!uFnfR+yNGT1i?+EQtfAt5QFf{&5 zZe7Vj6~$%Y{;eC*%ciLEAHr{JHdzj6QT}6mi^}i0e`~iqkKnInTt^#7jT*1l6wHRd zT70de`{J)wwet3JKB7LOR|Rr%BbJ6CYj=N&ZX!Tkf7P6mQhmv|9?iH`8Jyb{ApMo} zbJoUyrW89V?o;K7yAg4>BW_ADAmG091q&o7#pvg(h6LD<+?+VmUsYyA+lTYtcuarQ z?On6JNIUQT}XVyyej z&*yX`XWwVesyA9ctdWQ5wK7y@quys;6JbD<-mXT@0c&kPR;&S6t3At62=x+00d_q@ z1sEm*&|CwnyN94h+4N)mueFsxmm{9O!BQC9@na>GhGS((!#bp2A*&f_;C<%jThfo| zedb@XFUIYhoHj^ERlWRBesVh}3%GrQC6WIcer#ec^vj; zkH0T@(Hv0Vh3rIPseC_%$WmqYnOq(YcsBH}HVbp0ykb65h8)O8%qhf7PrehN@Z?&X z-Xs-=aPR0;arh$Jh4MUd-(c|@JRC@aV&RQ(Ls+{=NyIt*Yh*%)lkKg?o9r>iv?WB~ zYq?c$5aQJ%N*yGN2czbrJgaly?oA87+?a(wOpI^jQl)XKB4b}#R$LI@2z}I&P zS^o`?Nx|30kvFmx<$m2Tz2?*E>(AtnNg~nN3TW~57x@-_z43hny>IcD{O0xdyxn}! zHS{5U;qM10r>z?y>&uDVlcMiG)k@ChdhNsiz*Fw=B>3{5goCm3ACN2zbj}~8xVAD> zmkf!wQ7pach^@Tchk9_ZDQ(3rV-yC9vgtQ!<#4Sg!+Pxn4DR@i=aq&I<~TC^H_y>3q~7F3dK2=(Ua#fF z5LvQ`nxWD;k}Dlfo`{`3*u)$e#juH&6ydT2PJAtPGhlB-NSo*n@TmDuKT$%6G{$=E z6!K5QCOSfU?EHsLS@NH&oE9b{-zRPu$MxDVK7=u>0hk!W34+rYBCXeU%gio3vr>)3pq+}FlxV2=1XcT=O2>OzQO%gASvylc(sB!4?%qE z2joH0HVV6^n`EOF&aaS?iSu)S#&;w*4Um5x4mj=m4VOy2_^Tj$aRae=uXD(QcY{L@ zMvw2A_TSua8LXsjrmAha{WrV!(Ki2o`fvV+$%xqP{+m@{?R`&^=^iDiOz~W@{?Los zI|Wd7)I$c)^osm-(db%{0XK-diq?Pg%oSIU-Ts?8GN{piGhgxlR)Y8^(Rv;xe)ivp zok{FN$crE6>%Vymalnbg(fV%^kWD*Q453Z}yFqru{+px!)-w8U0up2Z>h#}yhf=$} zAN7fnTun)?O_FEz6qZ>ZNI{{$kXn>872hU5&F|uQe60N zMk&^nq43Ek#}}_ttO<&>F|npSE-dLJJF5i%4ko&X|?!PHx<9GURx;1inxkX2NP)F+z z2aoSe^^jQw?gJEfY4_hGV#Mt9-?Y1AvsC+U&NLKmhWl^6QM@~E;Vdr0&!ew}c-eom z5#Vs}iIMtm#!4IzZpP@p$&bVw4&Ld%8G4Zp9{o4hGl;;!7r-M~B4yrx^ZbvR3jOwv zyaDgO?n(9jr|@5}1lGXI2c z%*D~o^{+nA^{j_QVmdyzKLdGw9?&&s>No{VM>4tl1(h$sGpq z$GG)E0kN)>e<5t+eB#2R-tofm{#Ly1#`~r+1d0XzcwffBTS=h5Pw$A~nCX{xkpHXB zw^}_R204Q5TRzuNZ%2q;EtHhJMsk;c?*V z{f2yZoRxW8q+`!mf7_Cwzw_c*uYBeF`yvcz%J&h)-A8dZBJO>Uy7C<^;J*EWiV}lj z>=!J%>XGklpgQb-7Il}g5nPrDOGLOW9@E(IAs--iya*7n{!a+Xl|#56WS%_q?HBZw zdBzqO_BVg=_zSZ?vxq}eDUguf1%TopZ*k~319zPEEq#Dv+Be`0qnQBz3^u9n8Q<8C zh*{q&^cUDb%|Q8Zqcqmr4fNJ$+nD($_)n=6@tsoX0`er(r{+Qqo)+j@$4y+Ws7btf z6ZPsFY)7Hrx|8rfPzO**Tx3a#q<+w8NhPwiJu&07ty>YwdWUO=m**j+A)qugA`OE{ z1Iv0V0E(1Q%X+iCWxWkug;Win{%nJY~KA?hSJwk7CZJn2*8GLe{gy z%mT$OfXdQ_4VN>d)D|x5eIZU>WII}(M=t9%L|$%iVELcQffn*cT3{eXw+j?EC>^5; zkOLh_$DbX@fo6cRmjocL7lv@$%;NBpz&`GVgB8w)8mIl~`j;fQmg{8{BXr!T2yaq^ zCvXuK?)4%pA=Pqe>}Qk|4|`Y94+Kl#cj z`kbuS>zZ`(#EW3DpZ)$KM*R5m4-o9ek8~J~89#=r4_|NtB|8$SB3_wosAS@%KE(;RPoJhsIEkT8rT_Nm)0Cj8 zPsJIFAeYj3OnutfUiIk~K7c-*fwLBY-AYiOJ{2NzuRa|PX0A`cp$9znZ{{Q87#%>< zB#0@!1pq~nUKW|j+WIll_8BUeo1K=`~R*QXwf`DPEJ(Bn_JJlSl)hNG0X=`lmt~NQDT6q*YvZ@0{r1VkcfZ2NK&7F4kB}}f2PVfv%ow0W7^n3m5Q;k zZW`LtFmy6>K4bD0cw@Utty`q$e^TZw@NnZhTl43_9*EEn@&-x(Sz2gNrMj$?!$-Ec zPUxwJxfF*sxHTfbKic3SX=8Q8E0jOqVb}6@J)DZt?fTWMhp`hoKZ^o9Zz`2A9x$yP zaUVK$w;;AG<~$p=5$m+bMp8=r$%;t!D4zq5#-W4GI_LG0tw8V+pY_0rA(7yZAaK4d z>V7+4f1ZNpw)k@{C?sKhL$FzXK3*%Xyf>MOt9}aVi1c9bg7nkh5j;3=r;YeZV1G@q zrn?FJtPI+zbXP_zuDFeRx!;VVww5PaWn)E1?q~t&oyvT20W$AL=8^k^IUThN$XkT^ z=_c@wO=GSk6;e)`3wXZO}@!5^vEgs>tTuko5I^}rZ+VV{n#+HCF5PV8*mV$ zWb+X36B#7^pzaT!tXDWYHAUp+JkfaktZ**Ok0A~4b zoc(3Zeu0q0tQ6n+YR#|WudiOfzQ+#gp#P^$%Vo8V1AVK>aC<)5Q0hCJ-_TlY7&u%@ zRN`(EUvx;UnWF}7?;*#BV!RLaW!&7I)8C;ov``r;Q-&{Fi3~igqYFsUzUVe_-_ugL zFffC^5*<9R1Ti|ekU6hp^l|YcZQ$?#&p%M2_>uFp)D^h9)4uFhIo9$#oIpR$hTljz z0w)o2(1o+U`k~mt2__5mGoRM6=NA)2vcCGE+{Fr@y~?nyGQ3z$l)v&`84&~MIgso6 zYUZb<3Q97RB6)M#cD1W7tBV`%snYpiK)ou{N;;8j3=2hs&k zAef!$$)hUuj68IiyD4=cN*&xp%z=_q_;VzR$RKNfg2q#0xuY{3X78UZD#}W*9-DQ1 zTz>#Vi5VX$%j3s~y#KGQ#)q^2U_^D}6YaDtS&*B94P)5}>$fe%M1d}#ipIz5Kj%0; zmi_E_$53Q6-+u8(wP<|YuQF6u8TwF$H(H1cZ0~o0)WnBxzxYAs0-fN9w_p4r)XZ*t zAlH8nB}#la`w!Nq8C`T$Ip*Y|E^5&5Nt7cn6I9Xoctz}xojo~A4tV0DlibCMkM7E_ zwlZAKnZvi5%fJ~Q)j%F^|G`noLlPee_8;^^5pBiCzWp+Ao`1?DhKlG(Tr#mSy{cBp zy?GIux*cRv74;=KtD;!@586=_Pk)~x{e2l3d;))OQhQV5(CUWi_uU)5sUk85{9pU6 z*0Ih9zhN&#rSJQnFRQ=At!jY&&~J-M+`kvvSo=&Q_%g6w)bx~=7KLgUYhP7M;54|1 zC)otLaTTI`GkX3Z^?c{~vg!Mx*3SHVS>`$8wfmw*cMi+Ad4k;0vV0k3ew#8sg!M_B z|Jl@7z6Z!*d6X7dtoI$ja$FEwhLqp|nt>=!Ez2K*?qGR2fCaT%eS8Y-cFKw;^lowh zOFO0lctvMXH7W`kXpI;sV?ueYnA7+be4`wQ#Wz~ya5h8QYrm$mzJDZQF?Q?y9_RA@7a%7~A#}a^HH-Rgzw` zzlnL?`|RI5_ACLZqw_h_3D?MUvqdGc9xxGGsPP;WKf*=>g}`30nWYz4@x3RkS@BJ0 zj??9v?lR6S`kU}`HT?Bmg87oie}r(RAI){GcfMq#B4Je?l@sWRIyMrVe7EQ<@O@>= zUd1@3bM$|!GKu>dhWLE^#>6iarU>UMC?_ox+3rIynyKX8YB{3f02~Y6* z*Eb>j-g=%|FNP8k=eabd#hZgFT6mO&QgT?BH~P`BdW`2c|Agncg?SB?;q!BpVH^rR z?Ej+-EIihL)D#~6^S_uW6gc8Nzj+)5pH+Bt`9ZwEJij>ucXtZ&+A2pimE$xV5$Av1 zMO{1%s%YU+9Jk0;;gR}-@%vP`{7rHfEB)M}440nez(zxh4k8DX&x1X7eV#^F;^v)5^=xn~QnBRXb- zQleugf5GUmpWj@|dwSB3p8xedW2Afh=RvOVef-h9+h^L^7Z zRQM?@<>7hmhP3ctkeYl{lVi+&KI*v3*xBTxO1PnI?8eG_E03WGJVoAh$(zRhry|IG z`Dm=9s|5L|Br1EWz8JC7#b@Z%=5ZPKV&td>z+W!}wSd%wrNv%X^h4}vjKKjyt*t%tk0ANf!IB?Gvkr6n%Ro+5@Po#;8kMxN)j`6latB~hbZ`omXG;(OHcf= zeBAOKeIPYX`H1}kDW3Q>{t&Z%Jg^Nyns_~#;*HmbHD=yCMg2CSe)HWy{w;S7p5LCrh)LLZJP+WFJAWub|;9}UVA~r zHM(Eu0b)NwwmZII$VPyL7#QY9cm)=#L7L#}w;=-bIMb(8&_RDuN&itvKi3yQgZ)9p z{X%C&&A#JID^gnT`@v3pn`MB9Z(rlZiqZ&e;r5}F~nx12#&m3WR9*UKAyr-W!y=QvkwA35}NWMA!V09e+&Tmf0VBQX+RN z$Wv( zf1H=>^~Z$s7mt4f320w`{y98X6dNc1YyhZR`DbIY$v;193OI9|X1NioX;|01P4pI+ z1*&NN*|%9for67+Mr9}e3G>5sg*knqJjmnapBj>; zM3w~k=W~>=mVZ>h2v9&e`DZ9JY4Xo}0c8}B9nmimpApZ~MAe#q3SFuBX96!F|2zyL z$v>wI_Q1`DD0Vp}0MK3M%zdJ@J`4A-_=6`Obll;bzaQCl$xk)URqvel%n;bvU1M5A< z<&DA3-7f1Pm7%4|a4lt6e2d7yl&{S4hx=IS zwv3li0=r!nX6Da8o6yCWHbNc>YzP`%Jf?E2`<=RY3vd<*)}$PPcR+=JNdb;x@opY& zk*)n}KW+4Az;j&Qy||^TfhUx6bLCu#oEP0p4ah?s6+sFO=>D~-QfNjs5D}0U+j4e0 z_Hpemp*XfQaC(DkptY8)>q;373|2YT@Nk*Hbl@b;f1@0Mw?PFBI1inEfLpj}B=i2Y z_0j!nyEhoDNJW|YfZWA`i6P3cjWVo8hAZmGzzGxAgB&n{r&+K7^p2E((G}DJ?!dVo z8hZtG94ciCCN8WeOmxOMSVVo~j|sTs*}ryWeQ8Br#AU9Ab`(P70_`7l{brP2Ust+^0>$o$+9>sRn%Ki4K?1>id5D>-UYxK6~^r`0N^;k4+cx6>&$@U-YP>l~+uG5zv0s#iBGUR4?Ds0=eO84(G- zT}x!(^vgmiwB2>l-xwC=dG!qD8m)719xYTk1dk*`QN!GI(Qh*zN3HFK1(1I~)GELr z?~AcU6Ka_f30B2-jYApEhK0^@bCAB&U+&DM_(CLb_dC>c30jdL@N99T*SB>{-H%YO zV{yzG_OIPUy|x1t^y;j!-Yr&6yoRLO9K6;OVwcNZtPq=}3{UU?mOwHYb|OQD*w4in zV##oF=l!73PH?s)08v1aToqE%6sTOl@O4MVI`BzP^e2(oPrT$0l$o5*wBsA59j zXY|Bsi&Sq{<16mB`U@~CS+_iY#H<^g&n!hTJo%P84)(3dD#EPb!k^*JIEKQyltury z3bL7c`(z1kz5ThCl5ZZS85?0`5`Aw?nsFUSO}#yQwTv+P_4eG=#+cFm4>z$KmxBuf6 z*sca?g4^oC*R}s!t%45vl}hT$>C>NY5J7`;L8bklsM+8DQCeUB_ce{3Xo4pkI_JUD z@N>m-VDCRyLJ(u`;Q`p&dVgZ!2LwZc9~|OP4*e%#TZ%&ovbQ+ZF?70-Zhl>L*zZBhOzheMM3Uce+UawtG#2+-wZ^lYDMj#uW0Xl zwO1Xx7w`Wi%p-CK;xdh0>#WA>qr3pDYzPvG*C$Epi`U*{uJI}nFH3thWt>^97hSj| z2ll#Sg>A3aNnU&HQP(@q16%^LsI%VHMQ4G^AT{2j z@*bwVuO;t{YQ|pg3c1f-w@Fq@V6QbOr7e5ag4E9XUaLrOInf;US|civW_UzEf)nAo zgjZm&38ay}hWV2gGwZRR%a^_dqZd|YX|SxU!gfK4<-~QEagC@%@bA#&vZZx7KLYb634v|D)p~*UTQ96>zvaxSny-d0q3sft z8(G-rtwj*V*k=KJ*sdocnj;?giT26E)@E&G(NW+farboReDYL|L17}ZeKPMYdStQJ zK2lHA@r7HS+5$Jh{d>rJG?pB(ADO%vZuy1Wm!IC0^pzk#RYWOn*=ORH#y&WGv4}z7W+gUJ)`4)I{#LTUm;N)1%z|`hd*MT%C!DNVZ8Ol_Aj%xSNOt{p87Cxd>vS5 z+b_*m|F21*4&UU_F@Zdozd-$8iS{e&ssF_b9Ei+pzs&J9cahhAvh93}ucKS9yvr)@ z(abtyDhhAfZ-$Wj;%kqoYXIxXzD=uiCu3 zHDTUUFEG9ylAO%=>cZ@-@s%Ru%&H!2euJkT4DU_y;ALX_UGuqZzvTR0eB7ZaXU`9e zfzME?VgFYJ+V6NiEB;oA7v#Wx84EMpZ#r&hl% z&MfR_KW~-n%1{nWGfDuTxw3YZE5b?Uhu{NcO-*yZW|3RJr-fEwAshRDQXoqxSQ}J) zI6T_|Q93$b)0@n__*_%QnT5ZE=N0wDcX;z- ze!O>stg}tu{RPNUshz`glK7yntsE# zAMHmb2%U(Ew;!!53Rbt@fRVRAo6>JM?-NMBP|xkXo>w`heMemkLWtshWRxTDFsPy( z!i!>%#FLooI3>JbzKMfWq`dNS7pp^fQ5jyZ4D*uVYh_FbocgyO1|EAq+5tgzF=>MB z(7jRBTH&zs6B)SsKFTKeBr{abhUf?NeuL3J+{J`}Kxsyj_K-n$q#Y`(RZTr!hboJM zQsSi{f8mRlI=rK2ev|#f#ZMSB-O)`x0t@%|zfZu%*Tu{q!1%8|2EI=GpBw=N!It0? zTbK#_KKNo`gRjT6iumzc+Ax(_s8MNAX|OY>{P@}mce3VA<tf?;>sb5q$Irt} z8Jqs~?QyS*2yxc8j{;=Hdd~i;*8dqNyrgOL3LU@+R6|&|xmpGgxE@q+LT7)~#gAk- zT0>`NeY?`f#uv@{_U?;bhs=Gq)_>cmy#ZvNkIae5AAmgG`gTi68#1I>Y*}N@&+SAx zYdK^ij3BzcJsp}f>)YQ-BGC2ih0F=C`Z7^9@;vre4XLciy?~eCi7$glJn>5s$E>gC z@RlBbG1KB7OS!XMLOY|q~kF7k*UuM_O|e*Od39}2-@8AxJwf0Va8^?Tb^>US1q z2JrktGL5?eq$b~{a9nEJ%=LBV{wQspu`T;o$+wS50=2-Vfbw3!!(jr~l6MvIrfnO< z$hXf(B1n*L^P=3f>^a~=JKtU;a>8zTahdsc^+P(}`mg9no=5)!WS&+xF^ysh-DP&9z1uyP5X-jQ!B*D`>BqL2B&PpCih? zy{3GS*R zX|G!66z`ky0_;^DBx0}oNb0j!V>0*FN5y2ES=C3OKC$B~Cf;82o@*~Z-d;?Ew@)Jl z*m#@QObgzqVe#H3nm7qF7szWtn)rH9Me%l=cuEfNcH#TR#!yE7Uc2pcE7-K7I@nW<*8-w9nf7AZ>!^z!P{45t;8QW^DWn z$W8qEo@XqJ5ix!f6!5cADqHq0fe|IRbtV5>>+w%=3)p zGfrXxUKY@X@GE#kD-erEyucsPBh32QK;AQR0N*Z(N%TD9fBEd18u>Si{6BhKm?@U!X14hBb7L)>v$g1ZySHJ=TBmP{3OK?H|x4 zbm8{5HU2W8vP9)rwwk&a1*gS+7RnJQ2rB5p*`)K17$iIW?e>`_Mp997etps#9?O+s zGi6wk48I7-z?t4Af;?V-dr44QOqw7(MxpAp!sG9^O?ae4f_?DG>TjRd`$>P>iwOV$ z@+e87{cVK{`4}CYcpcGk6DTD*dhi!MyllridcuSKZ5h!?qV=&NC;a)%jgN%qJyx3G zMhVJa&wknK6*)7lI{VLi9DwX2D(#+^Ao};8#xvg5T=mW>dPXz$21Sc9O16T^@eF{@ z%Wvg4N~pw9w)V?@ zIK!g>&v}oR+CK4Qd88smLWq-|}24bG~_^l)zv2B9$9^23LXkhJh z)qr!}<4d@^vj^c*m1ELMdc$Ls<5FRILpM-C1I~WgXK;&b;l$kO9-O#J?qa3Uh03sk zGQ9A$3_P6-i4(scB~Iw+@5F=XX1*T;%VppR&U@^FO5DPU&C`ezIPdWRCITQqcU_|AK5Oi4U=!2NthW$X!e%z7uF!nb$IK|gf)n=UH& z>#6FK#e8w*pB@J6i`Ja^r_?jX_}#Q6d7US#1R|I%K!09{#=ja=FupVYG<0gz_}Qta z=1es{VCt!j|9Bmtr!v1vnU5gzQ3ZuL9pO!on|g{oqmHmu@`?;8!TeL(cRh}<8oG=2 zLuK&E)KjhWZqg6cVZwrw+%BrterQTZ?T2de5;8?W5Q%%-N@BW)zaOf^TYCJ1^G|=g zN&iTV*AJQcx_J1ev&bA~J|kv*ed+ah{?P8V1paV8z+RN+oENex3I-2qi932J!Jyk( z@rS?i(;ucP7&!j$*p!_4!{jNM{UOZ<3_X;2VP$@ZSUiZ#=?{V<#vgq3^$LM(8B&4* z;x1IO7BGDF2K~V~FQh0w8GpD_?zVx_Meb-Nia(V3`7g z`FP9B?y%*xgzm5@C(*cxCbYvBaAcQNB3S)&!hYfO1lQ93exc{{ z4n@1$FJPDI>#vIMB#jv*z?6HcOi3xI~UHu zdiPu7AY9D#?mrY&aLO)11mESyYsKXaamFEp!Xc+2IW{*Aqk2=`X4A`VA|;#5u2a>MO1fr1;LO9WqfA z*|M1B1GV?!S#2D*9Kv~=e*vCFWzKn=1ELU;w+>t;J(%(d4YBDP@q*BKdO-_?5NDdU z07jp~gi>vs;|MX%<2(VVa1%-am0|kFl%WY_C`cJNO}mz;;+$9OJCCz9^NvnH5g%hb zm-z$gTNh4Yy(S?=73Vz80zaCFD5`RlQaO$zFfc!Vj=DJb10%wjru|p!kezATs-b8o z08XdMU92cbQiiiX;=qTJ;pJq=DCi4vL_spZCuz)_D4e#!9N7JmZp5Ss&g0yV0@jLx z7LXcIfF0C75whXuzl;^5%1Xs5RAKTy^qv{P?b=Fh#dn;6nFDGmp?C3D^mfnt(AUa! zXZ^}Pe|Fp}^!M)Y_n7;Q!l5HM=%?O#+4X(@e9QE>^DPman*xj%H4T(B915giVaQ3I zS9YT3UptS=pO2Mb;NKZqyMkx^swfqqK9(8(GVi&rGd5~;_o(mfr@WTGTA6?FA(_`A z^HO9^%fAD1#Xmf#zBp=mIqJKsWGxxeOyXb6M^t`Ab!%C^%@|sK0Bnq@(PztjAff1?P;-MuUEm*Wkb zZFznSy&*Lo`eFaq-ZX!`ouHo@|B~wuvfn37)}O6@YJ;ZxrXNth12Bz&ai6Af%i8PD zH90c1ZRYjo%(m_Lvazk{r?$v~vK7_eDDSO2W+iZjxvegF)3!6X{(NRgBPou`rlpHb z$Nozz#C<{)qopb(~ zn3NVPO8e`6?Cqmztwik+-p{qq-~YPnDRK7G{xs6HS*G?U_;``2e;|JfH zaIU9VdjI>hcrJD&t51n$0wY0%a>hwy4d6IAOk_P@a;zR>z42Py+)ZQ+REC{AMkO$m zvu1Zt1}3r#yCkZeMCRL1`!Zo)9Wma1+5n1kE0GNyrHRbhPrCwlccASqm7}@JQ3^p2 z2`>7Jx_ARr(1nx8Zo)0HmB_k}GJcf!i}8e_>@TSw-MI#P%*umOc(w`I7O1X2m%b*obR}6k0!W3 zcpVkN8c<4t`;J`Hkz1AB|*;bdQ_g`d;$KM}qmnmBZcG@aMP5uZmV< zttTMAT?yf={5E`taf0PqV&6T7HYtY!5AWwYK_}=0s%U**oqEWAerq?v_yX&Dd8Vk4 z+|hD~uax6}h@IPGv}chccW&$By&g{ty}X{=tB@12Na5 z8)9JYJV(6s=nW`KEfl>413>_}>(Q;E?Z73KBfrXV4Sl#jE zfjSUhG~ld9|F_$CLqU}zugWo$ay(8s0zZNZ8gS;9!owt@&XIBEC%3Kl4<c(f*RDyBez3p?68aj*! zk?r}S#OsaYpLJ2dpD#v*M0;`a#ZiE;Xvyh^>K-x1ZlW#86>m}ZZ(}7G&p(7kFM$%E z5{<|*1oG)~qKfS2i%LU{%}u^og+&e9@M+5Y%^74~fz0!fISv1+tby?T1eyDxmXcOv zND1=APL#8j;TvHDFucAbgSNOE!ViAt{;uHL3=ZnXmqc@}`$QPv>`sWAT{19h;=-DBzPo((fhgOZH zPsE!a`VJ5;Ds<+D>V0Fp;tx&axu(-Fdr;uv{TxR{ErC*?f>$_Y^^s?CoDhmU>o`V? z`Jpd2Md9#-$}n^qWoS{^FuY6yVO_X%?~X?ZEL|{WefzmaNpN* zCJKlDs2r!KQjX)4qZ{Q2Y*#pR%IcrQ4%vaj!p}rQ1913?4-U^M!;#8xC>j3wn+%*$ z(OKazIoABpt&*t3qzUGSR-k~jqM|ya*7>2O#CX8r*H6npoOcS|F62ej%^{Ep z6fPq zaC5gVcvfW?s4{HfeBps#MFs{!UXYqV@b#D1F^eYdFF!^JYXw3X3`7FK=`X)uWppuI z9>~o^sc$>V4U$E~qzU@Vg{VxeK&S|*qy6QuK~{gcAcJ?4{_-{XQ)-6kAdnz& z-ybljo%WaGcpY)l3zQNkllTk9iQQk0;ypd<1?(?d49+4xifqYYd~_P%iw|>tQvXqm zk4&9||NNx6fPPV?bAD3QwZJ-3_uQ5J`vvX+li>N4&7gW*sSTQii@o{LN;~g>1 zPkL`nG(MhE8QQ807a5}~4~h(2mwgVTCO&-UClzE)J4a86cYabjidQ#2urhrS+LZWk z&QIDZTeozh!gDIeW=?7a24S&261;_S1mEY@Ejd4_J$@cNKk0tSBe7o_}U)LxbK7m+bSCDr}N2y*{pTb+;s$ zSm%Q@(hID(?iNL|;;N6ooQg}Ie||EHcXqUae&%HVtcQjYl%J(i$!)z+beel!~>v^p>geE>zIeZ5;X=AL}~L zUbMu!>snN*f-6CxbCP5RS2ny&C1tV*=B4pvRmgH`n@`bYaaelk?v`#LP;Si!W=1$asdn$Xd>xto{n zP#N}eqAJjsGTcoWh6!nBkRtAMTfnM(7y)Ke%InPc{~>L-z4N>Bm07^UFW1-Jfu1WP zh*H^&JHY9vCp7M!67o>swGBoWja81eD#t#`v2q`E@dT(4DK(*scaR|EGb=RFgMem%*#F*y$t(!bVI12s_wC5>4ryLzG;NS8b&wtWxR zTgdZga`Kf!50TM@~TnYLas!a^|ef*=5u~U20%?9*+h> zk|sn0b8tPX0X%#V)j)An%9aL(_friFkUNC}U#~D4=%8}6QaO?l7Lnl6pQwRppn?Wc zp#iM9+>BdfO9Q?8c{JdewMoM*T@5^-oWCDWA9xE+7zw75Gpn<*AVn0UQUgnKdo(as zl7nbq7OqD%fXSYy29i)NTN-%&G1Y*c865a3>I2i$*?Q#e{&^}qdH4t zoAR|lV082N1W7A0@DFgE1J{?saNrvx{5NM@f$A9f0=+lU|E0b%@FCA(dZsn@|2=9| zXC?G*gS%mV@_-B&)!8Kw$Yd{;xuMP`#Ux#h?E-vNY;Bp6(YuCD@$4fd0OoW2R_e81 zd5_&KUph0WP}9)1jJ;RMKBF~GPU$E;%-p`vOh_|ANHao6GeUZw?((j|hFu$W>AHry z2*b}E@z-k!)&o9y1aimR?{oTD(Q};noq~{A^y$p+^j~TMquf2ve0uPfakNqrHVxrD z#y`?6nt=*>aprf*P!HLk-)a1)@eVV;b8d;cNJGa(Dk$?MoSF(uM1h9=++@y@ViU;Y z&F}P+L?T0CqK&Np4`-t1zlU>NzgKv~ z@sJqx`;jlB2s&S7n8eAdKz+(^X_v^r`h6Kl7Vy}eBsp+^|(*`8bwH+Kt>&sByND#N=h z#lHMbWMCNW`@{+(|NGxDFt;T5OllOfK|6Yk@MzS;Rv7&QB}y1M?|)y3?$B9GT%vNU zeTlkgz*6i+$`P0Xs;J|CD0Xlh-`a(fd3*AnUdHij!tvY4U2Ml!hHaJM7FIqhx66p= z_!aHObyu_yksUY%B^e1aE|=@EvrIZlVaxF^_SAtp?|=V6_`vzoaT!Cyzw-X~0{QXB zN$ex!Riu;-qzfLE#H?tuQKg>2DVV?_mQRH!b?|E@W?)qce~zi6Snq$AJ8C|1YZK0| z78PYBh?letFmSG1i{-ykp_u*2w}u-^X2SRKRqa(;zR2@$(fkxMp8o9?FP_o{Cyb~2 zkZ45tUGqTsp}^8ljSscd!eKaj=)eOgF|mHXO;jD2460~6J=7z|@f7M2Kb~&I&E0rv ztukC3K|lT;1r*-vL>U-QML}xPlDzFhCcB*%3N0YcYg!sEU&V;0TToqF@$_zYb*uY? zJQP?I#g+~##~_vCV`L}Pzgww`35qRFBI$%%xbc*5B4})PPdqh~yIAq`fHKUh4C|BO z<7CKqDh+azNM^xRtnL2HH)2wWjyUnu0L8NvPana1P}p~g1nV(bA(k5Al6QaVtr_n! zncOI@CPjJyp+#88d6Bvwv5sD0HmNK6XEwP3e>vHN(eY=u#L=;3OImvVUxvfvV{<$8 z`?5Uo^GnS2h~K-o@!(&NDD({DAk)4-44GgqpnvM$Sn*zzt#RWFMolga>jWdl|H|4 z8ea>9orw0joIhROC2_=rt1XNlA2IXAHxIb+k>abr<_=(d#H+u`LqscI%$jFh;a9DF zTMwgU&c7*^S+iZtjM~5tU)f zP|7fvGTcfTm@iI$XoZC@UkqnjNt`bVpbmD!0;R#=PM&;m#rsAVf2bUdRgPg;Jj1?) z4b;WS_w2B^9=FI=zIdRM2@9#eK9svyVR1qk?tG2|FG_}YkRik3IgrQ87cWa%$s%6_ z`gp=(D7;7W#bwM%$QQ-Mq1@VQ`lr%$6yPN!iv3%JLyY<9`xDF4b1ZY-o}ETqZ|RVrp|77k)8)NQx~ zlmE~+Rt&g)P}5mIsHy7*oY9hHgOup9!FhnODD`QbD&K+5&#BE{(>c2;oHq!(imo5) zlk4akAAt%=l+A6)k>KSW=^I(ZiD%iMc1OocblJc&Y2FGqcjIJ=$}oqyFc6>&NtA(; z=9NH-^pU~|(=WV}<{dFGL@zyNs(fXZ4KQ!+EE^o?8I2R9kCyjqob=U6^M|5!)mth@ z8I|K^bPqUhXDxM+s&$ntpVi{Tez{)bH1pf||E3EHGw;-%SHHn_2aM+2To^J%!HtAP)d^USBIfvd>5 z2syKa=nqo(fG(VT%G%m29ktu!Xh8PM$C)($2?egDfu`+M0}pF${mQ#09u}w^$tuS$ za0Sd~tfmHfg9`B=3n#dEshwy*5jtTBQKP-10i86zM(zTvbSKR}SBCF%q9M?q3`>w9 zC(TdHAy(D}VtJkbl4rjXjA&{k_+eYCgxD_t z?L7ZTtVRj32?SDiV-ly3q)hxwCe2eahFqa@oE?Wp`B!Jez=AVokWTG9~N-zLX}MV_`M zSb+M&Ji+qGtZ1;jtTGH#8Cp<=17C>@43?1~HTCu)H&~kT38U*UFgI{na~QyMCw9Kg z_!vd66)a^i5P=Jvnvb6bZbsSSB#(5J)gd)N6u3V3Oyyrqx zwpP7e5mF;qo`%<_M1sRwTfwqGz!|}UcfP(xoJO!r2Z02Ov;T)an-Td$i|&{4B?IL_ zkV~M9=g(Mln*$$5@UEFF?q>H%#B}YBiMvN&WB7cZn$bWBUznT2db`uTZhWNp>g~FZ zF+O6}+jxHXQy{YF(AghaYo>99lvE=oO|U<721;HlEQ&&Egaw`-p8B=$fa|~0QU>D8bw2i< zy8L8bM7_}$Wa9GENKTiJwLf%}eC_QwIYZMz1|Qe^rQTi;|M?kK)%w0;%{XIy_4d8Z z-B?J~Sm6E}dF%1?|1lP7`rmq7#i_TeaJx=Qw91}@G$5+%p;h+9H;hMA>dfd^{Wv}1 z0yZ$?T$`n$yuc5jg6f>((1t>`!kwMulf*DAX|rhuHJQA6ce z)Q`F-$2pVolq1kgC#;+*dpd66*7p7?+tZJ4Ztl^5r^-HyHrUlbP32r)Ils$v_5NaN z0OfLnEg*#ks!#(nB=Jj?tr|EfNk(k@l3X{Nb5IbSG#YpcrLLuc-6XC#~|dkSumEri_A)X_kfN~u7|D!v(sM#`|EGHgbMA1#uB6Cux|CyJ%q3ignR*){FQXZta^aX}PIS7;6R6wx`*3Z)>< zuUIIi47{RP>g-?Xa!=HEmO|jH-kCh=9^*phyqdalM=R5=Qs(C$q2unr>|`X^o6PA) zg$bg=3b9*TCOo4B=*NQhGNjpZJ$3m@#~g=Hf#93c2`aAgy><5`W|^KlAdQ9tY!*4V&*42aCIf1^!Uj_6K|} zZhsChyE%u?FD<>x^_di3eY&v+eI{OgS{$Pj6+89m#McbswA2zQ^#oM1!7r8(MT{vyq)wo5r z(6?#hXy^cam;RqOY93IAYx;2DQddQSH;^HtCIs?$_36`+6~v?o>eK&FAX-uL7`#X8 z(|?KZh>YCgP;Px%y|zBTbh?pTL`-Z3nZ(2elEeG+zVt90q-JN0ma6|4? zJ09@4jPLUx-{&c?nZf69k)?Tj=MN@059Rq(H+GPk11I0|o`mFSntmNfWooNw=tt}`pl;OPteqIn`{pyBhmzLFIDk11We{#?W9MGwy`mSr;63aF z!2T!lrWZ63a^Lxq&wN4a$2|`vZ%dEm2Q(DRyXT=?Brfm9`;Ty0a4}=`;ymDaQ8Xm> z-YEq3{-Zo(rz-#j#M)c|xF}b#i9>Sjs)n?6P1w3F3TI5q_bDcwxU;oWrmMu>ccKF@ z_7nU2K2JbZY=3{5@B1RY&%J&AA*G1u%9q;4GeMNacw`cMW= zq*w!T%@=4@t!iENZ`~tlMNFDtzsc4#4{Fqh)W{d8*1uUGJP;k<)t7-d^BFDr%Uf;N z^Ab>Fh7iSCKU}L{aKFh$5rgQl5`Wq2htD@4f^?6UEqwFaG5vjNy?Fkf{6Ktvm-GJs zx1t=UKI$~i*!Z{>wkZ!%<>yf*;kn)qL>+-Tpo;o?0q7xz^-;C@jlpRXxO#~_ zzC~#DQfWxT18?BEIr2p=G?>x+c41+>`Mr4OAKV%*K8kfn7$4sO;jQ>+GsgJDHJS!< zF`oqXux9T29(|%ZsG{+4q;8JmqsVRX)nXfJi0%5j=l6KH_Rq)4zExqvFau+K;u2+U5mEjgl;zWXf&XIvLKK^Fo6#IP4TP06r5g#j1yjuN3bx5u8v6MLn z@$vO7V$>$N=%-Q(W^AaY3!wAy4V#G3pp_t5#NRMTeCNT;k#Aze$78o9jt?`xf~lv+ z@EqvauCnV0)6^(GL;1(oaeZCt{X#E#>-|1D@71&;U1k;*2yp)4Y|&g`|8TgATkqH8 zFw{T3KrDLaN;22`9d9uPGxh#B+|ah#Bg%X0{p5WudDkUxTCJ;)`|AC%g7yi{lP`(# z+p^S%o5fPrdGdvsEr4Cc@C{4;uNLIPAJ}+ZfLCCk{RGzFffo?lTH+2;K`W`C!>~jg z3I5+KQBrU*sCXvy`=VywdGb5uPR@pFw?TOOW*Re5g8+P+XZLsboNm{{_&m|~`3m3X z_P)<(7ovEH-{-YIhxg9+<7a~Y@s3)yKP`UV>rZ1KL z7Nm~$kIM<~aHch)66qf&ej-QyEayjf(j+0U`^VLKffe9-Va*C~x%}nykHc$c=^k6c z%ZhmVAJ{Wju9TW4A7BSSawIk6*-cOJiM4#X2wCa^n zx2TZDnUejj=@yGnrA2~i)5S`Gzr>*C!P+%9h&I(3R|+dVcOmZN+OZpqcci)pNx$uL zk;=-vyE4Cx%r{RnF4A9J1Pc>rnUh3xU6_!Txs;?j8PZt}JLW;sQ&FN?E>ajHkl0u! zzu;lg-Jn)|xHc&goG2Lq-@nAYHlbi6tSdUX_6C)6F>xsH3#XGRQqEu*P~m3Dkzga- zOxHaJ7s30G^=`7)rYchne6OZh5s-| zuZoPB=zIm%<3{eoxjOE|C;&z^Bb!h7hydn@1H+C7W%ZR=+?@+f$}~= z6q);`@Ft3^6LR1C%+CwLCwQOvNR+OYTb!z9=g*-`4?vHRxGcuXXyiO$|12*6Iqn0A zAjgX&C2~a9I|q@uE=S?#oPSM~ac1#8WaP`f@Jo{~@%c6TbGZ2ro_Yx1=gyToN}t%i z*HpFboBWiwKANvJ${s>Vpv1F+0gb27zQ+e!_FW}j;y}O`5=2=*Kn7Z%v}y;_(y{r{ zg@Ea}p>5yKly_I<{rWS)d*d6%zWs#US07y^St~((G#k~dW#1Bz+EZ`8$s~k$oGDrn z6Q9_XPX>nf_3#R8+mAHCmD3CctW-f4HfIp*CkB+Gpus7iV!eGUe-4kZj`!&$ckEAgrH$O>7$Y0;C2n`d5kiQ)ax#+`mn!lG&en>=gj#aCw&-pOqsuV54F{Z%=3{seeP?)P*nRYV=@qARvFV$Qke{C zyIha`lT<@kwH(L*QFYFoL5Q(mAkO;k@1 zmojCBz&y4DBCK+Gfa3OuC)$?fM=N9h%Ik7Hyo^ycUBms6i` zGsYd2>CvgEPts7Iz$f~ocvm2SKlxHE{K4l!7@&=Rh3xOc&#m?NzwPgf3CkGCR~6y! zZ9qtWUxH8c_X!Hyo1QS5`&<3}$0oGkf~Mj=jb5eZW`oM_@2zkrpTCEf_4eSY@qZNQ zG3LL@yZ$fr)=Y$y{r-31_R` znyS3FHl`-tL+2a`)+KNH@;^_4+=riIUx#Q3@UtX30n2|!RPg2F!t#6R&5Ge0Lg*8{ zoOhxX;1xLDenNO~r8F+;?C+_dl~mAvm?Fpg*Zg0Gsj0@aDHXc$?VXZ+9CqUOYhP3)E^ULs>gsh7#xpQe*E_4k!Ed z^&^;jx9cydugi!5Eqk|B-uoNT-iwIzY2;0NAMY>rj+pno$P+woN+L*5UspuAYuS5Z zik&aZFpD7jRK#T(d&CUg?R7OTpuYYK&?#xDJV|}^bty9U*4GD9vNRv|Td#_X7h{Ok zaKQhAnKEjDka#gxj3$C~=l8)k`x@s9bYX?_enV<)I07{iERil23l0R8A1}(`PJX=D z`;|wYaFK%^f3oo`gBT9^PFw@|X5ojFFN{yR|3NYS{G&#`>r}piD&IlGNF+F59Oc^y zD!+U$;7&gIj6cWB-`mQ#{_M}+TW%MX#L3^+K~O7y&wU&M>+IAOw@{%SQmN1g))X;+ z6B2;~BS00+-}O1@>`z1V#u}It115jhlsj56aFsIOb0?XPAoIp#&KSrI@_6|>U6Mo= z`MYFQPdtn$>&f5KCK;<;qjKD*ay-jkclj%{+F(#2T9Ci@it0`N-Y?Ls`Fk}{8eX!A z6q>)k*f06}D_(&ozfN*Hf3MXmy8bVNVg6o;zwG?|d|5_VYW(~i?(FR+jQ_;We^CwW&5v6TBEXtGxJS>UJ#KRJmb&>8eUH~5c0yq{J zDo#=#9_Ax+FCK0$oeexZ_M~UNesSwUxrSr5(oJyTW&e8cDX~3QCfoMh{*bqxc}jE4 zGxe!coj*GKGVS>;NKJn0E?$v?`Gql8d+jOj@@a<~+V*@#dH+XP3h4aNBjincRu*z! zJ+nlBJV8Bk7m8WSo}XRit7mRwB0wOf;v1Uu1#HIQ{K74~0$T<&S=`;n1piAaXgd|O z1~33|J6eW!_G4cJ+D_nc}@xACRV#GN3 zeh*TNfZ@B^pDpNR@ck}LNKe(H3(RM0^22_gYR|ajuyV( zt<2BgM&`B1yf>NC2MUAS;QQ|=@~r;sV@U%tq#bfSc7IkIWwqrGv#wNppDDi}WS@gJ z%`|g0=Z-H8$M-nzgn0(eQW8HCXTi*H>e+nw6Vp)zc@6GzK(jznPvb5fbWD|XOwV@{ zcbPDX?h@|dxXWCzqR(A+$(@|?*GBm1SJGut;~_li-&~kra^XStN9Ibg>S6g@$od>^ zex0Wuvg?^-js{~c2LUrGfROdfRTLMaJxRO`j*SM#QAOoj>(YY7(B(&hvqo~Xy%-$c z{hafInd%ul4}v4Y8m8Y@G+cfVDlNz>1~B6>@eng#9VqF>gXF8-U}@Ly(=~M8yp_@o zK+zQm=A(3hk3nkiZ8*fjNa;_R=esh`kIxMn-!}QGiwxKD?YEV8S>=5O^;0A`W`t;l zzFkAeefet77;yovFJrKop9|`Ra@z9e9i>dZ!qbyoBd`PTdj znd>?bOXj+tKVs%ePAVsQ$4~XVp2if$o4<<5xU-u7daj+vzl{B2;@LGNT>JU)ti?@Y zv^aS7G!lhXubzwISz|5L-n*G5Z-q5Z4xrY`724 z?osAdmH7@VGe&}whZ~#UXX9Ch=sLP=wqG(z7WHZ`l+3pMp*#G-op1WQo57$KD#tr@ zsD$e=GY&kX9Km!@Dfm?r)th>?hVqyBrV>nUK!K}Bq4ny!c#jvJ^WhaZ&JjUrOrA#1 zM=Qk}=q9C2{RubHhvGfoa}x$3 zDtGp;e%9S&#k`eZob+J#+En0e=>PFt$Ma&yz&KDLD>~2j++94!`xE*WcN{6k{)8KG zb9aA20hM82Ez0l(<^ixDnKE#HLOzhj+n=EMMssz%=g+S|&28;Zc&V5=le2&I3Tdge z11zd?v{N|(sQpp@45KbivSoGmC)C3&Tog@shROemMMDXd;fHb;3ptaN;jaXMz;qP+ zk>I^#NaTDDfF4$R`#{LJRdFBi5FnGn?NF#>p@aqzt)b- zz4xB$MO+)E`0#7^^$GFoNkF=VUq5v*F}qQVkC`{n z@Xw$+iv){2OT#Y&RTRHQ!+&zP|9)Ok$M`Yu>weta#jnjOLm8FfAJjoO|LPf$f%sJ& zr19`;`wK#r7{5B8F1GM%9h4}^(7~@Gos2HNQ#mHrpf36mP9j67i&db4E}Z?v&x#$g zv%l(tBF6n?f7P>c7Yo03DZ`4&@FJRPoX8M8THJT>R?9 z21K4fUd77sD$Hub-g`<|t4xa5UYz%7f zY>p4lo>bl~mG>Defji7R#=i&0z8{k%45kqkUF|wbR2OS)|@0N5j<*w_cmbB|0TQv~t0eW|*(kZ_oY}#%TzR7Q>)b4MJs;D4_ZG12m)6!h z-!w^cLSe#Mpb>URM}mU}(|%<^YVy&^f-+={|Lp8%NiO8IpUgLHY2%H`*OhmARr=0) zE=!#oWb8LX$bIuoO(k6=m~YyNV%Ew>jUcsWKg%W}E^3GEq7^aWo#>4)Fg*XoE3n-R z(gerD)1CFRSt{t^DipK^JD64!H28=hO$h5}5A)}+xV4{UlHAF+e%7sEmIlu{KRuhz zwP}hkKb@;6GREKk3$(ZLQ=9e%lj~}UmrKXEhq5NwvBddl5sF+ZKUKy+to$@yCXBScZm4pc zzLs({z`POm|5A>?BcO`rr=P?Q*~w3Z^P6yx{8T~iV&$jC%5bDI+`{7E&nIQzM6$mz zOBF9a-70A;i~O_#1+Enp)giUB|CdM&MEg3g48+<0d$Ebu*9&J z`)jH_V<2;;%JC`TC{T~9zGWy!Fh8gOy;z^ST~u%8I~pi|neV8;3^z_Q?v9z`En*X#!9bSQ6^FVdMoMZjOaDmC7isJ7>xpIuZp3wQOcjao_ZHNt7XH2)sYmB=`hy#q8C?`m zIR>d5TZz9vKSo^?0#y`$JK+}D!r!rx3MO=bzpI<#cNYE@R)%?%VHYxdoD7M-lRzF1 zf4`KxASO*PztP|_Pt<$_?@|1%$D{)MZ72@q;_vipwLhrCi@@I^AQSw(o#b)xw-QCk z+#mdL34>42AB2}J$-(@_r3(<1zAyd2kTh>SxkO8)CFSTsC78)7^`+@rg4EQLGyjtT zXTP4@_@6N#`vIvZFW%#|;&SEPKzYB;@?q|y!kbpyD&)R;^1R@3f_ic!%2+FNp1LTO zvz|wMhPV!(8jf#RPd>3YpA0M#e2Q0KwU(p_9%*jCaia=4nOG6%hju&?jQmdo4Xy$e z>&Ywmb8kI)7p3*CUnYrS5;qXcr^BuJkPDaPpntghUr1!^odWsn{_kO}TsD=Zy=S4p zjs)v)D1ma?6#A|Y}p0oRc*WR)pYmUUe6}2#}ObNGC-q(`%;zx|V2Mf7xKC7^# zphW#2Dpkwgc_6jb|2;1EMzl^6l}PjOSz)b|Uf~7l|3Je2kED#$=<^PvZ% zZERwIU-zL)Q~*`9e%*IgK4rgt&3DfDgjuiK?!)j+%KRB+UV+RH_clK94#?xxuQepi z$dD4$ub-oYw)~?4Mu1eH?;BLM&;d4dEZUmyL$?6;=?c@_u+e0Nj(Yh{c}{pw*4V>6yHB$ z?f|}jE-DdlXfsgf_detW;QNap5q$rYq&|F~BNu)6-e1O|gx59u`zao{J1FiF3~cw=sBh%4s9lrgUDDHWmdx&Uqo8V_bWM zdUM9UVw$yf;Ul)U;`|p7gf^#zq&<)yrbQ}m$0gT;!hP@Z@^9ZT!TACQ{=!{NzS(_; zH{ay%%AEaXkp8rTOQ`vJh)n|@gVf}k;gl`=`DX6lUVoB&(*-xQ{i%@hE~~sdkoTDG z!khk7L&$ykW{;qJf_&2prM2ZxJ5KrX%>&F50D|uLhAvgEk&|ya@CtmXhGvp$5P1&x zlu|(lm7%7K5@bFRyBC0eWKN$c4sy*$ zczXwVM$dztA?ZSf#1qV7p9fpOoRp zK50khzV&YzXBPP+Tx4nv`uQ9FfN%z{=hpSwtC~Vln4ueJgw+A~e`nfj7)Xu1wu{ws zV6St>Gux{=ZfM)<2IbvPd9TN+KqR=kld;!-w}RYfud0$t64>i=l%STqDnM#0|1%fB zUZ0CfB>%6Tl8^fpKI8?-{~%%hC#la~bL65w|I0YDve&eQd42fm?yq|Bj|nnKo9O)p zkN*x~X}?sRi!|>y7t7`B@+!-9E@2j~Wm zYfq2@S4hV5=*I*Qb9B1$@neoF=u0R)?>8upo4d1D$yvW#e8q*NHO-)}Jav_}JZA--t9IWe^o@X67@c9mlXBP=iv z69bW81IiJ&B(P-OBDOd~K50#oa0lMe3`Ya{euKqw7po50sSJB4!+K=6rM(QCxoa%Q zQHRt89(qnpm1huxlHz3GdSWV)cIJJ|(@;KJxOf?)Mje6^Q>PH?fr)P)6%O7vg=HL? zpO^Uf3ch62^Z>cw4DrYXYkfG=7{RVjum8L&J{hHVFdE_5eGR{7n zKUeKdBhTecn*4R>YqT|0oVQ!^yyAQ|eS&(X#n?V+cn1Hn-!MLtBg@pThppT=^yN^) z&?UzqhG=c^bs>hthn$P7-cIZjI9>~y<2ii0BEh*wL{o}Hnfv6-=QwOXV%!3CP16u+ z)CSXWL-mafxd&BlxcE8c-9&lcK;8@5y1vn%pOE|dn%qpI;+BJ|i9g88<=}13D-}0q zgisp0PyloOi}5>ovO^>|iom}c>%yWI$&;@#lP_aL~pFalzSo>i{%AI@$Z*|yfaKEw9Z^GWmNS}7R=d#c9G4C%K z8g5t>ovMlFnEmM;zd%CT-#=g4CAW+xPJj9a&|N^(d0$B~Fu)1@Yi~t9Ne`~iM{PX8 zX{wuA(`8Oc=$ZBYj}FNv3A&_F+38Pr9Wp*+`qP;v_SZA^t19!R%KQ{|Ea3UiR>o(Z z1i9%?S%XCT)BhxWh%B?EHi_Mzjzsxt`Ohin4tc?OUr7smGX3cbdN+ArNpI#QrOwjs9PC7bk%Ciw}wlvXA!% z4;q^ry#EL{wDJBO<=tL+-$CB1TDmrGFigmOI8mIbC_dg#Lk(`>{bi6kiuaS5O8^qn zL@fdmQ@ab^=TW>*=T(@nH|U7>lk^9EydNc(ec|6)#+x=+gHkDMA0PlCAj<({p5v2Cu{U)L`Ou1dOBBo5jImZ|n_CN9p%s4}l z{8ANz_oG$N!;xzNbb&x#0hv}5G`Jg7y8gwVd+~mf+{tI~ZU?*ukAe5$dCfiVy9oDv z&_Dm^_Q!F~2k*2OQqkrqzWq5+7@COT-| zjE?dcsDSd$^GECV3FPLe13tFTah4eSbCPg#xBH2x3|&-)CX``AQ;~uDa}LXdOsG%H z_X`zcLQ?;Y_x#c8N24GBWX_L)Ko{=*{qfQ6Cx2yTyj}lM7Y#6_md1?OByprvRO3CT`9>> zOqyVS&I}ZtR@4-Q)Ve=sDiIx-?46%DEHK2;;6v7SE~ zC0~2{pA_~#GWZ1hbC9p1{@&l248qG|$Kr9Nv3Oi5l>gD)5Rd*|Mg2WR&ND@N3vN6| zf6wxL$cvFbL`zR;vtJ(A=ae^FG}|0y-~?8o=8FW|+#|XVTo8mZj=yzJjvfEh9^?3_ z7>cLue+xHv9sgUEp_j@~pE7K_TV$Z)4+N=k{Dsoq19Y4hJ6_4esE#l1506g$MBj%z z12w3d{b0_b7>GFjqq-Dvypqwy_bSKUf9d!O0o;+`-IOD+0aQ`P|5^-^9mhY37dAPL zp9;r+QSM?n{%&RXs4~2Z48Lz81E=G+0XfP$b$nlWca3B*F=>MGZqBbB$1e$~o$@XP z=Q{pqm3K1*?y zQtbV}Pa_wIww?1FR+TqSGh4IgdyK@uxA0*+|J+z?7?=twXwZ3|;kX~fO?WnNX8w;}V%cNqt|3gp@!;Mic_c@Fyp(PcYv-d8qKgoJ%O&=gVpv?C$6apj2yfK**ka8;^#e6?z zx+D!5QUX9KiL%+s#3ObZK*Deg#bW z3dDj*C-@^`lIb^pm22Jv&3<#<&V&vE|G3ij4}31|`&`ubxrpyGR+*#zh2NL3KZi>< z^wh)nzPkN=*7ZTN?XC~{>x11V>4RC;2UC!A=#E++JR_4qx)@MfYqJe>=D-5x=2~~s z9oup;$SsUN{w~M$!H(}7kJP0hPknF(UAbEy+@dnvr7~2f44>Q~GO#|_4AOY@!C4}4 z;`(41>T|0;_ygJ$lymBXt!0cZ>Z=^fPBAnm19T(7Ybi(IeNaW~gLlLr*{KhVup$|L(Le^yaI6LLc=f?0$pTq~<0w?7Ryh9stqI4JNU#q+3B=0o zqau;u^LoF*_hY@A2?hcAC`sBw2A;Q+(dG`VoICM4qVXnBN;LN1FBpx{{j%+N$ISIX z8PQ4N`ruAGJ`gXL`#uMJpRxTV8h_!^%{}Yq_TiM@R`0(N%!|{#VLi9%qF(hs53SJB4ue1g1nW^e(7g0sJ2)r&J_|qRmiA*cW zDNV4nBJWWM{f(v?>!~g9`l8TA?0ZB?5Z`(k^Yq9|JIb06Dcnr>2dA81h&*{-LL~3) zGW@_tpmIV4X#f1y9K*%ztsc1WtfRKV&0V-Csxp*P8ICh*UZ^KB43l-#N+1PXB=bGJ z>jdzk?Zn1ZAyc^cP`)xN$;He{^1Y~EEx1?#wF+E3r_lLUve88em1EqW)J31uqKmV) zQ5Qo%1zpIhI+pMT;1=0hNq%RGM*|+ftc+W_8VD-q63Y1)a1-k`0BMIjRJNJC)eo_P~R5Lm% zr;f~~ zLqh7yGAkGwR)up7b0wIfa}DzZ>P0o&v=Mto{U#Lc7NpMnhLGA5?@MN$0CwDrOR~}m z7sBW;0o}4##vbg*lOs>c<2x?2o&(4Wa8}{32%J|Xl^X?lAd%Bwm7+Kv{H!be)xK|t zpO`p6^oKP1)BB{#A=B=WCmzHBo>awcGuOZ6!`~$VdGI~bQ1tt7=?NbEOx$mMvH?Si zSs%B^AnL^Ew@@D!gaSm>PJKK^09Ff<(ORP3a*Q7Hb3yT#cW$A_^d!K#{Z^SxQIE+^ zecX7HaU8QAQ%vq?dCyp7zT|f@?@8vB$eiBu3t~|FEzDH;8uosY1Y}4F>f^sriCW&% zbE8SfK+NUPq^XZj2&QVozKie*&)O@hw(H~a8O1JF$J)rRkdfa8u{hSZ{E@dlUc-BO z9E$aEXd@jeHBJKs|G3`vkL>27$?IItsOif`J&({cQv5rcl0EsTSTrB)0lJH7-%t#` ztd#MVzcd{e3e#Y}0A?b=fpzFDhf9jO-17C$^a=Qx~XiXF6ZX{1=k}!f6~Rpp#rp1aDgw zY8+aVQ9hK9IQU3ngLqF*IMw9**E)t%PVo6^JH8Na*ZDqI^L@U` z_xVQO=PJI>*ZMw}v_FS0jQ7vCm9@XmZoJR=8v2Y`f6h9@c+YlqirW}Ee zpn@)(`tuYlldbx*{A!N|JoRUO+|t#+P~|-FS8AX$IsbP9H6Z)=ekx84#H>H>zL{Z~ zu>RbFGT73|@C8Q{Uiii;_ z6hWy1N~vf9t-MMqRaRM~TEzMlwMq&oTQMyX9|2TAR8&MnP((zY8)-RI7oi7<(&L6bODAnIcQG_S`x8+A>L zsM#t^q8fhg#E6iibs8Hb5dP7U!V-TwhMMHWUqKN$zUsPX4#A_QD@gk^g;_AC*%cOVX$k2NOxY4PX$ zujrf5Ujn|Uy)Hfvp}UAbk?&VXOoT_Jp9ws1 z3$Y7Rs^k3RXoSE9@i_+Ckz&0?Bgxj@T|fkpqyJLi@yQQNgxBGa0@jv{hxG>Zg1>}` zO(oJZ0VsjgUBKu2Kjl-&==$zuEZRcc6L5{WIv_+4$U;KkCY^2Q$6vOXQCh z;ziCMrQjRqkK*~cH6lf)Y=&5$4rJjp&%!DvU|rvi=w&_7mEH=y-+AYnn({}TLhz}G zxGC&AejO<|U*FYX^YIK#j2lR25b=9q>@I-+WWZ5QH&gL{7T-kvi=SH^z)Y2l9D)C< zhgdRpVWAYTMhg6|t^t2bb^Lw39}Qn$2KUFaDY-?(tl5VB@q1PS9oBJMSUt#~?+J}s z>p|XusV9|C>p@#l=5jds`%fjlP>8_Xln3tFz$gRCkcmAkBU!+{c2 z(QBv&iN)ZW7rjN`;1oE#$N8f#+7b@DZa5fCkZZ07F|iL5wx_mwkg1464PNwb5RsH! zy|3j-vrdcK1s)p@FfGiSe(%V5m?iX5V=55n1LDJ_q`mjA4w^cw8zN~GgO%$h0QMCC z=cD*BVEw8MO`M(NH;vfJC2)==tR5tmd?~TCj(QO9#tq4)u>Vj{j-$b>z2wZ(JE_Ukv)Fu#JU2 z{_zF$@fmbvd*Z`4@%uNz27l67*T;!MA7fb&%yulrkZ-(!Xla$vE8Lz;#z+QVOCMq1 zOwk5=fy?8a@)n0TE8h3X1!yWg$A$NL{>ZQ%sHJ}E_0IvgMtv>)u6BJrkKaSOQRwS1 zvCe-cR+rIZ!XerAvy5(LeU%ewnr0_@1@*NaCU}|p+WrewT3uv$@;U1L6Y@%->>u@l z`uelLVg5eGA)RrEWgPOU>qd0d_4N%3MIjt&8A}!>rfE(AJ@V#>6HNKqI)8`qU0G0H zQFWibO6aS4dgbOQofdw9M^k}EcX$%m@9UWsap)D)*MEo)YJ^ffs4Wk!^V_Wo(bx5n zc+a4(zYBox?&XPZgXzb#dbQh-IH@kEK9L$nV{~BDD1ZRs-`&j_)>J z$E>>sUG;iZJ5Nj4_e;62Gxsx{fqZ_J&L?cUm=eOpxdQf~Z<&j?F>HxpGZ){a?qT(+ zuaOt1qh9s;bs?O4`BUPY;eMs7*o%OHHar36Ov>bY>ybzXtj)LuR`vuNe(Sv^-J~rP zh;|l;4uh9KUeiWIvL>My7l?d8WDYA3`H@Bnt5^N_Q)VwRkonjZn`p18UUht^$T`0aXm=6;QW3oW^4x$BdPJ?RLI9=`kxP1 zsLZV)UfhXTNQ)Og7dW&OIK(gxFI+=7aJ;yP!={?!#a(Qz>y8%(tO@!bL_wQCL_@rI zFGg2a$ZG^1v%h9qTwpu`EtwWc=oR!o&k-LkC0<Wk9#a_$zOF-SQ82V37a8RVf3DW zS3UlEljASFjCdEjkN=SW;!ybq5e@Qx{Jc(!Q38+IJD3(vaQqdxifK`bUIzImK3tOg zFAI_X=V%mz{68fCUM~Rt%kkF?2FUW?8{KP_e{ul-CI5(jjq?AYF8}O3NdD0jl>dQZ zz0{8zN&eA|<)6FPF8_>54f0QuuS@=W$AtK2WB#R>O)z}Wx(~2kYK@MpudDHmqrzGI z+?o=h2N#=!m)yIJnRgQUfck|5VxIL%^a@`u^}$GC>m}d#=#YG+@9{fojt^_BPoA^{ zKv*}!&oBP8nRT;_k~`uN*l`tG}4d1BS>eZAU3T(cKo@CI1xmmynor&`^5XIn79({SUvOoAGCT-z>;_~_^(ATQo#3K2n9kiD47^iqrg4^ zd9Z-oi6L*gf+;{5l-B493W)nZwufd=8k4^x3VcrOIt8%E4pLw?0%?N`L;-!G0N)rQ zn>U`+DR5ZevAdip@ZlDsKzGK&{1$qF0$pjThV#FR$i`G#r>T_^h78Iti&P2>O|-*K z4x&*E9{i{P_>chDjR9_JLK9~@*$&-dC%b~b4kyZa17qk~gMZmClBTs%EXn^xS@x(gwF%kKy{&o67BA~ERm*QVP zTd0eSUXM15Ml{IHPXc&50lWtTpKa0Q<{>s26UBKAh8e7|IYjoIrc{T2%|YaCkel70 zUC_UFz&E`fZMYbX?ypN@$5DmzvqWmh6P&AL5j)IwZh~)Zj!qO4_TtVEi!-k9`|CRM zkk$R`zweNA46|Q?e|7(srxinI8}^G@ysgPV_<4yVr7Q#gd0rwH4uNQ=o~O*Xpqmb# zSc|^O!elN$q6hn5jaeM7M=zKTH4!jz!DYMBg$q=Pn2=}>KTlcyZ_teXCUCe?;P5XJ zKB%`g6Aru(dIMecg;3aeO5tyWL96XNW#)%LGYVFI32KrxQO`@f>DOs-THqmagK0RtLH+!-l$Ed^3cb_loi8yhJDV98idE+$DHkqP1CM z3U1_fkTL>2Nh@yQH&`oz=Oq$(#1MVp^OV26#rlv9eaHoeA@PqS8;gB?Cb%a1Kt%lZ-TSdFLwq{o4PP6u!#03oORXTW+Nj6Ts&-B0bN=%O%BEKv*Au_)}v zP62-Zq5+FSQ}ha|#mF}=TP@@_b+y3$Oz1J=FMbKC#Tx>Lf4^cJ`ZErXG7hX3)6rE| zi?IB_3O49<=Lc?E5~3FG%@=B+?x!}x=xT)dj=;ku@W_P830Qxq&$Kvs+^80VF~lXQ zg=fC57L*_RfJQN>#UcSPN&q|v9t5mUGC)>~@#wCrMOc393vwpJ(mM82yCcFksKqi! z54;5OW8K&jLGT?UP}+X#Z@ol*pffi@>KmdPNqs7JXQ{7gKQ)n236X!!kNx(>f5?Bs zzr*Ffj^7KqI8T%P@c7_h3Cn&B>u=Nx4TOm&GL5F_6Tgf7tIq9ou>_v_B}-jLY*1n! zGnTo%61_kcH9i>iIuS|8SoQdz`rTo(Uk@^!*59`rQ2U_7% zNd3=iEDiSBq65SI#>o^L*g!7Y)y1+JyFYTw#km^)X@9PuLFoQXeN@I`|7JCdg85dE z74xab%D!0)GXU`ts<8c>a0O z!235-iG|Fe3G9Hy{*9gH`5*f?zVWw*=gYMHoI209rOg4FoH@g89%V}O^KA>iV9mYs z^8_Av1rmMrJVD8ix;8iN%>qzd%-Z}C++o0aeKZluJR7}&e(WvC(Pi%QY?!MGK@H*E z?HF8JB{vZ`bQU<68Hcx{2nY6KjnGy1V`1kB6t?=RjUiK2!+C-y5npSoWLW1zAS-C0 zohO)kM5je_fyXkYt~rMD+|3yea~^tu7HW9+GI2%??^cpE5jUk)KTl9LM^^(otl5n; ziou$-5CBsJz}bh0_=_WH;;aGZe=zv5u=50e#GxCpbR%0csJ>>+PCDg^PP?(PRq_#D z8?4z+v&F<;rZ+gm>wy-1#q)$1Q9Do23eSS)39{6OI8V@pKGG)99q2($&~TpMrOx7~ zpxW^x5Zi>#(K;s)%7SW9$dgSzwUUj4dQZx9?f}Kh?5!* zHb&5;#)IDpJVppSK4P)n8K9rBGb=wE_2?c9q3KcedL6^LoM&Iw^@!rZg*1vmkM;|I ze=_sTcQC*Q86fM?XmqbF9(Z`xFmk9SE)0 zxk>osr7Ky4o(BifzfE@c;I0l#RH@GEBMuu zM>oU+&xi(&2gZ<-p*e`n@ZiB>F z+b=t)Yh!C1hC+z<-3n&u+ejr~{qirf^j7qO*sAgRmn0dNkt0@YW1`<9VH@pO8$!%Of_f_Ing&a)dOcI`Vn1AUHPgHxe@l=JSSvlDc=B8Ns7b zKF>uT$$^b0Qj2_EZkovF<#7{qwih~)&W`2Ith3?yyb(NPh`#cESqGv^9r--pkYB?6 zRUPZMJLTHsVZukX$phAJufpyV@znDk39$XDbsjC2Q02>69-iVoiCg|*c{m*+56h+# zd4!IC6^wFf)$u*kL*;?iZwqKdgQXrLfM*Ecr+HuCvvayUJdN)9`Yr6d#|1LzG^IMu zd$?Z>k%!Zu9p2E+d#pj-rkdd&FYqX15}F(ABBkiScv$C9F(@zidK2lH0Ce6XQ^2S5 z9=Eb@f#pcy9^$-5(a*Hx>&Pt-oO;~d_`Nytv2~_eOR0Pz@7|*(I;Z7_9W?BU49-AW_s!}mY?C^B-a0DS$-nXD`-zf zy-4J%VxCoB|5uD{AQhhs@P8JG4&TmxF;sqN|9!=tQ27}ufY%qmkAZ#AX9mtbVhXy~ zW>40VE1@aXVNZG@UN_j2l^&x#X@qaOJ-JJaM)o9;eH83Tdvs9kN!N2C6Kdlo*psuc zxMWY-a_1WDNmCxOx;;7Qsaqm^{w|kcPkx_Tn>9V!no0{A&b-F!a-AHl#`9z5t?n>>6( zZsJT&Ld zHOfOY4_RFvw!QEl^3ZU=WyFJr3pIJ5cyJa7)+ykW|52TVQ~2-KmN0Xlf!g8soc?0w zK0>s`rZIkj1n0#`s#ITbDfQb+rs}-a$ltga2fi3@p+BE z;qm06_iEF3%KuggeOKd$eK4$AwqLl;sf&5G9XHTyPo1LKnpcvw*5k=hJmpJ|A7&To zGNGRr%?`8wiv;lc0{BYScNYU^nYcx_|JBcnt|d1?`d&x;&~s*pe5`bb#19|RCb?kw zQh~=5CZYL8RJa7Jznx^37jaPyC5#*5^$YW-H%G`@C=>%Fiv z%|tE(S8-{1O&edtbp*DXc;t>DU}o~?s@UBpa%Gl9EOrSTwm$a<(a}6ah#i$N*#g$T zr!dts*6P6p4amErh95MNQVqo{EuL2;ZvxGGqRk&G$>$Na+EAl&5k5>yRQ3}%$UIT= zY>r;f{7yJbq^{qfD-tZYYYEa>YVp?(4VtS+}D)DAH zK(m4n3WQvS(E~$j6c{NWzwi!I;K*vC!0F$Z0`Z_gb94m-x-tdUVpG{51F7V^hyw4S zJxBq(7NkHKf?xv$l7T)^U^I;+o0o3aDKJXl5m>-@6f*_>$9S0C=miScK>7xky01lOdn^Jjmhi4VhH7bmlRqJ;TcrmZIv7%Wb* zlaHc_e}HzLxJcLY#MN|tIpSReC-4PamevJWBbhM){vj)1ojC!)W|ew(<$CfoDE-Yw z-iMtIT*-2D0MkMGOpr4@9PMFx_D@iLimwM^%;0`-FpuC(T$tyI%aBn` z+McKz^A4fOZsk>cQr*fRDq$Nq5u}lYOOS<2kcCU|K9X&$&VYXz@>}@&^gr_PgP#NL zHJ;x{dXt!2^Z6y5pZx?5fT%iCsK@i=x_WrTLh%T{Z(a?Sp?=FpyfP0(FAzj6TPh!a z+4*??cvVblI6oWM6jYSy0*9djhc1jmg+e&+`Pn__3PlmWe-Kvv8PA?gi0n$<*Q$Pg zb}nLQO;Jz*9D|9FqNvrMPhxb{b-pa{*fXCM<-%J;i@O*PvxHtG970h_h!3i}Fl2SB zSAY7R(-kEdtMo`3#gOHhBLLBSXxK*=bMO; z4N-g}U`-Pj)t_@u5F9APo6ib`fFi^xmB{RJ7(bI+A^sz|pS2foQDeGy1lAwD!DRXl zTnkte7;Ecw=*3}tGQYkLD(*7eUnutT`_YJ@)t{WdZ%M?e>%7N#=`z-9H;>hHh1P3F zfS7T;_KaAH_+IBZtY^yiJ5Cfae@;}_)@!@Q1vz~w>$R$JI>Yt#+6W?wf$RAK_7ej3 z-3)u*&jg#f-i5k{t=HO-!>VJw_9=o{1E*U9>yY)@Qa1Ns_6nj3t=B%rUI;UKF}Hxx z6SAGqL}Vzz94*7|oHkcAuaPfi_)h`!bvp z=~A|cpT?KzCZV&)o0RcD<`$ojtatc{cxCR7UaCnz{Pg~q%QlbO#;CF)w*5mQsjAYT zdAwcV&|Tm#7h43V|M-z`;A_RUqbtm#xYqV9GVl~fWNWVTDs|x9!&?YwH=F) zRx^)CxEu#H$x8GSt|B&Q9=i)XK7Weq_Bfg#|qA+Xig6Cpp4 zx+On^0wIyq3=FA7Qg#73RX}dakQX0g3Q#1KgRY=}xK?bw7D)*T{6Y4c5GkZ~J(`A1 zIH_Okn~#vzK!KlJf&%x8Na_jXPgDnSx4`4mxlDnU$m9jAtr!n;FUqp$m)5?9AucJB zs&wi0!VU)!L8BN4>S0P`8CPYazHINK9);_vdYydrl2hex?P71nGf^H1I z0z+`d)f`ubrGeV&eYGPPlaTxz*DrLSxnIV8VZO(=Uq(LX=BG8Q5T4IzI-9LR4f}(1 z{}-G9QBBR~#BI=-zf+_#R`J{B;cN=7J3_oLA6w7NSN8|!KSQLs^nA|7XLK3R^EtC< zM1vsg7Qj;k@MCNP7X6?L!b9j@+kViApH)GqBcC%GQL8}^j)8U{g0>&DmCAXAOV}&$ z_~aGVfRa@tkS!Sx>w8?z%lCf~>6rk0|CfNz_kYnxiaFYG50THAvz78W*K!Nw=nPrc zkbF)e51`)vMLwDX?^gI^%;y|_nx)B(pizQl%tAG^jpFTL`tQT~-Ux)8&(!yWpc~ce z0e^o|lOKv73f6_j4^T)LQ|r=~nGVk&&4zsTVVa$}Kf3Di!>l}w6qZ6mq*&|TU~!%< z3wrzzjRB3a0C!BVZxXQ2Ahm|y^F2hc*(iMb6}pGT4?Z%}b;J*&5vd#b{}l0G-~VSD z53Y?yGY1d%U!*JBM)6m$tS66d-2WF1V*j7`$s8NSepB85r+L;L4g`Pivqt{h`-G7{ z(^iM_r&z?O^857I5iJ?qeMQ z@lchyLLmCnOh)u0$P<45j}f&dlMvBw{65OBhsJlW&`4qN-S8*>lc7GpFI@k$_^y`v zv;RG=@z@qte>Q6d;au~27v~YmV3)~?tMzB6!6DU!BNI-_bCTaTZ)WBU`JM%18}U(J z?|wJxvIDyFqg3Ij;l7TiFt`@ZY!Wz(5;&wY4tw_#4qShhhOYX0H?025#tujLmfG%j zTRfJ8MgPTnD<(q5T&+JFiC{^k1#-hgi=VvAe=~A~;6LMGwu^vHUGHuoK3qy-=-lJF zdeD0JA9zorX6z6EM+<=Sks1tG5AUOiv*p@~?qa=*aAr|xIMbG#46(G1`m>J^P#dgR zOJFVP&pu$wjBw_Y|ItL$``w2ABJN0E#El4L#-kgBG9Pkx4rOXOk1(4a*KohvP?~&Q z>(@0KFC%_=GFOxR@c3n!%(7o|{89l&Kx9(m7pX+&_66a(&+yykx3OD@`y2KW@y)H# ziy}Oc-8lFd5$V$7m+1cmnXa8j*hRWzh+j-8ENagR;H??>Pv7aBe}_e$>YJ+XN8LoO zjiyvb{PHP6NdxCwV+JJhZ;=ei)>lwis+znQfyb#AS>y*VCn5}GJgiTk7lpWx10ua1 zzf2^zfg~dKqaJ1t0yFy<_Ym>R&+93E8O|*bp4+&)v7TjwXkl-dOOs)5_#i$Rj?68+65RvP@_kwd@k;etl(<}-_Z+WKEy{chXypA-0ehl=y?8poR`w8V*7_%?dr@Fq4@v`HBYFEE z7oS32Nch7V7cLtRG8_1PE3gj6D_^oXhqiAZl8`f8pJze^Lcm(W4bb$L(1kR;jJvX? z2hZDmMvba|<8@A76gayI2kcNWEy2 z^?Nq^AY-YkJztqH4wptyZ*_Zd1fpDxU7-FqIXb)U3s{Ho%V5_CG!wftI^td|ZowP3 zP@kd$E~EsvO7hjH6A=w;14od@XB#+}eZSDKRy5N(R|LNH--qW1MLlSZ`gQX|Mt8Wm69exPqucCh>=TQ8Y1} zqv003G?DvQ>tXt;v&0XDP<*)2%|yBYpNYCnM$~$QkfilNFMb`OWLW-SXUWpM3B#_rvZPuJPCwwmw*}?uNS72k*fBP)MPjPuZ+TNeyttJm$RXd7g6ylnUol zcMx;T(dZRiAFRs0?DfHcY+adA(-C@J`Tfe^`oJu3a0(nY6%h_!Y$qJV`4n`mZGB*3 zzgqYDU@GEN!}{QF5Rrl2RbdT6nJdJJ^+3nzB}X<{AWDO3Frk{sOy6dh!2;t zKG;88R}Wer>|Tmd3{he;0kE$CxD9fL`=7Vb#91@mMfcj)2eIU!h^2L`54;FeHM0hR z|Mx+fIGtC1ku5b$+DmBC*9ZUZ7qzK{+z6{S1l`CB$=sd2P)+Lt7d@_FeQ*a&zOMDb zfrgh6KioT1lYNT!Dwl-D4=)QJUcZ1@_b}TS*H)sW`Au}y?c2#=LC#%DyqEBx&Oklh zb7DXv7v~7r-pLI6IFj}OYt!%tb_61Hn!W~-Zw-N zGHx$75b?tnZUE=rK^NlO*W5KMe%MHjVe#IqVa%&K<30WNf;;%$SqRSQ@k18n6QSY5 z>^NU6LDRG7{@=kGzrxpZjc{)!av3$O=TKjM7WS6JTKzq=am#e=yh$u&+Du|H@5F8* zT}SyR9MkTn(S zIjrQvF5DPK9)zaE8x}R+@Af0YR0F^7AHteS7j9sAwhWZi>xq9L+l`@$`6R+Yr>n zA)c#XnfVI6ATu_Yh6KbT4_vl)yYPT2Hm*dH`;hzI9>U;S_G^d0;YoqRUd}r0FDD%G zsWk33bk#TW-lh#%sHVD|*%}km{7fM|s^PvjikLO;hWMm8CPLn=KXpeP0M^ASE%pdJ zjz7n=7>?Br?lECJ%q8drT2P@RihG2V z0*{}bWeR-6>9{_Ohq+Y5I_iCITLxYt1=~!TiA{Ht;mZJ1-O1krvRK_kOGSkY#Ls z8IMfH!(5JDkO3->gkV$-Ad@2Es_Lb2h7#Gc15^qO<@??WXcU9p^a+4Z3xKcl+WO!I znmF6d`_LT`PFKi$wHxzqAQws#r}`acy|$qnyqDv{heGUT3t){12RG&~VcWb9zX#Qy zSQ&QL+xnw)Klgk*;)=S_)Y%x&FBA>DdRt6r@akV#oK-AUt{TgXT!=Jdz*@MT=xTlfUG;d!#B&sUtRC-FziTC_ zzs^p5KdvPPH1ae-zpptp%y15oU{)kY~=>Pf=AGQ6s zgKV(D%O8m(6z@Fz5Ap9He}zx`lsXvscT6-e|Be%A=HEg3q~^C4^dsKkLX_H%Q*6V1 zQkTK6<@Xu+weRiF__SEWh>xKb3QLRAtay7$2_N%E=&JK8i{~U_m+Jhgo{t>YH|8V4rX?>@f^`5W{AE-9+8P;?t$%7wU*lJ0UDK@N41yMt*f*r-Hbo6PlS{ zw`N3fKJrFxKr|A8E)*W3a%`dtSIi7yciNeoovxprVB~MzS zUGm0sh1-=X(h`#*C>eo98`v;@G*KibkvNAYq*Y=nlhB0ET?5ws>=}StsjIc*#RXva zJsEBy?&P$ClEqnUn?0|y(VPTQ0;#&u|7uH@dBHGG2;Rbn1jVz$#8(}DmZ zL*%t4;8Vc*E16z*#|T(j8VZEzN)Uo0w_||il8pELZ-w2zZ0}3IT_wr;E!P&nMDoa# zd-{n+MQ-^Iz_$(2vVHh{8>UaO4P6!ceL`;JfAGFkwA)hX;ea8ME$&46>>ihAvK0M~ zz34rNY&W}-m5jV-6DHqQIeA+&gf`}#@7kD3_S2aRulb{I+L)B8+oMe-ZSX5Oz9BS5 z(E&?gV=gO-;(@mjnmlmfT*g@DpPmMJk_o_7l00h#wHNJnMFw_D6>fS=|4H(v;=vhL zhI>*|Q-054Iw5+}Qg-(^w-PbAvn1b}4Z0=)2}f~7JxuW?{0KK%^OT=f)I-}Aw4p;R zIv|mwSn#ydZbxx35584-h+|#g;U6r?S*S4D?PBKc2K)O+a_@13AHt3(DJLr#4`Y;x zj~xy01Fv=EZi0FjhEl#5Ku~+fDHorJ4gp{SfQp`@2y07xtffhmCB9F*rAhC2OMEYz zrAbd4z9-{*GQQjK-Hz{B_@0ID+4!D~fAjEfo+W-}0U%kL$ox#V202J5=_2j-rh<4_?;0^V5i;I6Hq ziCsyGhHs$Pbq~gQPmOm05U6wp z{~PD@^e@2Qv@}ouS@?Gz{ubbG3I0}~tr-87;;#~ayYROUZAb90g1?jagVo%OFrKtf zj$mW(EIvC^vhwm%opP3xS+pBmpLZ+IyM8;&yQP?S|DBlk0wPx-F!Mb^Z$ZogyL}dX zbpO-V@ywjF=yRD*UE-9>UI>{l9V0f*sf(zoUVR%cD8`5yu zlKcwsx#mGmTbiU7C|^y4Q5=SG7^M&K0Vs`fA>J0~tVFSZ7`R^@=&=3pU4Yuj<-S}D z;_%upx~uA0UU&dsiY-6_NRGrr9+^d4nw&&x6f83U}+fT}51#j6!|TZaiqi|CTl^r;2{TP&^N% zCkFQ&Q@`3k)^7TUO4?=3IYXd10|$9XN*Z7s-zFFghr7yVnf@Jtko&~rNgSRydbM5c6dKK?mXb zDff3^FS4OEyhtMKB4P*2W_XdoH^GY(0g}J9a9YewWqj$rJPT5Efb@+orhHbE1Ynt>yN7JIE9ZkcQbu?w;ug`}aP50yP5464Z zvG}_keYDTv|1Lt`_wlzMeSXGYk=nNuZ9VXQH~ic1qmHH)%f%Qg0V8~j+P;s+yIMrR zA$(so{!dq9f&B`?J_N512>L4(5Hnm6c(ONwL3haVVOwz$`Y83ZH_3^+S~%r`N;GHU zb7M*NkQc;zNg0779FQahmmli;X@dH{#D4 z`n-Ng=r8au5TnrIMgCQi>z{SRo1p)$tMQASV4OGWIIXh~P}yk~!+a;t1Ol`Q!!E^y z#IBtJphbSPeAXYY40sk8%azLVCH3&{Nt(R-&lp(tNmn~_N|92RmFyq0bG2>f{a5&{3}AmY|Z+oCFUt(?kIw?c`ad@bBvOdMBtV?z<>pC6q z%vPy;jyRJgXXMFcmJ%fnUj|u9PN8lF>?_(${|E+J(kki8fAP@MCy&-cWHO|bL3#O2 zy*-ikm@f!DWh0@AR0$~0y!Be!>XeTG<-@31CkNhphCR)k4Kh?A41jJ+=mUvv!a!k9 zlI@!4NYCe_-D%giN!o(X%rt|brka}I+VanLbEugj(LCz z5b)WiSpJD5!z~$Pg#5*D)rQ53QQglr1$z5~*%ybFeaXlM_8*jyY2ob4$LVZZ@|2Np z*F&3{ees|Jso+cWG~A|W_HxmkDld?j+KhrN_v#}++2p!T`Cv3Lpi+7MwR-p$>MhA` zdd5RZs>{(+UW6qWGCw>b}Bq#X@oA6QJil|9{gJ_IpS{yIa(_Qm(=O$Rx&c7!NNl83KW zalt-f3%T$vwwa!5Qyz%Vzg2Nx&*98a5U*q*aD?XDOQHF4Vl*p#?|LP(3DAKXqD{We zcvZL;yqO{1r27?1-WPAyqc`uvn_7_Ly~nM*LvQ|rF@$c?^2>%WOgU$!LQ>xmdLpkN zTa3)U%Oz(;yZ?!p0KsIxWl8(SnX@HB{>Dj!$&9Kbt7qpGW8gcefnB6Vr<}u5dh(cL z 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