From 707d9aa5ac1f748577827bb5a2b6ef93c8bbef18 Mon Sep 17 00:00:00 2001 From: Arthur Belleville Date: Sun, 23 Mar 2025 10:57:30 +0100 Subject: [PATCH] Add reset-password and improve login/signup --- backend/app/__pycache__/auth.cpython-312.pyc | Bin 0 -> 1597 bytes .../app/__pycache__/config.cpython-312.pyc | Bin 0 -> 1170 bytes backend/app/__pycache__/main.cpython-312.pyc | Bin 9093 -> 13629 bytes backend/app/auth.py | 46 ++ backend/app/config.py | 16 + backend/app/main.py | 189 +++-- backend/pyproject.toml | 2 + backend/uv.lock | 213 ++++++ ui/package.json | 3 +- ui/pnpm-lock.yaml | 8 + ui/src/App.tsx | 649 +----------------- .../BrandButtons/LoginWIthGoogle.tsx | 5 +- ui/src/hooks/useAuth.ts | 109 ++- ui/src/main.tsx | 3 +- ui/src/pages/landing.tsx | 633 +++++++++++++++++ ui/src/pages/login.tsx | 65 +- ui/src/pages/reset-password.tsx | 124 ++++ ui/src/pages/signup.tsx | 98 +-- ui/src/ui-library/toast/toast-region.tsx | 3 +- 19 files changed, 1383 insertions(+), 783 deletions(-) create mode 100644 backend/app/__pycache__/auth.cpython-312.pyc create mode 100644 backend/app/__pycache__/config.cpython-312.pyc create mode 100644 backend/app/auth.py create mode 100644 backend/app/config.py create mode 100644 ui/src/pages/landing.tsx create mode 100644 ui/src/pages/reset-password.tsx diff --git a/backend/app/__pycache__/auth.cpython-312.pyc b/backend/app/__pycache__/auth.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..313f917db797dc80189fea0abb98e3edca0c4e4a GIT binary patch literal 1597 zcmZ8h%}*Og6rb7I4}aTWCzQ5;6_XHG2?o?#t4b~)rKv=s21L6TYuO!Oowe7R-Hid+ zElP7pPwg!nQBSEzrTz6EIAn`P;*q5GtSb5BE51#h_{tQm(W>G2@msUAcc)i$T60ai>dTI+xt^29e&$Zm zbC)OXYK~L4nej2z7-is>CoPj!-Ba_ix$e%aMKsu< zVA)G%m1ny4eOjGkmM=5vdaSBn9J zoxhvHg?PZ%d5mjKBA^Cp2o16&bRzcvh#AHWxLsUlRC8%b530+{P?%TK7Bq*lBxLx4 z?XWOcVqJg9gHq0|`*bxg2Dz+<=Mf$z;B|OuSy=zvF3iDpPC;Ytvd2ajsAbUyCWyk6 zt$P(f)hW~RyHQ!4bS>XB@;j zIux(9Wh5m|Vkny4j|}ZbhSnz!BE4PpID%sR8|e*wFM4H1ywZk`kS_)NuoUR}DMH+j zIO<=+)BXv>r@+S(k(!12x4j#X7E|74ikD;~z;K=cSpo!AaY*jBM3* zvkx@OG=SzTux$X|re-;7srmW&o4nb%Lx-p@pLRR(qn&vu>9zrGgSwh&`N}fY4B#m* zGhQ^~{{a6IAEeUzW85XS$-Zx!-!%7=S9g?twe4ol>7IHfc~Fz9nN_;RJ@G8&lU;V7BHyWBwS3B?U+zZknM!T z^)vy0zSmb4HGr~aGTsOmU`w6)M;!|FnC>d$y%B)I6wrKGx2uchQfK(YvJD_|?pc(J zVAA3?$9SUT=*zT1gIVy2_W-{3}LukXgO V)Psjx(Zmsf_sc})gxkTv{{si?jM@MI literal 0 HcmV?d00001 diff --git a/backend/app/__pycache__/config.cpython-312.pyc b/backend/app/__pycache__/config.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5b42de0fb58fa82cdaeb8c51e4ba43b8e4855f29 GIT binary patch literal 1170 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 UR-whJMT3FegB80dMo-!P2NLfb3;+NC literal 9093 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 R>R*~n+$pSWU>JLj`7f!hha&(0 diff --git a/backend/app/auth.py b/backend/app/auth.py new file mode 100644 index 0000000..c235e2c --- /dev/null +++ b/backend/app/auth.py @@ -0,0 +1,46 @@ +from fastapi import Depends, HTTPException, status +from fastapi.security import OAuth2PasswordBearer +from supabase import Client +from .config import settings +from jose import JWTError, jwt +import os + +oauth2_scheme = OAuth2PasswordBearer(tokenUrl="auth/login") + +def get_supabase() -> Client: + from supabase import create_client + + # Temporary hardcoded values + import os + + + # Access environment variables + # Debugging purpose + + url = settings.supabase_url + key = settings.supabase_key # From Supabase dashboard + + # print("[HARDCODED] URL:", url) + # print("[HARDCODED] Key:", key[:10] + "...") + + return create_client(url, key) + +# Updated current user dependency +async def get_current_user( + token: str = Depends(oauth2_scheme), + supabase: Client = Depends(get_supabase) +): + credentials_exception = HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Could not validate credentials", + headers={"WWW-Authenticate": "Bearer"}, + ) + + try: + # Get user from Supabase auth + user = supabase.auth.get_user(token) + if not user: + raise credentials_exception + return user + except Exception as e: + raise credentials_exception \ No newline at end of file diff --git a/backend/app/config.py b/backend/app/config.py new file mode 100644 index 0000000..e4fffe1 --- /dev/null +++ b/backend/app/config.py @@ -0,0 +1,16 @@ +from pydantic_settings import BaseSettings +from pathlib import Path +from dotenv import load_dotenv +import os + +# Load environment variables from the .env file +env_path = Path(__file__).parent / ".env" +load_dotenv(dotenv_path=env_path) + +class Settings(BaseSettings): + supabase_url: str = os.getenv("SUPABASE_URL") + supabase_key: str = os.getenv("SUPABASE_KEY") + secret_key: str = os.getenv("SECRET_KEY") + access_token_expire_minutes: int = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", 30)) + +settings = Settings() \ No newline at end of file diff --git a/backend/app/main.py b/backend/app/main.py index 6975d8b..89aa2bb 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -1,54 +1,103 @@ import os import json import random -from typing import Dict, List, Optional +import inspect +from typing import Annotated, Dict, List, Optional from contextlib import contextmanager -from fastapi import FastAPI, Depends, HTTPException, status +from .auth import get_supabase +from fastapi import FastAPI, Depends, HTTPException, status, Request +from fastapi.exceptions import RequestValidationError from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import JSONResponse +from fastapi.encoders import jsonable_encoder from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials -from pydantic import BaseModel +from pydantic import BaseModel, EmailStr, field_validator, ValidationInfo, Field, SecretStr +from pydantic_core.core_schema import FieldValidationInfo + from dotenv import load_dotenv -from supabase import create_client, Client +from supabase import Client +from .auth import get_current_user from uuid import uuid4 from datetime import datetime -# Load environment variables -load_dotenv() - -# Initialize Supabase client -supabase_url = os.getenv("SUPABASE_URL") -supabase_key = os.getenv("SUPABASE_KEY") -supabase: Client = create_client(supabase_url, supabase_key) - # Initialize FastAPI app app = FastAPI(title="XTablo API") # CORS Middleware app.add_middleware( CORSMiddleware, - allow_origins=["*"], + allow_origins=["http://localhost:5173"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], + expose_headers=["X-Error-Code", "X-Error-Message"] ) # Security security = HTTPBearer() +@app.exception_handler(RequestValidationError) +async def validation_exception_handler(request: Request, exc: RequestValidationError): + errors = exc.errors() + + custom_errors = [] + for error in errors: + custom_message = error["msg"] + if custom_message.startswith("Value error, "): + custom_message = custom_message.split(", ")[1] + + custom_errors.append({ + **error, + "form_location": error["loc"][-1], + "human_error": custom_message + }) + + return JSONResponse(status_code=422, content=jsonable_encoder(custom_errors)) + # ====================================== # 🚀 MODELS # ====================================== class UserCreate(BaseModel): - email: str + email: EmailStr first_name: str last_name: str password: str - username: str + confirm_password: str + business_name: str + + @field_validator("email") + def email_must_contain_at_symbol(cls, v): + if '@' not in v: + raise ValueError("Entrer un email valide") + return v + + @field_validator("password") + def password_must_contain_at_least_8_characters(cls, v): + if len(v) < 8: + raise ValueError("Le mot de passe doit contenir au moins 8 caractères") + return v + + @field_validator("business_name") + def business_name_must_contain_at_least_3_characters(cls, v): + if len(v) < 3: + raise ValueError("Le nom de la société doit contenir au moins 3 caractères") + return v + + @field_validator('confirm_password', mode='before') + def passwords_match(cls, v, info: FieldValidationInfo): + if 'password' in info.data and v != info.data['password']: + raise ValueError('Les mots de passe ne correspondent pas') + return v + class UserLogin(BaseModel): - email: str + email: EmailStr password: str + +class UserOut(BaseModel): + email: EmailStr + business_name: str class GameState(BaseModel): id: str @@ -99,63 +148,101 @@ class RefreshResponse(BaseModel): expires_at: int user: dict - -# ====================================== -# 🔒 AUTHENTICATION HELPERS -# ====================================== -async def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(security)): - token = credentials.credentials - try: - response = supabase.auth.get_user(token) - if not hasattr(response, "user") or not response.user: - raise Exception("Invalid user data from Supabase") - - class UserResponse: - def __init__(self, id, email, username): - self.id = id - self.email = email - self.username = username - - # Extract username from user metadata or profile - username = response.user.user_metadata.get("username", "Unknown") # Adjust the key as needed - - # Pass id, email, and username to UserResponse - return UserResponse(response.user.id, response.user.email, username) - except Exception: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid authentication credentials") - - # ====================================== # 🔥 AUTH ROUTES # ====================================== @app.post("/auth/register") -async def register(user: UserCreate): +async def register(user: UserCreate, supabase: Client = Depends(get_supabase)): try: return supabase.auth.sign_up({ "email": user.email, "password": user.password, - "options": {"data": {"username": user.username, "first_name": user.first_name, "last_name": user.last_name}} + "options": {"data": {"first_name": user.first_name, "last_name": user.last_name, "business_name": user.business_name}} }) except Exception as e: + headers = {} + if e.code == "user_already_exists": + headers = {"X-Error-Code": e.code, "X-Error-Message": "Cette adresse email est déjà utilisée"} + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) @app.post("/auth/login") -async def login(user: UserLogin): +async def login(credentials: UserLogin, supabase: Client = Depends(get_supabase)): try: - return supabase.auth.sign_in_with_password({"email": user.email, "password": user.password}) + print("Login attempt for:", credentials.email) # Debug log + + response = supabase.auth.sign_in_with_password({ + "email": credentials.email.strip(), + "password": credentials.password.strip() + }) + + print("Login response:", response) + + return { + "access_token": response.session.access_token, + "token_type": "bearer" + } except Exception as e: - raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) + headers = {} + if e.code == "invalid_credentials": + headers = {"X-Error-Code": e.code, "X-Error-Message": "Email ou mot de passe incorrect"} + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Invalid credentials", + headers=headers + ) + +@app.get("/auth/login/google") +async def login_with_google(supabase: Client = Depends(get_supabase)): + try: + response = supabase.auth.sign_in_with_oauth({ + "provider": "google", + "options": { + "redirect_to": "https://mhcafqvzbrrwvahpvvzd.supabase.co/auth/v1/callback" + } + }) + return {"auth_url": response.url} + except Exception as e: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=str(e) + ) + @app.post("/auth/logout") -async def logout(user=Depends(get_current_user)): +async def logout(user=Depends(get_current_user), supabase: Client = Depends(get_supabase)): try: supabase.auth.sign_out() return {"message": "Successfully logged out"} except Exception as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) +@app.get("/me", response_model=UserOut) +async def get_me( + user = Depends(get_current_user), # Now properly imported + supabase: Client = Depends(get_supabase) +): + try: + # Get user details from public.users table + db_user = supabase.table("users").select("*").eq("id", user.user.id).execute().data[0] + return { + "username": db_user["username"], + "email": user.user.email, + "business_name": db_user["business_name"] + } + except IndexError: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="User not found in database" + ) + except Exception as e: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=str(e) + ) + @app.post("/auth/refresh", response_model=RefreshResponse) -async def refresh_token(refresh_request: RefreshToken): +async def refresh_token(refresh_request: RefreshToken, supabase: Client = Depends(get_supabase)): """Refresh the access token using a valid refresh token.""" try: # Validate the refresh token and get new tokens @@ -165,7 +252,9 @@ async def refresh_token(refresh_request: RefreshToken): user_data = { "id": response.user.id, "email": response.user.email, - "username": response.user.user_metadata.get("username", "Unknown") + "first_name": response.user.user_metadata.get("first_name", "Unknown"), + "last_name": response.user.user_metadata.get("last_name", "Unknown"), + "business_name": response.user.user_metadata.get("business_name", "Unknown") } # Return the new tokens and user data diff --git a/backend/pyproject.toml b/backend/pyproject.toml index ff49609..ebd88ef 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -6,5 +6,7 @@ readme = "README.md" requires-python = ">=3.12" dependencies = [ "fastapi[standard]>=0.115.11", + "pydantic-settings>=2.8.1", + "python-jose>=3.4.0", "supabase>=2.13.0", ] diff --git a/backend/uv.lock b/backend/uv.lock index 9ef9a3b..1b8343b 100644 --- a/backend/uv.lock +++ b/backend/uv.lock @@ -26,6 +26,22 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/6c/96/91e93ae5fd04d428c101cdbabce6c820d284d61d2614d00518f4fa52ea24/aiohttp-3.11.14.tar.gz", hash = "sha256:d6edc538c7480fa0a3b2bdd705f8010062d74700198da55d16498e1b49549b9c", size = 7676994 } wheels = [ + { url = "https://files.pythonhosted.org/packages/9c/ca/e4acb3b41f9e176f50960f7162d656e79bed151b1f911173b2c4a6c0a9d2/aiohttp-3.11.14-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:70ab0f61c1a73d3e0342cedd9a7321425c27a7067bebeeacd509f96695b875fc", size = 705489 }, + { url = "https://files.pythonhosted.org/packages/84/d5/dcf870e0b11f0c1e3065b7f17673485afa1ddb3d630ccd8f328bccfb459f/aiohttp-3.11.14-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:602d4db80daf4497de93cb1ce00b8fc79969c0a7cf5b67bec96fa939268d806a", size = 464807 }, + { url = "https://files.pythonhosted.org/packages/7c/f0/dc417d819ae26be6abcd72c28af99d285887fddbf76d4bbe46346f201870/aiohttp-3.11.14-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3a8a0d127c10b8d89e69bbd3430da0f73946d839e65fec00ae48ca7916a31948", size = 456819 }, + { url = "https://files.pythonhosted.org/packages/28/db/f7deb0862ebb821aa3829db20081a122ba67ffd149303f2d5202e30f20cd/aiohttp-3.11.14-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca9f835cdfedcb3f5947304e85b8ca3ace31eef6346d8027a97f4de5fb687534", size = 1683536 }, + { url = "https://files.pythonhosted.org/packages/5e/0d/8bf0619e21c6714902c44ab53e275deb543d4d2e68ab2b7b8fe5ba267506/aiohttp-3.11.14-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8aa5c68e1e68fff7cd3142288101deb4316b51f03d50c92de6ea5ce646e6c71f", size = 1738111 }, + { url = "https://files.pythonhosted.org/packages/f5/10/204b3700bb57b30b9e759d453fcfb3ad79a3eb18ece4e298aaf7917757dd/aiohttp-3.11.14-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b512f1de1c688f88dbe1b8bb1283f7fbeb7a2b2b26e743bb2193cbadfa6f307", size = 1794508 }, + { url = "https://files.pythonhosted.org/packages/cc/39/3f65072614c62a315a951fda737e4d9e6e2703f1da0cd2f2d8f629e6092e/aiohttp-3.11.14-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc9253069158d57e27d47a8453d8a2c5a370dc461374111b5184cf2f147a3cc3", size = 1692006 }, + { url = "https://files.pythonhosted.org/packages/73/77/cc06ecea173f9bee2f20c8e32e2cf4c8e03909a707183cdf95434db4993e/aiohttp-3.11.14-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b2501f1b981e70932b4a552fc9b3c942991c7ae429ea117e8fba57718cdeed0", size = 1620369 }, + { url = "https://files.pythonhosted.org/packages/87/75/5bd424bcd90c7eb2f50fd752d013db4cefb447deeecfc5bc4e8e0b1c74dd/aiohttp-3.11.14-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:28a3d083819741592685762d51d789e6155411277050d08066537c5edc4066e6", size = 1642508 }, + { url = "https://files.pythonhosted.org/packages/81/f0/ce936ec575e0569f91e5c8374086a6f7760926f16c3b95428fb55d6bfe91/aiohttp-3.11.14-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:0df3788187559c262922846087e36228b75987f3ae31dd0a1e5ee1034090d42f", size = 1685771 }, + { url = "https://files.pythonhosted.org/packages/68/b7/5216590b99b5b1f18989221c25ac9d9a14a7b0c3c4ae1ff728e906c36430/aiohttp-3.11.14-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e73fa341d8b308bb799cf0ab6f55fc0461d27a9fa3e4582755a3d81a6af8c09", size = 1648318 }, + { url = "https://files.pythonhosted.org/packages/a5/c2/c27061c4ab93fa25f925c7ebddc10c20d992dbbc329e89d493811299dc93/aiohttp-3.11.14-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:51ba80d473eb780a329d73ac8afa44aa71dfb521693ccea1dea8b9b5c4df45ce", size = 1704545 }, + { url = "https://files.pythonhosted.org/packages/09/f5/11b2da82f2c52365a5b760a4e944ae50a89cf5fb207024b7853615254584/aiohttp-3.11.14-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:8d1dd75aa4d855c7debaf1ef830ff2dfcc33f893c7db0af2423ee761ebffd22b", size = 1737839 }, + { url = "https://files.pythonhosted.org/packages/03/7f/145e23fe0a4c45b256f14c3268ada5497d487786334721ae8a0c818ee516/aiohttp-3.11.14-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41cf0cefd9e7b5c646c2ef529c8335e7eafd326f444cc1cdb0c47b6bc836f9be", size = 1695833 }, + { url = "https://files.pythonhosted.org/packages/1c/78/627dba6ee9fb9439e2e29b521adb1135877a9c7b54811fec5c46e59f2fc8/aiohttp-3.11.14-cp312-cp312-win32.whl", hash = "sha256:948abc8952aff63de7b2c83bfe3f211c727da3a33c3a5866a0e2cf1ee1aa950f", size = 412185 }, + { url = "https://files.pythonhosted.org/packages/3f/5f/1737cf6fcf0524693a4aeff8746530b65422236761e7bfdd79c6d2ce2e1c/aiohttp-3.11.14-cp312-cp312-win_amd64.whl", hash = "sha256:3b420d076a46f41ea48e5fcccb996f517af0d406267e31e6716f480a3d50d65c", size = 438526 }, { url = "https://files.pythonhosted.org/packages/c5/8e/d7f353c5aaf9f868ab382c3d3320dc6efaa639b6b30d5a686bed83196115/aiohttp-3.11.14-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d14e274828561db91e4178f0057a915f3af1757b94c2ca283cb34cbb6e00b50", size = 698774 }, { url = "https://files.pythonhosted.org/packages/d5/52/097b98d50f8550883f7d360c6cd4e77668c7442038671bb4b349ced95066/aiohttp-3.11.14-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f30fc72daf85486cdcdfc3f5e0aea9255493ef499e31582b34abadbfaafb0965", size = 461443 }, { url = "https://files.pythonhosted.org/packages/2b/5c/19c84bb5796be6ca4fd1432012cfd5f88ec02c8b9e0357cdecc48ff2c4fd/aiohttp-3.11.14-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4edcbe34e6dba0136e4cabf7568f5a434d89cc9de5d5155371acda275353d228", size = 453717 }, @@ -72,6 +88,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "idna" }, { name = "sniffio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949 } wheels = [ @@ -93,12 +110,16 @@ version = "0.1.0" source = { virtual = "." } dependencies = [ { name = "fastapi", extra = ["standard"] }, + { name = "pydantic-settings" }, + { name = "python-jose" }, { name = "supabase" }, ] [package.metadata] requires-dist = [ { name = "fastapi", extras = ["standard"], specifier = ">=0.115.11" }, + { name = "pydantic-settings", specifier = ">=2.8.1" }, + { name = "python-jose", specifier = ">=3.4.0" }, { name = "supabase", specifier = ">=2.13.0" }, ] @@ -153,6 +174,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/68/1b/e0a87d256e40e8c888847551b20a017a6b98139178505dc7ffb96f04e954/dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86", size = 313632 }, ] +[[package]] +name = "ecdsa" +version = "0.19.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/1f/924e3caae75f471eae4b26bd13b698f6af2c44279f67af317439c2f4c46a/ecdsa-0.19.1.tar.gz", hash = "sha256:478cba7b62555866fcb3bb3fe985e06decbdb68ef55713c4e5ab98c57d508e61", size = 201793 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/a3/460c57f094a4a165c84a1341c373b0a4f5ec6ac244b998d5021aade89b77/ecdsa-0.19.1-py2.py3-none-any.whl", hash = "sha256:30638e27cf77b7e15c4c4cc1973720149e1033827cfd00661ca5c8cc0cdb24c3", size = 150607 }, +] + [[package]] name = "email-validator" version = "2.2.0" @@ -215,6 +248,21 @@ version = "1.5.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/8f/ed/0f4cec13a93c02c47ec32d81d11c0c1efbadf4a471e3f3ce7cad366cbbd3/frozenlist-1.5.0.tar.gz", hash = "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817", size = 39930 } wheels = [ + { url = "https://files.pythonhosted.org/packages/79/73/fa6d1a96ab7fd6e6d1c3500700963eab46813847f01ef0ccbaa726181dd5/frozenlist-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21", size = 94026 }, + { url = "https://files.pythonhosted.org/packages/ab/04/ea8bf62c8868b8eada363f20ff1b647cf2e93377a7b284d36062d21d81d1/frozenlist-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d", size = 54150 }, + { url = "https://files.pythonhosted.org/packages/d0/9a/8e479b482a6f2070b26bda572c5e6889bb3ba48977e81beea35b5ae13ece/frozenlist-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e", size = 51927 }, + { url = "https://files.pythonhosted.org/packages/e3/12/2aad87deb08a4e7ccfb33600871bbe8f0e08cb6d8224371387f3303654d7/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a", size = 282647 }, + { url = "https://files.pythonhosted.org/packages/77/f2/07f06b05d8a427ea0060a9cef6e63405ea9e0d761846b95ef3fb3be57111/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a", size = 289052 }, + { url = "https://files.pythonhosted.org/packages/bd/9f/8bf45a2f1cd4aa401acd271b077989c9267ae8463e7c8b1eb0d3f561b65e/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee", size = 291719 }, + { url = "https://files.pythonhosted.org/packages/41/d1/1f20fd05a6c42d3868709b7604c9f15538a29e4f734c694c6bcfc3d3b935/frozenlist-1.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6", size = 267433 }, + { url = "https://files.pythonhosted.org/packages/af/f2/64b73a9bb86f5a89fb55450e97cd5c1f84a862d4ff90d9fd1a73ab0f64a5/frozenlist-1.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e", size = 283591 }, + { url = "https://files.pythonhosted.org/packages/29/e2/ffbb1fae55a791fd6c2938dd9ea779509c977435ba3940b9f2e8dc9d5316/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9", size = 273249 }, + { url = "https://files.pythonhosted.org/packages/2e/6e/008136a30798bb63618a114b9321b5971172a5abddff44a100c7edc5ad4f/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039", size = 271075 }, + { url = "https://files.pythonhosted.org/packages/ae/f0/4e71e54a026b06724cec9b6c54f0b13a4e9e298cc8db0f82ec70e151f5ce/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784", size = 285398 }, + { url = "https://files.pythonhosted.org/packages/4d/36/70ec246851478b1c0b59f11ef8ade9c482ff447c1363c2bd5fad45098b12/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631", size = 294445 }, + { url = "https://files.pythonhosted.org/packages/37/e0/47f87544055b3349b633a03c4d94b405956cf2437f4ab46d0928b74b7526/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f", size = 280569 }, + { url = "https://files.pythonhosted.org/packages/f9/7c/490133c160fb6b84ed374c266f42800e33b50c3bbab1652764e6e1fc498a/frozenlist-1.5.0-cp312-cp312-win32.whl", hash = "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8", size = 44721 }, + { url = "https://files.pythonhosted.org/packages/b1/56/4e45136ffc6bdbfa68c29ca56ef53783ef4c2fd395f7cbf99a2624aa9aaa/frozenlist-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f", size = 51329 }, { url = "https://files.pythonhosted.org/packages/da/3b/915f0bca8a7ea04483622e84a9bd90033bab54bdf485479556c74fd5eaf5/frozenlist-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953", size = 91538 }, { url = "https://files.pythonhosted.org/packages/c7/d1/a7c98aad7e44afe5306a2b068434a5830f1470675f0e715abb86eb15f15b/frozenlist-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0", size = 52849 }, { url = "https://files.pythonhosted.org/packages/3a/c8/76f23bf9ab15d5f760eb48701909645f686f9c64fbb8982674c241fbef14/frozenlist-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2", size = 50583 }, @@ -296,6 +344,13 @@ version = "0.6.4" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/a7/9a/ce5e1f7e131522e6d3426e8e7a490b3a01f39a6696602e1c4f33f9e94277/httptools-0.6.4.tar.gz", hash = "sha256:4e93eee4add6493b59a5c514da98c939b244fce4a0d8879cd3f466562f4b7d5c", size = 240639 } wheels = [ + { url = "https://files.pythonhosted.org/packages/bb/0e/d0b71465c66b9185f90a091ab36389a7352985fe857e352801c39d6127c8/httptools-0.6.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:df017d6c780287d5c80601dafa31f17bddb170232d85c066604d8558683711a2", size = 200683 }, + { url = "https://files.pythonhosted.org/packages/e2/b8/412a9bb28d0a8988de3296e01efa0bd62068b33856cdda47fe1b5e890954/httptools-0.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:85071a1e8c2d051b507161f6c3e26155b5c790e4e28d7f236422dbacc2a9cc44", size = 104337 }, + { url = "https://files.pythonhosted.org/packages/9b/01/6fb20be3196ffdc8eeec4e653bc2a275eca7f36634c86302242c4fbb2760/httptools-0.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69422b7f458c5af875922cdb5bd586cc1f1033295aa9ff63ee196a87519ac8e1", size = 508796 }, + { url = "https://files.pythonhosted.org/packages/f7/d8/b644c44acc1368938317d76ac991c9bba1166311880bcc0ac297cb9d6bd7/httptools-0.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16e603a3bff50db08cd578d54f07032ca1631450ceb972c2f834c2b860c28ea2", size = 510837 }, + { url = "https://files.pythonhosted.org/packages/52/d8/254d16a31d543073a0e57f1c329ca7378d8924e7e292eda72d0064987486/httptools-0.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec4f178901fa1834d4a060320d2f3abc5c9e39766953d038f1458cb885f47e81", size = 485289 }, + { url = "https://files.pythonhosted.org/packages/5f/3c/4aee161b4b7a971660b8be71a92c24d6c64372c1ab3ae7f366b3680df20f/httptools-0.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f9eb89ecf8b290f2e293325c646a211ff1c2493222798bb80a530c5e7502494f", size = 489779 }, + { url = "https://files.pythonhosted.org/packages/12/b7/5cae71a8868e555f3f67a50ee7f673ce36eac970f029c0c5e9d584352961/httptools-0.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:db78cb9ca56b59b016e64b6031eda5653be0589dba2b1b43453f6e8b405a0970", size = 88634 }, { url = "https://files.pythonhosted.org/packages/94/a3/9fe9ad23fd35f7de6b91eeb60848986058bd8b5a5c1e256f5860a160cc3e/httptools-0.6.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ade273d7e767d5fae13fa637f4d53b6e961fb7fd93c7797562663f0171c26660", size = 197214 }, { url = "https://files.pythonhosted.org/packages/ea/d9/82d5e68bab783b632023f2fa31db20bebb4e89dfc4d2293945fd68484ee4/httptools-0.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:856f4bc0478ae143bad54a4242fccb1f3f86a6e1be5548fecfd4102061b3a083", size = 102431 }, { url = "https://files.pythonhosted.org/packages/96/c1/cb499655cbdbfb57b577734fde02f6fa0bbc3fe9fb4d87b742b512908dff/httptools-0.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:322d20ea9cdd1fa98bd6a74b77e2ec5b818abdc3d36695ab402a0de8ef2865a3", size = 473121 }, @@ -373,6 +428,16 @@ version = "3.0.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537 } wheels = [ + { url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274 }, + { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348 }, + { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149 }, + { url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118 }, + { url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993 }, + { url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178 }, + { url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319 }, + { url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352 }, + { url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097 }, + { url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601 }, { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274 }, { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352 }, { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122 }, @@ -410,6 +475,21 @@ version = "6.2.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/82/4a/7874ca44a1c9b23796c767dd94159f6c17e31c0e7d090552a1c623247d82/multidict-6.2.0.tar.gz", hash = "sha256:0085b0afb2446e57050140240a8595846ed64d1cbd26cef936bfab3192c673b8", size = 71066 } wheels = [ + { url = "https://files.pythonhosted.org/packages/a4/e2/0153a8db878aef9b2397be81e62cbc3b32ca9b94e0f700b103027db9d506/multidict-6.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:437c33561edb6eb504b5a30203daf81d4a9b727e167e78b0854d9a4e18e8950b", size = 49204 }, + { url = "https://files.pythonhosted.org/packages/bb/9d/5ccb3224a976d1286f360bb4e89e67b7cdfb87336257fc99be3c17f565d7/multidict-6.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9f49585f4abadd2283034fc605961f40c638635bc60f5162276fec075f2e37a4", size = 29807 }, + { url = "https://files.pythonhosted.org/packages/62/32/ef20037f51b84b074a89bab5af46d4565381c3f825fc7cbfc19c1ee156be/multidict-6.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5dd7106d064d05896ce28c97da3f46caa442fe5a43bc26dfb258e90853b39b44", size = 30000 }, + { url = "https://files.pythonhosted.org/packages/97/81/b0a7560bfc3ec72606232cd7e60159e09b9cf29e66014d770c1315868fa2/multidict-6.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e25b11a0417475f093d0f0809a149aff3943c2c56da50fdf2c3c88d57fe3dfbd", size = 131820 }, + { url = "https://files.pythonhosted.org/packages/49/3b/768bfc0e41179fbccd3a22925329a11755b7fdd53bec66dbf6b8772f0bce/multidict-6.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac380cacdd3b183338ba63a144a34e9044520a6fb30c58aa14077157a033c13e", size = 136272 }, + { url = "https://files.pythonhosted.org/packages/71/ac/fd2be3fe98ff54e7739448f771ba730d42036de0870737db9ae34bb8efe9/multidict-6.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:61d5541f27533f803a941d3a3f8a3d10ed48c12cf918f557efcbf3cd04ef265c", size = 135233 }, + { url = "https://files.pythonhosted.org/packages/93/76/1657047da771315911a927b364a32dafce4135b79b64208ce4ac69525c56/multidict-6.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:facaf11f21f3a4c51b62931feb13310e6fe3475f85e20d9c9fdce0d2ea561b87", size = 132861 }, + { url = "https://files.pythonhosted.org/packages/19/a5/9f07ffb9bf68b8aaa406c2abee27ad87e8b62a60551587b8e59ee91aea84/multidict-6.2.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:095a2eabe8c43041d3e6c2cb8287a257b5f1801c2d6ebd1dd877424f1e89cf29", size = 122166 }, + { url = "https://files.pythonhosted.org/packages/95/23/b5ce3318d9d6c8f105c3679510f9d7202980545aad8eb4426313bd8da3ee/multidict-6.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a0cc398350ef31167e03f3ca7c19313d4e40a662adcb98a88755e4e861170bdd", size = 136052 }, + { url = "https://files.pythonhosted.org/packages/ce/5c/02cffec58ffe120873dce520af593415b91cc324be0345f534ad3637da4e/multidict-6.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7c611345bbe7cb44aabb877cb94b63e86f2d0db03e382667dbd037866d44b4f8", size = 130094 }, + { url = "https://files.pythonhosted.org/packages/49/f3/3b19a83f4ebf53a3a2a0435f3e447aa227b242ba3fd96a92404b31fb3543/multidict-6.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8cd1a0644ccaf27e9d2f6d9c9474faabee21f0578fe85225cc5af9a61e1653df", size = 140962 }, + { url = "https://files.pythonhosted.org/packages/cc/1a/c916b54fb53168c24cb6a3a0795fd99d0a59a0ea93fa9f6edeff5565cb20/multidict-6.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:89b3857652183b8206a891168af47bac10b970d275bba1f6ee46565a758c078d", size = 138082 }, + { url = "https://files.pythonhosted.org/packages/ef/1a/dcb7fb18f64b3727c61f432c1e1a0d52b3924016124e4bbc8a7d2e4fa57b/multidict-6.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:125dd82b40f8c06d08d87b3510beaccb88afac94e9ed4a6f6c71362dc7dbb04b", size = 136019 }, + { url = "https://files.pythonhosted.org/packages/fb/02/7695485375106f5c542574f70e1968c391f86fa3efc9f1fd76aac0af7237/multidict-6.2.0-cp312-cp312-win32.whl", hash = "sha256:76b34c12b013d813e6cb325e6bd4f9c984db27758b16085926bbe7ceeaace626", size = 26676 }, + { url = "https://files.pythonhosted.org/packages/3c/f5/f147000fe1f4078160157b15b0790fff0513646b0f9b7404bf34007a9b44/multidict-6.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:0b183a959fb88ad1be201de2c4bdf52fa8e46e6c185d76201286a97b6f5ee65c", size = 28899 }, { url = "https://files.pythonhosted.org/packages/a4/6c/5df5590b1f9a821154589df62ceae247537b01ab26b0aa85997c35ca3d9e/multidict-6.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5c5e7d2e300d5cb3b2693b6d60d3e8c8e7dd4ebe27cd17c9cb57020cac0acb80", size = 49151 }, { url = "https://files.pythonhosted.org/packages/d5/ca/c917fbf1be989cd7ea9caa6f87e9c33844ba8d5fbb29cd515d4d2833b84c/multidict-6.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:256d431fe4583c5f1e0f2e9c4d9c22f3a04ae96009b8cfa096da3a8723db0a16", size = 29803 }, { url = "https://files.pythonhosted.org/packages/22/19/d97086fc96f73acf36d4dbe65c2c4175911969df49c4e94ef082be59d94e/multidict-6.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a3c0ff89fe40a152e77b191b83282c9664357dce3004032d42e68c514ceff27e", size = 29947 }, @@ -472,6 +552,22 @@ version = "0.3.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/92/76/f941e63d55c0293ff7829dd21e7cf1147e90a526756869a9070f287a68c9/propcache-0.3.0.tar.gz", hash = "sha256:a8fd93de4e1d278046345f49e2238cdb298589325849b2645d4a94c53faeffc5", size = 42722 } wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/2c/921f15dc365796ec23975b322b0078eae72995c7b4d49eba554c6a308d70/propcache-0.3.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e53d19c2bf7d0d1e6998a7e693c7e87300dd971808e6618964621ccd0e01fe4e", size = 79867 }, + { url = "https://files.pythonhosted.org/packages/11/a5/4a6cc1a559d1f2fb57ea22edc4245158cdffae92f7f92afcee2913f84417/propcache-0.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a61a68d630e812b67b5bf097ab84e2cd79b48c792857dc10ba8a223f5b06a2af", size = 46109 }, + { url = "https://files.pythonhosted.org/packages/e1/6d/28bfd3af3a567ad7d667348e7f46a520bda958229c4d545ba138a044232f/propcache-0.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fb91d20fa2d3b13deea98a690534697742029f4fb83673a3501ae6e3746508b5", size = 45635 }, + { url = "https://files.pythonhosted.org/packages/73/20/d75b42eaffe5075eac2f4e168f6393d21c664c91225288811d85451b2578/propcache-0.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67054e47c01b7b349b94ed0840ccae075449503cf1fdd0a1fdd98ab5ddc2667b", size = 242159 }, + { url = "https://files.pythonhosted.org/packages/a5/fb/4b537dd92f9fd4be68042ec51c9d23885ca5fafe51ec24c58d9401034e5f/propcache-0.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:997e7b8f173a391987df40f3b52c423e5850be6f6df0dcfb5376365440b56667", size = 248163 }, + { url = "https://files.pythonhosted.org/packages/e7/af/8a9db04ac596d531ca0ef7dde518feaadfcdabef7b17d6a5ec59ee3effc2/propcache-0.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d663fd71491dde7dfdfc899d13a067a94198e90695b4321084c6e450743b8c7", size = 248794 }, + { url = "https://files.pythonhosted.org/packages/9d/c4/ecfc988879c0fd9db03228725b662d76cf484b6b46f7e92fee94e4b52490/propcache-0.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8884ba1a0fe7210b775106b25850f5e5a9dc3c840d1ae9924ee6ea2eb3acbfe7", size = 243912 }, + { url = "https://files.pythonhosted.org/packages/04/a2/298dd27184faa8b7d91cc43488b578db218b3cc85b54d912ed27b8c5597a/propcache-0.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa806bbc13eac1ab6291ed21ecd2dd426063ca5417dd507e6be58de20e58dfcf", size = 229402 }, + { url = "https://files.pythonhosted.org/packages/be/0d/efe7fec316ca92dbf4bc4a9ba49ca889c43ca6d48ab1d6fa99fc94e5bb98/propcache-0.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6f4d7a7c0aff92e8354cceca6fe223973ddf08401047920df0fcb24be2bd5138", size = 226896 }, + { url = "https://files.pythonhosted.org/packages/60/63/72404380ae1d9c96d96e165aa02c66c2aae6072d067fc4713da5cde96762/propcache-0.3.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:9be90eebc9842a93ef8335291f57b3b7488ac24f70df96a6034a13cb58e6ff86", size = 221447 }, + { url = "https://files.pythonhosted.org/packages/9d/18/b8392cab6e0964b67a30a8f4dadeaff64dc7022b5a34bb1d004ea99646f4/propcache-0.3.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bf15fc0b45914d9d1b706f7c9c4f66f2b7b053e9517e40123e137e8ca8958b3d", size = 222440 }, + { url = "https://files.pythonhosted.org/packages/6f/be/105d9ceda0f97eff8c06bac1673448b2db2a497444de3646464d3f5dc881/propcache-0.3.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5a16167118677d94bb48bfcd91e420088854eb0737b76ec374b91498fb77a70e", size = 234104 }, + { url = "https://files.pythonhosted.org/packages/cb/c9/f09a4ec394cfcce4053d8b2a04d622b5f22d21ba9bb70edd0cad061fa77b/propcache-0.3.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:41de3da5458edd5678b0f6ff66691507f9885f5fe6a0fb99a5d10d10c0fd2d64", size = 239086 }, + { url = "https://files.pythonhosted.org/packages/ea/aa/96f7f9ed6def82db67c972bdb7bd9f28b95d7d98f7e2abaf144c284bf609/propcache-0.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:728af36011bb5d344c4fe4af79cfe186729efb649d2f8b395d1572fb088a996c", size = 230991 }, + { url = "https://files.pythonhosted.org/packages/5a/11/bee5439de1307d06fad176f7143fec906e499c33d7aff863ea8428b8e98b/propcache-0.3.0-cp312-cp312-win32.whl", hash = "sha256:6b5b7fd6ee7b54e01759f2044f936dcf7dea6e7585f35490f7ca0420fe723c0d", size = 40337 }, + { url = "https://files.pythonhosted.org/packages/e4/17/e5789a54a0455a61cb9efc4ca6071829d992220c2998a27c59aeba749f6f/propcache-0.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:2d15bc27163cd4df433e75f546b9ac31c1ba7b0b128bfb1b90df19082466ff57", size = 44404 }, { url = "https://files.pythonhosted.org/packages/3a/0f/a79dd23a0efd6ee01ab0dc9750d8479b343bfd0c73560d59d271eb6a99d4/propcache-0.3.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a2b9bf8c79b660d0ca1ad95e587818c30ccdb11f787657458d6f26a1ea18c568", size = 77287 }, { url = "https://files.pythonhosted.org/packages/b8/51/76675703c90de38ac75adb8deceb3f3ad99b67ff02a0fa5d067757971ab8/propcache-0.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b0c1a133d42c6fc1f5fbcf5c91331657a1ff822e87989bf4a6e2e39b818d0ee9", size = 44923 }, { url = "https://files.pythonhosted.org/packages/01/9b/fd5ddbee66cf7686e73c516227c2fd9bf471dbfed0f48329d095ea1228d3/propcache-0.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bb2f144c6d98bb5cbc94adeb0447cfd4c0f991341baa68eee3f3b0c9c0e83767", size = 44325 }, @@ -507,6 +603,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b5/35/6c4c6fc8774a9e3629cd750dc24a7a4fb090a25ccd5c3246d127b70f9e22/propcache-0.3.0-py3-none-any.whl", hash = "sha256:67dda3c7325691c2081510e92c561f465ba61b975f481735aefdfc845d2cd043", size = 12101 }, ] +[[package]] +name = "pyasn1" +version = "0.4.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a4/db/fffec68299e6d7bad3d504147f9094830b704527a7fc098b721d38cc7fa7/pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba", size = 146820 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/1e/a94a8d635fa3ce4cfc7f506003548d0a2447ae76fd5ca53932970fe3053f/pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d", size = 77145 }, +] + [[package]] name = "pydantic" version = "2.10.6" @@ -530,6 +635,20 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443 } wheels = [ + { url = "https://files.pythonhosted.org/packages/d6/74/51c8a5482ca447871c93e142d9d4a92ead74de6c8dc5e66733e22c9bba89/pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", size = 1893127 }, + { url = "https://files.pythonhosted.org/packages/d3/f3/c97e80721735868313c58b89d2de85fa80fe8dfeeed84dc51598b92a135e/pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", size = 1811340 }, + { url = "https://files.pythonhosted.org/packages/9e/91/840ec1375e686dbae1bd80a9e46c26a1e0083e1186abc610efa3d9a36180/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", size = 1822900 }, + { url = "https://files.pythonhosted.org/packages/f6/31/4240bc96025035500c18adc149aa6ffdf1a0062a4b525c932065ceb4d868/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934", size = 1869177 }, + { url = "https://files.pythonhosted.org/packages/fa/20/02fbaadb7808be578317015c462655c317a77a7c8f0ef274bc016a784c54/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6", size = 2038046 }, + { url = "https://files.pythonhosted.org/packages/06/86/7f306b904e6c9eccf0668248b3f272090e49c275bc488a7b88b0823444a4/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c", size = 2685386 }, + { url = "https://files.pythonhosted.org/packages/8d/f0/49129b27c43396581a635d8710dae54a791b17dfc50c70164866bbf865e3/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2", size = 1997060 }, + { url = "https://files.pythonhosted.org/packages/0d/0f/943b4af7cd416c477fd40b187036c4f89b416a33d3cc0ab7b82708a667aa/pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4", size = 2004870 }, + { url = "https://files.pythonhosted.org/packages/35/40/aea70b5b1a63911c53a4c8117c0a828d6790483f858041f47bab0b779f44/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3", size = 1999822 }, + { url = "https://files.pythonhosted.org/packages/f2/b3/807b94fd337d58effc5498fd1a7a4d9d59af4133e83e32ae39a96fddec9d/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4", size = 2130364 }, + { url = "https://files.pythonhosted.org/packages/fc/df/791c827cd4ee6efd59248dca9369fb35e80a9484462c33c6649a8d02b565/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57", size = 2158303 }, + { url = "https://files.pythonhosted.org/packages/9b/67/4e197c300976af185b7cef4c02203e175fb127e414125916bf1128b639a9/pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc", size = 1834064 }, + { url = "https://files.pythonhosted.org/packages/1f/ea/cd7209a889163b8dcca139fe32b9687dd05249161a3edda62860430457a5/pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9", size = 1989046 }, + { url = "https://files.pythonhosted.org/packages/bc/49/c54baab2f4658c26ac633d798dab66b4c3a9bbf47cff5284e9c182f4137a/pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b", size = 1885092 }, { url = "https://files.pythonhosted.org/packages/41/b1/9bc383f48f8002f99104e3acff6cba1231b29ef76cfa45d1506a5cad1f84/pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b", size = 1892709 }, { url = "https://files.pythonhosted.org/packages/10/6c/e62b8657b834f3eb2961b49ec8e301eb99946245e70bf42c8817350cbefc/pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154", size = 1811273 }, { url = "https://files.pythonhosted.org/packages/ba/15/52cfe49c8c986e081b863b102d6b859d9defc63446b642ccbbb3742bf371/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9", size = 1823027 }, @@ -546,6 +665,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/51/b2/b2b50d5ecf21acf870190ae5d093602d95f66c9c31f9d5de6062eb329ad1/pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", size = 1885186 }, ] +[[package]] +name = "pydantic-settings" +version = "2.8.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "python-dotenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/88/82/c79424d7d8c29b994fb01d277da57b0a9b09cc03c3ff875f9bd8a86b2145/pydantic_settings-2.8.1.tar.gz", hash = "sha256:d5c663dfbe9db9d5e1c646b2e161da12f0d734d422ee56f567d0ea2cee4e8585", size = 83550 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/53/a64f03044927dc47aafe029c42a5b7aabc38dfb813475e0e1bf71c4a59d0/pydantic_settings-2.8.1-py3-none-any.whl", hash = "sha256:81942d5ac3d905f7f3ee1a70df5dfb62d5569c12f51a5a647defc1c3d9ee2e9c", size = 30839 }, +] + [[package]] name = "pygments" version = "2.19.1" @@ -576,6 +708,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863 }, ] +[[package]] +name = "python-jose" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ecdsa" }, + { name = "pyasn1" }, + { name = "rsa" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8e/a0/c49687cf40cb6128ea4e0559855aff92cd5ebd1a60a31c08526818c0e51e/python-jose-3.4.0.tar.gz", hash = "sha256:9a9a40f418ced8ecaf7e3b28d69887ceaa76adad3bcaa6dae0d9e596fec1d680", size = 92145 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/63/b0/2586ea6b6fd57a994ece0b56418cbe93fff0efb85e2c9eb6b0caf24a4e37/python_jose-3.4.0-py2.py3-none-any.whl", hash = "sha256:9c9f616819652d109bd889ecd1e15e9a162b9b94d682534c9c2146092945b78f", size = 34616 }, +] + [[package]] name = "python-multipart" version = "0.0.20" @@ -591,6 +737,15 @@ version = "6.0.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 } wheels = [ + { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873 }, + { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302 }, + { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154 }, + { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223 }, + { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542 }, + { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164 }, + { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611 }, + { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591 }, + { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338 }, { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 }, { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 }, { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 }, @@ -644,6 +799,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7e/1b/1c2f43af46456050b27810a7a013af8a7e12bc545a0cdc00eb0df55eb769/rich_toolkit-0.13.2-py3-none-any.whl", hash = "sha256:f3f6c583e5283298a2f7dbd3c65aca18b7f818ad96174113ab5bec0b0e35ed61", size = 13566 }, ] +[[package]] +name = "rsa" +version = "4.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyasn1" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/aa/65/7d973b89c4d2351d7fb232c2e452547ddfa243e93131e7cfa766da627b52/rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21", size = 29711 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7", size = 34315 }, +] + [[package]] name = "shellingham" version = "1.5.4" @@ -789,6 +956,12 @@ version = "0.21.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/af/c0/854216d09d33c543f12a44b393c402e89a920b1a0a7dc634c42de91b9cf6/uvloop-0.21.0.tar.gz", hash = "sha256:3bf12b0fda68447806a7ad847bfa591613177275d35b6724b1ee573faa3704e3", size = 2492741 } wheels = [ + { url = "https://files.pythonhosted.org/packages/8c/4c/03f93178830dc7ce8b4cdee1d36770d2f5ebb6f3d37d354e061eefc73545/uvloop-0.21.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:359ec2c888397b9e592a889c4d72ba3d6befba8b2bb01743f72fffbde663b59c", size = 1471284 }, + { url = "https://files.pythonhosted.org/packages/43/3e/92c03f4d05e50f09251bd8b2b2b584a2a7f8fe600008bcc4523337abe676/uvloop-0.21.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f7089d2dc73179ce5ac255bdf37c236a9f914b264825fdaacaded6990a7fb4c2", size = 821349 }, + { url = "https://files.pythonhosted.org/packages/a6/ef/a02ec5da49909dbbfb1fd205a9a1ac4e88ea92dcae885e7c961847cd51e2/uvloop-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baa4dcdbd9ae0a372f2167a207cd98c9f9a1ea1188a8a526431eef2f8116cc8d", size = 4580089 }, + { url = "https://files.pythonhosted.org/packages/06/a7/b4e6a19925c900be9f98bec0a75e6e8f79bb53bdeb891916609ab3958967/uvloop-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86975dca1c773a2c9864f4c52c5a55631038e387b47eaf56210f873887b6c8dc", size = 4693770 }, + { url = "https://files.pythonhosted.org/packages/ce/0c/f07435a18a4b94ce6bd0677d8319cd3de61f3a9eeb1e5f8ab4e8b5edfcb3/uvloop-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:461d9ae6660fbbafedd07559c6a2e57cd553b34b0065b6550685f6653a98c1cb", size = 4451321 }, + { url = "https://files.pythonhosted.org/packages/8f/eb/f7032be105877bcf924709c97b1bf3b90255b4ec251f9340cef912559f28/uvloop-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:183aef7c8730e54c9a3ee3227464daed66e37ba13040bb3f350bc2ddc040f22f", size = 4659022 }, { url = "https://files.pythonhosted.org/packages/3f/8d/2cbef610ca21539f0f36e2b34da49302029e7c9f09acef0b1c3b5839412b/uvloop-0.21.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bfd55dfcc2a512316e65f16e503e9e450cab148ef11df4e4e679b5e8253a5281", size = 1468123 }, { url = "https://files.pythonhosted.org/packages/93/0d/b0038d5a469f94ed8f2b2fce2434a18396d8fbfb5da85a0a9781ebbdec14/uvloop-0.21.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:787ae31ad8a2856fc4e7c095341cccc7209bd657d0e71ad0dc2ea83c4a6fa8af", size = 819325 }, { url = "https://files.pythonhosted.org/packages/50/94/0a687f39e78c4c1e02e3272c6b2ccdb4e0085fda3b8352fecd0410ccf915/uvloop-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ee4d4ef48036ff6e5cfffb09dd192c7a5027153948d85b8da7ff705065bacc6", size = 4582806 }, @@ -806,6 +979,19 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/f5/26/c705fc77d0a9ecdb9b66f1e2976d95b81df3cae518967431e7dbf9b5e219/watchfiles-1.0.4.tar.gz", hash = "sha256:6ba473efd11062d73e4f00c2b730255f9c1bdd73cd5f9fe5b5da8dbd4a717205", size = 94625 } wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/1a/8f4d9a1461709756ace48c98f07772bc6d4519b1e48b5fa24a4061216256/watchfiles-1.0.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:229e6ec880eca20e0ba2f7e2249c85bae1999d330161f45c78d160832e026ee2", size = 391345 }, + { url = "https://files.pythonhosted.org/packages/bc/d2/6750b7b3527b1cdaa33731438432e7238a6c6c40a9924049e4cebfa40805/watchfiles-1.0.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5717021b199e8353782dce03bd8a8f64438832b84e2885c4a645f9723bf656d9", size = 381515 }, + { url = "https://files.pythonhosted.org/packages/4e/17/80500e42363deef1e4b4818729ed939aaddc56f82f4e72b2508729dd3c6b/watchfiles-1.0.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0799ae68dfa95136dde7c472525700bd48777875a4abb2ee454e3ab18e9fc712", size = 449767 }, + { url = "https://files.pythonhosted.org/packages/10/37/1427fa4cfa09adbe04b1e97bced19a29a3462cc64c78630787b613a23f18/watchfiles-1.0.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:43b168bba889886b62edb0397cab5b6490ffb656ee2fcb22dec8bfeb371a9e12", size = 455677 }, + { url = "https://files.pythonhosted.org/packages/c5/7a/39e9397f3a19cb549a7d380412fd9e507d4854eddc0700bfad10ef6d4dba/watchfiles-1.0.4-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb2c46e275fbb9f0c92e7654b231543c7bbfa1df07cdc4b99fa73bedfde5c844", size = 482219 }, + { url = "https://files.pythonhosted.org/packages/45/2d/7113931a77e2ea4436cad0c1690c09a40a7f31d366f79c6f0a5bc7a4f6d5/watchfiles-1.0.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:857f5fc3aa027ff5e57047da93f96e908a35fe602d24f5e5d8ce64bf1f2fc733", size = 518830 }, + { url = "https://files.pythonhosted.org/packages/f9/1b/50733b1980fa81ef3c70388a546481ae5fa4c2080040100cd7bf3bf7b321/watchfiles-1.0.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55ccfd27c497b228581e2838d4386301227fc0cb47f5a12923ec2fe4f97b95af", size = 497997 }, + { url = "https://files.pythonhosted.org/packages/2b/b4/9396cc61b948ef18943e7c85ecfa64cf940c88977d882da57147f62b34b1/watchfiles-1.0.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c11ea22304d17d4385067588123658e9f23159225a27b983f343fcffc3e796a", size = 452249 }, + { url = "https://files.pythonhosted.org/packages/fb/69/0c65a5a29e057ad0dc691c2fa6c23b2983c7dabaa190ba553b29ac84c3cc/watchfiles-1.0.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:74cb3ca19a740be4caa18f238298b9d472c850f7b2ed89f396c00a4c97e2d9ff", size = 614412 }, + { url = "https://files.pythonhosted.org/packages/7f/b9/319fcba6eba5fad34327d7ce16a6b163b39741016b1996f4a3c96b8dd0e1/watchfiles-1.0.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c7cce76c138a91e720d1df54014a047e680b652336e1b73b8e3ff3158e05061e", size = 611982 }, + { url = "https://files.pythonhosted.org/packages/f1/47/143c92418e30cb9348a4387bfa149c8e0e404a7c5b0585d46d2f7031b4b9/watchfiles-1.0.4-cp312-cp312-win32.whl", hash = "sha256:b045c800d55bc7e2cadd47f45a97c7b29f70f08a7c2fa13241905010a5493f94", size = 271822 }, + { url = "https://files.pythonhosted.org/packages/ea/94/b0165481bff99a64b29e46e07ac2e0df9f7a957ef13bec4ceab8515f44e3/watchfiles-1.0.4-cp312-cp312-win_amd64.whl", hash = "sha256:c2acfa49dd0ad0bf2a9c0bb9a985af02e89345a7189be1efc6baa085e0f72d7c", size = 285441 }, + { url = "https://files.pythonhosted.org/packages/11/de/09fe56317d582742d7ca8c2ca7b52a85927ebb50678d9b0fa8194658f536/watchfiles-1.0.4-cp312-cp312-win_arm64.whl", hash = "sha256:22bb55a7c9e564e763ea06c7acea24fc5d2ee5dfc5dafc5cfbedfe58505e9f90", size = 277141 }, { url = "https://files.pythonhosted.org/packages/08/98/f03efabec64b5b1fa58c0daab25c68ef815b0f320e54adcacd0d6847c339/watchfiles-1.0.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:8012bd820c380c3d3db8435e8cf7592260257b378b649154a7948a663b5f84e9", size = 390954 }, { url = "https://files.pythonhosted.org/packages/16/09/4dd49ba0a32a45813debe5fb3897955541351ee8142f586303b271a02b40/watchfiles-1.0.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa216f87594f951c17511efe5912808dfcc4befa464ab17c98d387830ce07b60", size = 381133 }, { url = "https://files.pythonhosted.org/packages/76/59/5aa6fc93553cd8d8ee75c6247763d77c02631aed21551a97d94998bf1dae/watchfiles-1.0.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c9953cf85529c05b24705639ffa390f78c26449e15ec34d5339e8108c7c407", size = 449516 }, @@ -826,6 +1012,17 @@ version = "14.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/94/54/8359678c726243d19fae38ca14a334e740782336c9f19700858c4eb64a1e/websockets-14.2.tar.gz", hash = "sha256:5059ed9c54945efb321f097084b4c7e52c246f2c869815876a69d1efc4ad6eb5", size = 164394 } wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/81/04f7a397653dc8bec94ddc071f34833e8b99b13ef1a3804c149d59f92c18/websockets-14.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1f20522e624d7ffbdbe259c6b6a65d73c895045f76a93719aa10cd93b3de100c", size = 163096 }, + { url = "https://files.pythonhosted.org/packages/ec/c5/de30e88557e4d70988ed4d2eabd73fd3e1e52456b9f3a4e9564d86353b6d/websockets-14.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:647b573f7d3ada919fd60e64d533409a79dcf1ea21daeb4542d1d996519ca967", size = 160758 }, + { url = "https://files.pythonhosted.org/packages/e5/8c/d130d668781f2c77d106c007b6c6c1d9db68239107c41ba109f09e6c218a/websockets-14.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6af99a38e49f66be5a64b1e890208ad026cda49355661549c507152113049990", size = 160995 }, + { url = "https://files.pythonhosted.org/packages/a6/bc/f6678a0ff17246df4f06765e22fc9d98d1b11a258cc50c5968b33d6742a1/websockets-14.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:091ab63dfc8cea748cc22c1db2814eadb77ccbf82829bac6b2fbe3401d548eda", size = 170815 }, + { url = "https://files.pythonhosted.org/packages/d8/b2/8070cb970c2e4122a6ef38bc5b203415fd46460e025652e1ee3f2f43a9a3/websockets-14.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b374e8953ad477d17e4851cdc66d83fdc2db88d9e73abf755c94510ebddceb95", size = 169759 }, + { url = "https://files.pythonhosted.org/packages/81/da/72f7caabd94652e6eb7e92ed2d3da818626e70b4f2b15a854ef60bf501ec/websockets-14.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a39d7eceeea35db85b85e1169011bb4321c32e673920ae9c1b6e0978590012a3", size = 170178 }, + { url = "https://files.pythonhosted.org/packages/31/e0/812725b6deca8afd3a08a2e81b3c4c120c17f68c9b84522a520b816cda58/websockets-14.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0a6f3efd47ffd0d12080594f434faf1cd2549b31e54870b8470b28cc1d3817d9", size = 170453 }, + { url = "https://files.pythonhosted.org/packages/66/d3/8275dbc231e5ba9bb0c4f93144394b4194402a7a0c8ffaca5307a58ab5e3/websockets-14.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:065ce275e7c4ffb42cb738dd6b20726ac26ac9ad0a2a48e33ca632351a737267", size = 169830 }, + { url = "https://files.pythonhosted.org/packages/a3/ae/e7d1a56755ae15ad5a94e80dd490ad09e345365199600b2629b18ee37bc7/websockets-14.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e9d0e53530ba7b8b5e389c02282f9d2aa47581514bd6049d3a7cffe1385cf5fe", size = 169824 }, + { url = "https://files.pythonhosted.org/packages/b6/32/88ccdd63cb261e77b882e706108d072e4f1c839ed723bf91a3e1f216bf60/websockets-14.2-cp312-cp312-win32.whl", hash = "sha256:20e6dd0984d7ca3037afcb4494e48c74ffb51e8013cac71cf607fffe11df7205", size = 163981 }, + { url = "https://files.pythonhosted.org/packages/b3/7d/32cdb77990b3bdc34a306e0a0f73a1275221e9a66d869f6ff833c95b56ef/websockets-14.2-cp312-cp312-win_amd64.whl", hash = "sha256:44bba1a956c2c9d268bdcdf234d5e5ff4c9b6dc3e300545cbe99af59dda9dcce", size = 164421 }, { url = "https://files.pythonhosted.org/packages/82/94/4f9b55099a4603ac53c2912e1f043d6c49d23e94dd82a9ce1eb554a90215/websockets-14.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6f1372e511c7409a542291bce92d6c83320e02c9cf392223272287ce55bc224e", size = 163102 }, { url = "https://files.pythonhosted.org/packages/8e/b7/7484905215627909d9a79ae07070057afe477433fdacb59bf608ce86365a/websockets-14.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4da98b72009836179bb596a92297b1a61bb5a830c0e483a7d0766d45070a08ad", size = 160766 }, { url = "https://files.pythonhosted.org/packages/a3/a4/edb62efc84adb61883c7d2c6ad65181cb087c64252138e12d655989eec05/websockets-14.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8a86a269759026d2bde227652b87be79f8a734e582debf64c9d302faa1e9f03", size = 160998 }, @@ -851,6 +1048,22 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/b7/9d/4b94a8e6d2b51b599516a5cb88e5bc99b4d8d4583e468057eaa29d5f0918/yarl-1.18.3.tar.gz", hash = "sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1", size = 181062 } wheels = [ + { url = "https://files.pythonhosted.org/packages/33/85/bd2e2729752ff4c77338e0102914897512e92496375e079ce0150a6dc306/yarl-1.18.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50", size = 142644 }, + { url = "https://files.pythonhosted.org/packages/ff/74/1178322cc0f10288d7eefa6e4a85d8d2e28187ccab13d5b844e8b5d7c88d/yarl-1.18.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576", size = 94962 }, + { url = "https://files.pythonhosted.org/packages/be/75/79c6acc0261e2c2ae8a1c41cf12265e91628c8c58ae91f5ff59e29c0787f/yarl-1.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640", size = 92795 }, + { url = "https://files.pythonhosted.org/packages/6b/32/927b2d67a412c31199e83fefdce6e645247b4fb164aa1ecb35a0f9eb2058/yarl-1.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2", size = 332368 }, + { url = "https://files.pythonhosted.org/packages/19/e5/859fca07169d6eceeaa4fde1997c91d8abde4e9a7c018e371640c2da2b71/yarl-1.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75", size = 342314 }, + { url = "https://files.pythonhosted.org/packages/08/75/76b63ccd91c9e03ab213ef27ae6add2e3400e77e5cdddf8ed2dbc36e3f21/yarl-1.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512", size = 341987 }, + { url = "https://files.pythonhosted.org/packages/1a/e1/a097d5755d3ea8479a42856f51d97eeff7a3a7160593332d98f2709b3580/yarl-1.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba", size = 336914 }, + { url = "https://files.pythonhosted.org/packages/0b/42/e1b4d0e396b7987feceebe565286c27bc085bf07d61a59508cdaf2d45e63/yarl-1.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb", size = 325765 }, + { url = "https://files.pythonhosted.org/packages/7e/18/03a5834ccc9177f97ca1bbb245b93c13e58e8225276f01eedc4cc98ab820/yarl-1.18.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272", size = 344444 }, + { url = "https://files.pythonhosted.org/packages/c8/03/a713633bdde0640b0472aa197b5b86e90fbc4c5bc05b727b714cd8a40e6d/yarl-1.18.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6", size = 340760 }, + { url = "https://files.pythonhosted.org/packages/eb/99/f6567e3f3bbad8fd101886ea0276c68ecb86a2b58be0f64077396cd4b95e/yarl-1.18.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e", size = 346484 }, + { url = "https://files.pythonhosted.org/packages/8e/a9/84717c896b2fc6cb15bd4eecd64e34a2f0a9fd6669e69170c73a8b46795a/yarl-1.18.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb", size = 359864 }, + { url = "https://files.pythonhosted.org/packages/1e/2e/d0f5f1bef7ee93ed17e739ec8dbcb47794af891f7d165fa6014517b48169/yarl-1.18.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393", size = 364537 }, + { url = "https://files.pythonhosted.org/packages/97/8a/568d07c5d4964da5b02621a517532adb8ec5ba181ad1687191fffeda0ab6/yarl-1.18.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285", size = 357861 }, + { url = "https://files.pythonhosted.org/packages/7d/e3/924c3f64b6b3077889df9a1ece1ed8947e7b61b0a933f2ec93041990a677/yarl-1.18.3-cp312-cp312-win32.whl", hash = "sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2", size = 84097 }, + { url = "https://files.pythonhosted.org/packages/34/45/0e055320daaabfc169b21ff6174567b2c910c45617b0d79c68d7ab349b02/yarl-1.18.3-cp312-cp312-win_amd64.whl", hash = "sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477", size = 90399 }, { url = "https://files.pythonhosted.org/packages/30/c7/c790513d5328a8390be8f47be5d52e141f78b66c6c48f48d241ca6bd5265/yarl-1.18.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb", size = 140789 }, { url = "https://files.pythonhosted.org/packages/30/aa/a2f84e93554a578463e2edaaf2300faa61c8701f0898725842c704ba5444/yarl-1.18.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa", size = 94144 }, { url = "https://files.pythonhosted.org/packages/c6/fc/d68d8f83714b221a85ce7866832cba36d7c04a68fa6a960b908c2c84f325/yarl-1.18.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782", size = 91974 }, diff --git a/ui/package.json b/ui/package.json index a76e2f7..5a768d1 100644 --- a/ui/package.json +++ b/ui/package.json @@ -49,6 +49,7 @@ "@types/react-router-dom": "^5.3.3", "axios": "^1.8.4", "react-router-dom": "^7.3.0", - "react-stately": "^3.36.1" + "react-stately": "^3.36.1", + "ts-pattern": "^5.6.2" } } diff --git a/ui/pnpm-lock.yaml b/ui/pnpm-lock.yaml index 709fe3a..716fecd 100644 --- a/ui/pnpm-lock.yaml +++ b/ui/pnpm-lock.yaml @@ -29,6 +29,9 @@ importers: react-stately: specifier: ^3.36.1 version: 3.36.1(react@19.0.0) + ts-pattern: + specifier: ^5.6.2 + version: 5.6.2 devDependencies: '@eslint/js': specifier: ^9.22.0 @@ -2607,6 +2610,9 @@ packages: peerDependencies: typescript: '>=4.8.4' + ts-pattern@5.6.2: + resolution: {integrity: sha512-d4IxJUXROL5NCa3amvMg6VQW2HVtZYmUTPfvVtO7zJWGYLJ+mry9v2OmYm+z67aniQoQ8/yFNadiEwtNS9qQiw==} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -5883,6 +5889,8 @@ snapshots: dependencies: typescript: 5.7.3 + ts-pattern@5.6.2: {} + tslib@2.8.1: {} turbo-stream@2.4.0: {} diff --git a/ui/src/App.tsx b/ui/src/App.tsx index e12c3b0..6caa8a9 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -1,11 +1,10 @@ -import { Button } from "./ui-library/button"; -import { Header } from "./ui-library/header"; import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; import { LoginPage } from "./pages/login"; import { SignUpPage } from "./pages/signup"; -import logo from "./assets/icon.jpg"; import { ThemeProvider } from "./contexts/ThemeContext"; import { twMerge } from "tailwind-merge"; +import { ResetPasswordPage } from "./pages/reset-password"; +import { LandingPage } from "./pages/landing"; export const App = () => { return ( @@ -18,650 +17,10 @@ export const App = () => { )} > - -
-
- {/* Hero Section */} -
-
-
-
-

- Maîtrisez vos dépenses de chantier -

-

- XTablo aide les entreprises du BTP à suivre, analyser et - optimiser leurs dépenses de projet. Obtenez des insights - en temps réel sur vos coûts et prenez de meilleures - décisions financières. -

-
- -
-
-
-
-
- - {/* Features Section */} -
-
-

- Une solution complète pour votre entreprise -

-

- Découvrez comment XTablo peut transformer votre - gestion des dépenses -

-
-
-
-
- - - -
-

- Suivi en temps réel -

-

- Visualisez vos dépenses en temps réel et prenez des - décisions éclairées -

-
-
-
- - - -
-

- Rapports personnalisés -

-

- Générez des rapports détaillés adaptés à vos besoins -

-
-
-
- - - -
-

- Optimisation des coûts -

-

- Identifiez les opportunités d'optimisation et - réduisez vos dépenses -

-
-
-
- - {/* Testimonials Section */} -
-
-

- Fait confiance par les entreprises du BTP -

-

- Découvrez ce que nos clients disent de XTablo -

-
-
-
-

- "XTablo a révolutionné notre gestion des - dépenses. Nous pouvons maintenant suivre chaque euro - en temps réel et prendre de meilleures décisions - pour nos projets de construction." -

-
-
-
-

- Michel Dubois -

-

- Chef de Projet -

-
-
-
- -
-

- "Les fonctionnalités de suivi des dépenses sont - exactement ce dont nous avions besoin. Cela nous a - permis de réduire nos coûts de 15% et - d'améliorer significativement nos marges." -

-
-
-
-

- Sophie Martin -

-

- Directrice Financière -

-
-
-
- -
-

- "La gestion des dépenses sur plusieurs - chantiers n'a jamais été aussi simple. XTablo - nous donne une visibilité totale sur nos - coûts." -

-
-
-
-

- David Laurent -

-

- Chef de Chantier -

-
-
-
-
-
- - {/* Pricing Section */} -
-
-

- Des tarifs adaptés à vos besoins -

-

- Choisissez le plan qui correspond le mieux à votre - entreprise -

-
-
-
-

- Starter -

-
- - 12€ - - - /mois - -
-
    -
  • - - - - Jusqu'à 5 chantiers -
  • -
  • - - - - Suivi des dépenses en temps réel -
  • -
  • - - - - Rapports mensuels -
  • -
  • - - - - Support par email -
  • -
- -
- -
-
- - Plus populaire - -
-

- Pro -

-
- - 25€ - - - /mois - -
-
    -
  • - - - - Chantiers illimités -
  • -
  • - - - - Suivi des dépenses en temps réel -
  • -
  • - - - - Rapports personnalisés -
  • -
  • - - - - Support prioritaire -
  • -
  • - - - - API disponible -
  • -
- -
-
-
- - {/* CTA Section */} -
-
-

- Prêt à optimiser vos dépenses de projet ? -

-

- Commencez votre essai gratuit de 14 jours - aujourd'hui. Aucune carte bancaire requise. -

-
- - -
-
-
-
- - {/* Footer */} - - - } - /> + } /> } /> } /> + } />