Spaces:
Runtime error
Runtime error
Commit ·
f2cb2b4
1
Parent(s): 7761651
Few changes for making it production ready
Browse files- src/data_ingestion/saving_data_to_postgres.py → .dockerignore +0 -0
- Dockerfile +0 -0
- config.py +4 -6
- docker-compose.yml +16 -0
- pyproject.toml +2 -1
- scraper.log +52 -0
- src/data_ingestion/clean_data.py +28 -12
- src/data_ingestion/fetch_anime.py +80 -38
- src/data_ingestion/load_to_neo4j.py +0 -24
- src/data_ingestion/load_to_postgres.py +53 -0
- src/database/__init__.py +17 -0
- src/database/crud.py +0 -0
- src/database/models.py +56 -0
- src/database/session.py +5 -0
- src/utils/neo4j_client.py +0 -49
- uv.lock +149 -33
src/data_ingestion/saving_data_to_postgres.py → .dockerignore
RENAMED
|
File without changes
|
Dockerfile
ADDED
|
File without changes
|
config.py
CHANGED
|
@@ -4,13 +4,11 @@ import os
|
|
| 4 |
|
| 5 |
class Settings(BaseSettings):
|
| 6 |
groq_api_key: str
|
| 7 |
-
neo4j_uri: str
|
| 8 |
-
neo4j_username: str
|
| 9 |
-
neo4j_password: str
|
| 10 |
-
neo4j_database: str
|
| 11 |
-
aura_instanceid: str
|
| 12 |
-
aura_instancename: str
|
| 13 |
model_name: str
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
class Config:
|
| 16 |
env_file = '.env'
|
|
|
|
| 4 |
|
| 5 |
class Settings(BaseSettings):
|
| 6 |
groq_api_key: str
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
model_name: str
|
| 8 |
+
postgres_user: str
|
| 9 |
+
postgres_password: str
|
| 10 |
+
postgres_db: str
|
| 11 |
+
database_url: str
|
| 12 |
|
| 13 |
class Config:
|
| 14 |
env_file = '.env'
|
docker-compose.yml
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
services:
|
| 2 |
+
db:
|
| 3 |
+
image: postgres:15-alpine
|
| 4 |
+
container_name: anime_postgres
|
| 5 |
+
restart: always
|
| 6 |
+
environment:
|
| 7 |
+
POSTGRES_USER: ${POSTGRES_USER}
|
| 8 |
+
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
| 9 |
+
POSTGRES_DB: ${POSTGRES_DB}
|
| 10 |
+
ports:
|
| 11 |
+
- "5433:5432"
|
| 12 |
+
volumes:
|
| 13 |
+
- postgres_data:/var/lib/postgresql/data
|
| 14 |
+
|
| 15 |
+
volumes:
|
| 16 |
+
postgres_data:
|
pyproject.toml
CHANGED
|
@@ -10,11 +10,12 @@ dependencies = [
|
|
| 10 |
"gradio>=6.2.0",
|
| 11 |
"langchain>=1.1.3",
|
| 12 |
"langchain-groq>=1.1.1",
|
| 13 |
-
"neo4j>=6.1.0",
|
| 14 |
"pandas>=2.3.3",
|
|
|
|
| 15 |
"python-dotenv>=1.2.1",
|
| 16 |
"requests>=2.32.5",
|
| 17 |
"sentence-transformers>=5.2.0",
|
|
|
|
| 18 |
"torch>=2.9.1",
|
| 19 |
"torchvision>=0.24.1",
|
| 20 |
"uvicorn>=0.38.0",
|
|
|
|
| 10 |
"gradio>=6.2.0",
|
| 11 |
"langchain>=1.1.3",
|
| 12 |
"langchain-groq>=1.1.1",
|
|
|
|
| 13 |
"pandas>=2.3.3",
|
| 14 |
+
"psycopg2-binary>=2.9.11",
|
| 15 |
"python-dotenv>=1.2.1",
|
| 16 |
"requests>=2.32.5",
|
| 17 |
"sentence-transformers>=5.2.0",
|
| 18 |
+
"sqlmodel>=0.0.37",
|
| 19 |
"torch>=2.9.1",
|
| 20 |
"torchvision>=0.24.1",
|
| 21 |
"uvicorn>=0.38.0",
|
scraper.log
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Critical error on page 41: 504 Server Error: Gateway Time-out for url: https://api.jikan.moe/v4/anime?page=41&limit=25&order_by=popularity&sort=asc
|
| 2 |
+
Saved 1000 anime to data/raw/raw_anime.json
|
| 3 |
+
|
| 4 |
+
Sample anime:
|
| 5 |
+
{
|
| 6 |
+
"mal_id": 16498,
|
| 7 |
+
"url": "https://myanimelist.net/anime/16498/Shingeki_no_Kyojin",
|
| 8 |
+
"images": {
|
| 9 |
+
"jpg": {
|
| 10 |
+
"image_url": "https://cdn.myanimelist.net/images/anime/10/47347.jpg",
|
| 11 |
+
"small_image_url": "https://cdn.myanimelist.net/images/anime/10/47347t.jpg",
|
| 12 |
+
"large_image_url": "https://cdn.myanimelist.net/images/anime/10/47347l.jpg"
|
| 13 |
+
},
|
| 14 |
+
"webp": {
|
| 15 |
+
"image_url": "https://cdn.myanimelist.net/images/anime/10/47347.webp",
|
| 16 |
+
"small_image_url": "https://cdn.myanimelist.net/images/anime/10/47347t.webp",
|
| 17 |
+
"large_image_url": "https://cdn.myanimelist.net/images/anime/10/47347l.webp"
|
| 18 |
+
}
|
| 19 |
+
},
|
| 20 |
+
"title": "Shingeki no Kyojin",
|
| 21 |
+
"title_english": "Attack on Titan",
|
| 22 |
+
"synopsis": "Centuries ago, mankind was slaughtered to near extinction by monstrous humanoid creatures called Titans, forcing humans to hide in fear behind enormous concentric walls. What makes these giants truly terrifying is that their taste for human flesh is not born out of hunger but what appears to be out of pleasure. To ensure their survival, the remnants of humanity began living within defensive barriers, resulting in one hundred years without a single titan encounter. However, that fragile calm is soon shattered when a colossal Titan manages to breach the supposedly impregnable outer wall, reigniting the fight for survival against the man-eating abominations.\n\nAfter witnessing a horrific personal loss at the hands of the invading creatures, Eren Yeager dedicates his life to their eradication by enlisting into the Survey Corps, an elite military unit that combats the merciless humanoids outside the protection of the walls. Eren, his adopted sister Mikasa Ackerman, and his childhood friend Armin Arlert join the brutal war against the Titans and race to discover a way of defeating them before the last walls are breached.\n\n[Written by MAL Rewrite]",
|
| 23 |
+
"genres": [
|
| 24 |
+
"Action",
|
| 25 |
+
"Award Winning",
|
| 26 |
+
"Drama",
|
| 27 |
+
"Suspense"
|
| 28 |
+
],
|
| 29 |
+
"studios": [
|
| 30 |
+
"Wit Studio"
|
| 31 |
+
],
|
| 32 |
+
"themes": [
|
| 33 |
+
"Gore",
|
| 34 |
+
"Military",
|
| 35 |
+
"Survival"
|
| 36 |
+
],
|
| 37 |
+
"demographics": [
|
| 38 |
+
"Shounen"
|
| 39 |
+
],
|
| 40 |
+
"type": "TV",
|
| 41 |
+
"episodes": 25,
|
| 42 |
+
"score": 8.57,
|
| 43 |
+
"scored_by": 3036922,
|
| 44 |
+
"rank": 120,
|
| 45 |
+
"popularity": 1,
|
| 46 |
+
"year": 2013,
|
| 47 |
+
"rating": "R - 17+ (violence & profanity)",
|
| 48 |
+
"season": "spring",
|
| 49 |
+
"aired_from": "2013-04-07T00:00:00+00:00",
|
| 50 |
+
"aired_to": "2013-09-29T00:00:00+00:00",
|
| 51 |
+
"favorites": 187237
|
| 52 |
+
}
|
src/data_ingestion/clean_data.py
CHANGED
|
@@ -3,6 +3,7 @@ import pandas as pd
|
|
| 3 |
import logging
|
| 4 |
|
| 5 |
logger = logging.getLogger(__name__)
|
|
|
|
| 6 |
|
| 7 |
|
| 8 |
class AnimeDataCleaner:
|
|
@@ -89,19 +90,33 @@ class AnimeDataCleaner:
|
|
| 89 |
for anime in anime_list:
|
| 90 |
record = {
|
| 91 |
"mal_id": anime["mal_id"],
|
| 92 |
-
"
|
| 93 |
-
"
|
| 94 |
-
|
| 95 |
-
"
|
| 96 |
-
|
| 97 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
"type": anime.get("type"),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
"year": anime.get("year"),
|
| 100 |
-
"
|
| 101 |
-
"aired_from": anime.get("aired_from", ""),
|
| 102 |
-
"aired_to": anime.get("aired_to", ""),
|
| 103 |
"rating": anime.get("rating"),
|
| 104 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
}
|
| 106 |
|
| 107 |
records.append(record)
|
|
@@ -125,14 +140,15 @@ if __name__ == "__main__":
|
|
| 125 |
cleaner = AnimeDataCleaner()
|
| 126 |
|
| 127 |
print("Loading raw data....")
|
| 128 |
-
raw_animes = cleaner.load_raw_data()
|
| 129 |
|
| 130 |
valid_animes = cleaner.filter_valid_anime(raw_animes)
|
| 131 |
|
| 132 |
print("\nPreparing data for embedding...")
|
| 133 |
df = cleaner.prepare_for_embedding(valid_animes)
|
| 134 |
|
| 135 |
-
cleaner.save_processed_data(
|
|
|
|
| 136 |
|
| 137 |
print("\nSample searchable text:")
|
| 138 |
print(df.iloc[0]["searchable_text"][:500])
|
|
|
|
| 3 |
import logging
|
| 4 |
|
| 5 |
logger = logging.getLogger(__name__)
|
| 6 |
+
logging.basicConfig(level=logging.INFO)
|
| 7 |
|
| 8 |
|
| 9 |
class AnimeDataCleaner:
|
|
|
|
| 90 |
for anime in anime_list:
|
| 91 |
record = {
|
| 92 |
"mal_id": anime["mal_id"],
|
| 93 |
+
"url": anime.get("url"),
|
| 94 |
+
"title": anime.get("title"),
|
| 95 |
+
"title_english": anime.get("title_english"),
|
| 96 |
+
"synopsis": AnimeDataCleaner.clean_synopsis(anime.get("synopsis", "")),
|
| 97 |
+
|
| 98 |
+
# Keep these as native dicts/lists for Postgres JSONB!
|
| 99 |
+
"images": anime.get("images", {}),
|
| 100 |
+
"genres": anime.get("genres", []),
|
| 101 |
+
"studios": anime.get("studios", []),
|
| 102 |
+
"themes": anime.get("themes", []),
|
| 103 |
+
"demographics": anime.get("demographics", []),
|
| 104 |
+
|
| 105 |
"type": anime.get("type"),
|
| 106 |
+
"episodes": anime.get("episodes"),
|
| 107 |
+
"score": anime.get("score"),
|
| 108 |
+
"scored_by": anime.get("scored_by"),
|
| 109 |
+
"rank": anime.get("rank"),
|
| 110 |
+
"popularity": anime.get("popularity"),
|
| 111 |
"year": anime.get("year"),
|
| 112 |
+
"season": anime.get("season"),
|
|
|
|
|
|
|
| 113 |
"rating": anime.get("rating"),
|
| 114 |
+
"aired_from": anime.get("aired_from"),
|
| 115 |
+
"aired_to": anime.get("aired_to"),
|
| 116 |
+
"favorites": anime.get("favorites"),
|
| 117 |
+
|
| 118 |
+
# And our custom RAG field
|
| 119 |
+
"searchable_text": AnimeDataCleaner.create_searchable_text(anime)
|
| 120 |
}
|
| 121 |
|
| 122 |
records.append(record)
|
|
|
|
| 140 |
cleaner = AnimeDataCleaner()
|
| 141 |
|
| 142 |
print("Loading raw data....")
|
| 143 |
+
raw_animes = cleaner.load_raw_data("data/raw/raw_anime.json")
|
| 144 |
|
| 145 |
valid_animes = cleaner.filter_valid_anime(raw_animes)
|
| 146 |
|
| 147 |
print("\nPreparing data for embedding...")
|
| 148 |
df = cleaner.prepare_for_embedding(valid_animes)
|
| 149 |
|
| 150 |
+
cleaner.save_processed_data(
|
| 151 |
+
df, filepath="data/processed/anime_clean.csv")
|
| 152 |
|
| 153 |
print("\nSample searchable text:")
|
| 154 |
print(df.iloc[0]["searchable_text"][:500])
|
src/data_ingestion/fetch_anime.py
CHANGED
|
@@ -11,6 +11,8 @@ def convert_datetime(dt: str | None):
|
|
| 11 |
return datetime.fromisoformat(dt)
|
| 12 |
|
| 13 |
|
|
|
|
|
|
|
| 14 |
logger = logging.getLogger(__name__)
|
| 15 |
|
| 16 |
|
|
@@ -22,55 +24,94 @@ class AnimeDataFetcher:
|
|
| 22 |
def __init__(self):
|
| 23 |
self.session = requests.Session()
|
| 24 |
|
| 25 |
-
def
|
| 26 |
"""
|
| 27 |
-
Fetches
|
| 28 |
-
Args:
|
| 29 |
-
limit: Number of anime to fetch(max ~500 with pagination)
|
| 30 |
-
Returns:
|
| 31 |
-
List of anime dictionaries
|
| 32 |
"""
|
| 33 |
-
|
| 34 |
all_animes = []
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
break
|
| 63 |
|
| 64 |
-
return all_animes[:
|
| 65 |
|
| 66 |
def extract_relevant_fields(self, anime: dict) -> dict:
|
| 67 |
"""Extract only fields we need for RAG"""
|
| 68 |
return {
|
| 69 |
"mal_id": anime.get("mal_id"),
|
|
|
|
|
|
|
| 70 |
"title": anime.get("title"),
|
| 71 |
"title_english": anime.get("title_english"),
|
| 72 |
"synopsis": anime.get("synopsis"),
|
| 73 |
"genres": [g["name"] for g in anime.get("genres", [])],
|
|
|
|
| 74 |
"themes": [t["name"] for t in anime.get("themes", [])],
|
| 75 |
"demographics": [d["name"] for d in anime.get("demographics", [])],
|
| 76 |
"type": anime.get("type"),
|
|
@@ -98,12 +139,13 @@ class AnimeDataFetcher:
|
|
| 98 |
if __name__ == "__main__":
|
| 99 |
fetcher = AnimeDataFetcher()
|
| 100 |
|
| 101 |
-
logger.info("Fetching top anime from MyAnimeList...")
|
| 102 |
-
raw_anime = fetcher.
|
| 103 |
|
| 104 |
processed_anime = [fetcher.extract_relevant_fields(a) for a in raw_anime]
|
| 105 |
|
| 106 |
-
fetcher.save_raw_data(processed_anime
|
|
|
|
| 107 |
|
| 108 |
print("\nSample anime: ")
|
| 109 |
print(json.dumps(processed_anime[0], indent=2, ensure_ascii=False))
|
|
|
|
| 11 |
return datetime.fromisoformat(dt)
|
| 12 |
|
| 13 |
|
| 14 |
+
logging.basicConfig(level=logging.INFO,
|
| 15 |
+
format='%(asctime)s - %(levelname)s - %(message)s')
|
| 16 |
logger = logging.getLogger(__name__)
|
| 17 |
|
| 18 |
|
|
|
|
| 24 |
def __init__(self):
|
| 25 |
self.session = requests.Session()
|
| 26 |
|
| 27 |
+
def fetch_bulk_anime(self, total_limit: int = 10000, filename: str = "raw_anime.json"):
|
| 28 |
"""
|
| 29 |
+
Fetches anime in bulk with Resume and Retry capabilities.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
"""
|
| 31 |
+
filepath = f"data/raw/{filename}"
|
| 32 |
all_animes = []
|
| 33 |
+
|
| 34 |
+
# --- RESUME LOGIC ---
|
| 35 |
+
try:
|
| 36 |
+
with open(filepath, "r", encoding="utf-8") as f:
|
| 37 |
+
all_animes = json.load(f)
|
| 38 |
+
logger.info(
|
| 39 |
+
f"Found existing data. Resuming from record {len(all_animes)}.")
|
| 40 |
+
except (FileNotFoundError, json.JSONDecodeError):
|
| 41 |
+
logger.info("No existing data found. Starting fresh.")
|
| 42 |
+
|
| 43 |
+
# Calculate the next page to fetch (25 items per page)
|
| 44 |
+
page = (len(all_animes) // 25) + 1
|
| 45 |
+
max_retries = 5
|
| 46 |
+
|
| 47 |
+
while len(all_animes) < total_limit:
|
| 48 |
+
retries = 0
|
| 49 |
+
success = False
|
| 50 |
+
|
| 51 |
+
while retries < max_retries and not success:
|
| 52 |
+
try:
|
| 53 |
+
logger.info(
|
| 54 |
+
f"🚀 Fetching page {page} (Progress: {len(all_animes)}/{total_limit})...")
|
| 55 |
+
response = self.session.get(
|
| 56 |
+
f"{self.BASE_URL}anime",
|
| 57 |
+
params={
|
| 58 |
+
"page": page,
|
| 59 |
+
"limit": 25,
|
| 60 |
+
"order_by": "popularity",
|
| 61 |
+
"sort": "asc"
|
| 62 |
+
},
|
| 63 |
+
timeout=30
|
| 64 |
+
)
|
| 65 |
+
|
| 66 |
+
if response.status_code == 429:
|
| 67 |
+
wait = 60 + (retries * 30) # Increasing wait time
|
| 68 |
+
logger.warning(f"⚠️ Rate limit! Sleeping {wait}s...")
|
| 69 |
+
time.sleep(wait)
|
| 70 |
+
retries += 1
|
| 71 |
+
continue
|
| 72 |
+
|
| 73 |
+
response.raise_for_status()
|
| 74 |
+
data = response.json()
|
| 75 |
+
anime_list = data.get("data", [])
|
| 76 |
+
|
| 77 |
+
if not anime_list:
|
| 78 |
+
logger.info("🏁 No more anime found in API.")
|
| 79 |
+
return all_animes
|
| 80 |
+
|
| 81 |
+
all_animes.extend(anime_list)
|
| 82 |
+
|
| 83 |
+
# --- AUTO-SAVE EVERY PAGE ---
|
| 84 |
+
# In production, we save often so we never lose more than 1 page of work
|
| 85 |
+
self.save_raw_data(all_animes, filename=filename)
|
| 86 |
+
|
| 87 |
+
success = True
|
| 88 |
+
page += 1
|
| 89 |
+
time.sleep(1.2) # Polite delay
|
| 90 |
+
|
| 91 |
+
except Exception as e:
|
| 92 |
+
retries += 1
|
| 93 |
+
logger.error(
|
| 94 |
+
f"❌ Error on page {page}: {e}. Retry {retries}/{max_retries}")
|
| 95 |
+
time.sleep(10 * retries)
|
| 96 |
+
|
| 97 |
+
if not success:
|
| 98 |
+
logger.critical(
|
| 99 |
+
f"🛑 Giving up on page {page}. Run script again later to resume.")
|
| 100 |
break
|
| 101 |
|
| 102 |
+
return all_animes[:total_limit]
|
| 103 |
|
| 104 |
def extract_relevant_fields(self, anime: dict) -> dict:
|
| 105 |
"""Extract only fields we need for RAG"""
|
| 106 |
return {
|
| 107 |
"mal_id": anime.get("mal_id"),
|
| 108 |
+
"url": anime.get("url", ""),
|
| 109 |
+
"images": anime.get("images", {}),
|
| 110 |
"title": anime.get("title"),
|
| 111 |
"title_english": anime.get("title_english"),
|
| 112 |
"synopsis": anime.get("synopsis"),
|
| 113 |
"genres": [g["name"] for g in anime.get("genres", [])],
|
| 114 |
+
"studios": [s["name"] for s in anime.get("studios", [])],
|
| 115 |
"themes": [t["name"] for t in anime.get("themes", [])],
|
| 116 |
"demographics": [d["name"] for d in anime.get("demographics", [])],
|
| 117 |
"type": anime.get("type"),
|
|
|
|
| 139 |
if __name__ == "__main__":
|
| 140 |
fetcher = AnimeDataFetcher()
|
| 141 |
|
| 142 |
+
logger.info("Fetching top 10000 anime from MyAnimeList...")
|
| 143 |
+
raw_anime = fetcher.fetch_bulk_anime(total_limit=10000)
|
| 144 |
|
| 145 |
processed_anime = [fetcher.extract_relevant_fields(a) for a in raw_anime]
|
| 146 |
|
| 147 |
+
fetcher.save_raw_data(processed_anime,
|
| 148 |
+
filename="raw_anime.json")
|
| 149 |
|
| 150 |
print("\nSample anime: ")
|
| 151 |
print(json.dumps(processed_anime[0], indent=2, ensure_ascii=False))
|
src/data_ingestion/load_to_neo4j.py
DELETED
|
@@ -1,24 +0,0 @@
|
|
| 1 |
-
from neo4j import GraphDatabase
|
| 2 |
-
import pandas as pd
|
| 3 |
-
from src.utils.neo4j_client import Neo4j_Client
|
| 4 |
-
|
| 5 |
-
class AnimeGraphLoader:
|
| 6 |
-
"""Loads anime into Neo4j Graph"""
|
| 7 |
-
|
| 8 |
-
def __init__(self):
|
| 9 |
-
self.client = Neo4j_Client()
|
| 10 |
-
|
| 11 |
-
def clear_database(self):
|
| 12 |
-
"""Delete all nodes (use carefully !)"""
|
| 13 |
-
query = "MATCH (n) DETACH DELETE n"
|
| 14 |
-
self.client.run_query(query)
|
| 15 |
-
|
| 16 |
-
def create_constraints(self):
|
| 17 |
-
"""Create uniqueness constraints for performance"""
|
| 18 |
-
queries = [
|
| 19 |
-
"CREATE CONSTRAINT anime_id IF NOT EXISTS FOR (a: Anime) REQUIRE a.mal_id IS UNIQUE",
|
| 20 |
-
"CREATE CONSTRAINT genre_name IF NOT EXISTS FOR (g:Genre) REQUIRE g.name IS UNIQUE",
|
| 21 |
-
"CREATE CONSTRAINT theme_name IF NOT EXISTS FOR (t:Theme) REQUIRE t.name IS UNIQUE",
|
| 22 |
-
"CREATE CONSTRAINT demographic_name IF NOT EXISTS FOR (d:Demographic) REQUIRE d.name IS UNIQUE",
|
| 23 |
-
"CREAE CONSTRAINT content_type IF NOT EXISTS FOR (t: Type) REQUIRE t.type IS UNIUE"
|
| 24 |
-
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/data_ingestion/load_to_postgres.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
import logging
|
| 3 |
+
from sqlmodel import Session, select
|
| 4 |
+
from src.database.session import engine
|
| 5 |
+
from src.database.models import Animes
|
| 6 |
+
from src.database import init_db
|
| 7 |
+
|
| 8 |
+
init_db()
|
| 9 |
+
|
| 10 |
+
logging.basicConfig(level=logging.WARNING)
|
| 11 |
+
logger = logging.getLogger(__name__)
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def load_json_data(filepath: str = "data/processed/anime_clean.json") -> list[dict]:
|
| 15 |
+
"""Reads the cleaned JSON file."""
|
| 16 |
+
with open(filepath, 'r', encoding='utf-8') as f:
|
| 17 |
+
return json.load(f)
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def insert_animes_to_db(anime_list: list[dict]):
|
| 21 |
+
"""
|
| 22 |
+
Inject a list of anime dictionaries into PostgreSQL safely
|
| 23 |
+
"""
|
| 24 |
+
inserted_count = 0
|
| 25 |
+
skipped_count = 0
|
| 26 |
+
with Session(engine) as session:
|
| 27 |
+
for data in anime_list:
|
| 28 |
+
try:
|
| 29 |
+
existing = session.exec(
|
| 30 |
+
select(Animes).where(Animes.mal_id == data["mal_id"])
|
| 31 |
+
).first()
|
| 32 |
+
|
| 33 |
+
if not existing:
|
| 34 |
+
new_anime = Animes(**data)
|
| 35 |
+
session.add(new_anime)
|
| 36 |
+
inserted_count += 1
|
| 37 |
+
print(f"Inserted_count: {inserted_count}/{len(anime_list)} animes")
|
| 38 |
+
else:
|
| 39 |
+
skipped_count += 1
|
| 40 |
+
|
| 41 |
+
except Exception as e:
|
| 42 |
+
logger.error(
|
| 43 |
+
f"Error processing anime ID: {data.get("mal_id")}: {e}")
|
| 44 |
+
|
| 45 |
+
session.commit()
|
| 46 |
+
logger.info(
|
| 47 |
+
f"Injection complete! Inserted: {inserted_count} | Skipped (Duplicates): {skipped_count}")
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
if __name__ == "__main__":
|
| 51 |
+
anime_data = load_json_data(filepath="data/processed/anime_clean.json")
|
| 52 |
+
|
| 53 |
+
insert_animes_to_db(anime_data)
|
src/database/__init__.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import logging
|
| 2 |
+
from sqlmodel import SQLModel
|
| 3 |
+
from src.database.session import engine
|
| 4 |
+
from src.database.models import Animes, User
|
| 5 |
+
|
| 6 |
+
logging.basicConfig(level=logging.INFO)
|
| 7 |
+
logger = logging.getLogger(__name__)
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def init_db():
|
| 11 |
+
"""Connects to PostgreSQL DB and creates all tables defined in SQLModel classes"""
|
| 12 |
+
logger.info("Started table creation....")
|
| 13 |
+
try:
|
| 14 |
+
SQLModel.metadata.create_all(engine)
|
| 15 |
+
logger.info("Database Tables created successfully")
|
| 16 |
+
except Exception as e:
|
| 17 |
+
logger.error(f"Failed to create tables: {e}")
|
src/database/crud.py
ADDED
|
File without changes
|
src/database/models.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sqlmodel import SQLModel, Field, TIMESTAMP, text
|
| 2 |
+
from sqlalchemy import Column
|
| 3 |
+
from sqlalchemy.dialects.postgresql import JSONB
|
| 4 |
+
from datetime import datetime, timezone
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class Animes(SQLModel, table=True):
|
| 8 |
+
id: int | None = Field(default=None, primary_key=True)
|
| 9 |
+
|
| 10 |
+
mal_id: int = Field(index=True, unique=True)
|
| 11 |
+
url: str | None = Field(default=None)
|
| 12 |
+
|
| 13 |
+
title: str = Field(index=True)
|
| 14 |
+
title_english: str | None = Field(default=None)
|
| 15 |
+
searchable_text: str | None = Field(default=None)
|
| 16 |
+
|
| 17 |
+
synopsis: str | None = Field(default=None)
|
| 18 |
+
|
| 19 |
+
# Store nested JSON
|
| 20 |
+
images: dict = Field(sa_column=Column(JSONB))
|
| 21 |
+
|
| 22 |
+
# Arrays → Postgres ARRAY or JSON
|
| 23 |
+
genres: list[str] = Field(sa_column=Column(JSONB))
|
| 24 |
+
studios: list[str] = Field(sa_column=Column(JSONB))
|
| 25 |
+
themes: list[str] = Field(sa_column=Column(JSONB))
|
| 26 |
+
demographics: list[str] = Field(sa_column=Column(JSONB))
|
| 27 |
+
|
| 28 |
+
type: str | None = None
|
| 29 |
+
episodes: int | None = None
|
| 30 |
+
|
| 31 |
+
score: float | None = Field(default=None, index=True)
|
| 32 |
+
scored_by: int | None = None
|
| 33 |
+
|
| 34 |
+
rank: int | None = Field(default=None, index=True)
|
| 35 |
+
popularity: int | None = None
|
| 36 |
+
|
| 37 |
+
year: int | None = Field(default=None, index=True)
|
| 38 |
+
season: str | None = None
|
| 39 |
+
|
| 40 |
+
rating: str | None = None
|
| 41 |
+
|
| 42 |
+
aired_from: str | None = None
|
| 43 |
+
aired_to: str | None = None
|
| 44 |
+
|
| 45 |
+
favorites: int | None = None
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
class User(SQLModel, table=True):
|
| 49 |
+
id: int | None = Field(default=None, primary_key=True)
|
| 50 |
+
email: str = Field(unique=True, index=True)
|
| 51 |
+
hashed_password: str
|
| 52 |
+
|
| 53 |
+
created_at: datetime | None = Field(sa_column=Column(TIMESTAMP(timezone=True),
|
| 54 |
+
nullable=True,
|
| 55 |
+
server_default=text("NOW()")))
|
| 56 |
+
is_active: bool = Field(default=True)
|
src/database/session.py
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sqlmodel import create_engine
|
| 2 |
+
import os
|
| 3 |
+
from config import settings
|
| 4 |
+
|
| 5 |
+
engine = create_engine(settings.database_url, echo=True)
|
src/utils/neo4j_client.py
DELETED
|
@@ -1,49 +0,0 @@
|
|
| 1 |
-
from dotenv import load_dotenv
|
| 2 |
-
from neo4j import GraphDatabase
|
| 3 |
-
|
| 4 |
-
from config import settings
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
class Neo4j_Client:
|
| 8 |
-
"""Neo4j database client"""
|
| 9 |
-
|
| 10 |
-
def __init__(self):
|
| 11 |
-
uri = settings.neo4j_uri
|
| 12 |
-
user = settings.neo4j_username
|
| 13 |
-
password = settings.neo4j_password
|
| 14 |
-
try:
|
| 15 |
-
self.driver = GraphDatabase.driver(
|
| 16 |
-
uri, auth=(user, password)) # type: ignore
|
| 17 |
-
self.driver.verify_connectivity()
|
| 18 |
-
|
| 19 |
-
except Exception as e:
|
| 20 |
-
raise e
|
| 21 |
-
|
| 22 |
-
def close(self):
|
| 23 |
-
self.driver.close()
|
| 24 |
-
|
| 25 |
-
def verify_connectivity(self):
|
| 26 |
-
"""Test connection"""
|
| 27 |
-
with self.driver.session() as session:
|
| 28 |
-
result = session.run("RETURN 'Connection Successful !' AS message")
|
| 29 |
-
record = result.single()
|
| 30 |
-
if record['message']: #type: ignore
|
| 31 |
-
return record["message"] # type: ignore
|
| 32 |
-
else:
|
| 33 |
-
return "Connection failed"
|
| 34 |
-
|
| 35 |
-
def run_query(self, query, parameters=None):
|
| 36 |
-
with self.driver.session() as session:
|
| 37 |
-
result = session.run(query, parameters or {})
|
| 38 |
-
return [record.data() for record in result]
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
if __name__ == '__main__':
|
| 42 |
-
client = Neo4j_Client()
|
| 43 |
-
|
| 44 |
-
message = client.verify_connectivity()
|
| 45 |
-
print(f"Message: {message}")
|
| 46 |
-
|
| 47 |
-
result = client.run_query("RETURN 1 + 1 AS result")
|
| 48 |
-
print(f"Test query result: {result}")
|
| 49 |
-
client.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uv.lock
CHANGED
|
@@ -32,11 +32,12 @@ dependencies = [
|
|
| 32 |
{ name = "gradio" },
|
| 33 |
{ name = "langchain" },
|
| 34 |
{ name = "langchain-groq" },
|
| 35 |
-
{ name = "neo4j" },
|
| 36 |
{ name = "pandas" },
|
|
|
|
| 37 |
{ name = "python-dotenv" },
|
| 38 |
{ name = "requests" },
|
| 39 |
{ name = "sentence-transformers" },
|
|
|
|
| 40 |
{ name = "torch", version = "2.9.1", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "sys_platform == 'darwin'" },
|
| 41 |
{ name = "torch", version = "2.9.1+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "sys_platform != 'darwin'" },
|
| 42 |
{ name = "torchvision", version = "0.24.1", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(platform_machine == 'aarch64' and platform_python_implementation == 'CPython' and sys_platform == 'linux') or sys_platform == 'darwin'" },
|
|
@@ -58,11 +59,12 @@ requires-dist = [
|
|
| 58 |
{ name = "gradio", specifier = ">=6.2.0" },
|
| 59 |
{ name = "langchain", specifier = ">=1.1.3" },
|
| 60 |
{ name = "langchain-groq", specifier = ">=1.1.1" },
|
| 61 |
-
{ name = "neo4j", specifier = ">=6.1.0" },
|
| 62 |
{ name = "pandas", specifier = ">=2.3.3" },
|
|
|
|
| 63 |
{ name = "python-dotenv", specifier = ">=1.2.1" },
|
| 64 |
{ name = "requests", specifier = ">=2.32.5" },
|
| 65 |
{ name = "sentence-transformers", specifier = ">=5.2.0" },
|
|
|
|
| 66 |
{ name = "torch", specifier = ">=2.9.1", index = "https://download.pytorch.org/whl/cpu" },
|
| 67 |
{ name = "torchvision", specifier = ">=0.24.1", index = "https://download.pytorch.org/whl/cpu" },
|
| 68 |
{ name = "uvicorn", specifier = ">=0.38.0" },
|
|
@@ -950,6 +952,38 @@ wheels = [
|
|
| 950 |
{ url = "https://files.pythonhosted.org/packages/a7/a2/a3497afea984202f481de3464b3bfbcb3de1cd83cbbf3714933d40dd7106/gradio_client-2.0.2-py3-none-any.whl", hash = "sha256:46a7f63eaa7758fe2e38be7f78f26a1fff48a7b526ebdd87141b050e08556622", size = 55566, upload-time = "2025-12-19T18:29:47.508Z" },
|
| 951 |
]
|
| 952 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 953 |
[[package]]
|
| 954 |
name = "groovy"
|
| 955 |
version = "0.1.2"
|
|
@@ -1942,18 +1976,6 @@ wheels = [
|
|
| 1942 |
{ url = "https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b", size = 78454, upload-time = "2024-04-04T11:20:34.895Z" },
|
| 1943 |
]
|
| 1944 |
|
| 1945 |
-
[[package]]
|
| 1946 |
-
name = "neo4j"
|
| 1947 |
-
version = "6.1.0"
|
| 1948 |
-
source = { registry = "https://pypi.org/simple" }
|
| 1949 |
-
dependencies = [
|
| 1950 |
-
{ name = "pytz" },
|
| 1951 |
-
]
|
| 1952 |
-
sdist = { url = "https://files.pythonhosted.org/packages/1b/01/d6ce65e4647f6cb2b9cca3b813978f7329b54b4e36660aaec1ddf0ccce7a/neo4j-6.1.0.tar.gz", hash = "sha256:b5dde8c0d8481e7b6ae3733569d990dd3e5befdc5d452f531ad1884ed3500b84", size = 239629, upload-time = "2026-01-12T11:27:34.777Z" }
|
| 1953 |
-
wheels = [
|
| 1954 |
-
{ url = "https://files.pythonhosted.org/packages/70/5c/ee71e2dd955045425ef44283f40ba1da67673cf06404916ca2950ac0cd39/neo4j-6.1.0-py3-none-any.whl", hash = "sha256:3bd93941f3a3559af197031157220af9fd71f4f93a311db687bd69ffa417b67d", size = 325326, upload-time = "2026-01-12T11:27:33.196Z" },
|
| 1955 |
-
]
|
| 1956 |
-
|
| 1957 |
[[package]]
|
| 1958 |
name = "nest-asyncio"
|
| 1959 |
version = "1.6.0"
|
|
@@ -2511,6 +2533,47 @@ wheels = [
|
|
| 2511 |
{ url = "https://files.pythonhosted.org/packages/c9/ad/33b2ccec09bf96c2b2ef3f9a6f66baac8253d7565d8839e024a6b905d45d/psutil-7.1.3-cp37-abi3-win_arm64.whl", hash = "sha256:bd0d69cee829226a761e92f28140bec9a5ee9d5b4fb4b0cc589068dbfff559b1", size = 244608, upload-time = "2025-11-02T12:26:36.136Z" },
|
| 2512 |
]
|
| 2513 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2514 |
[[package]]
|
| 2515 |
name = "ptyprocess"
|
| 2516 |
version = "0.7.0"
|
|
@@ -3535,6 +3598,59 @@ wheels = [
|
|
| 3535 |
{ url = "https://files.pythonhosted.org/packages/14/a0/bb38d3b76b8cae341dad93a2dd83ab7462e6dbcdd84d43f54ee60a8dc167/soupsieve-2.8-py3-none-any.whl", hash = "sha256:0cc76456a30e20f5d7f2e14a98a4ae2ee4e5abdc7c5ea0aafe795f344bc7984c", size = 36679, upload-time = "2025-08-27T15:39:50.179Z" },
|
| 3536 |
]
|
| 3537 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3538 |
[[package]]
|
| 3539 |
name = "stack-data"
|
| 3540 |
version = "0.6.3"
|
|
@@ -3671,10 +3787,10 @@ dependencies = [
|
|
| 3671 |
{ name = "typing-extensions", marker = "sys_platform == 'darwin'" },
|
| 3672 |
]
|
| 3673 |
wheels = [
|
| 3674 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1-cp311-none-macosx_11_0_arm64.whl" },
|
| 3675 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1-cp312-none-macosx_11_0_arm64.whl" },
|
| 3676 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1-cp313-cp313t-macosx_11_0_arm64.whl" },
|
| 3677 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1-cp313-none-macosx_11_0_arm64.whl" },
|
| 3678 |
]
|
| 3679 |
|
| 3680 |
[[package]]
|
|
@@ -3699,21 +3815,21 @@ dependencies = [
|
|
| 3699 |
{ name = "typing-extensions", marker = "sys_platform != 'darwin'" },
|
| 3700 |
]
|
| 3701 |
wheels = [
|
| 3702 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp311-cp311-manylinux_2_28_aarch64.whl" },
|
| 3703 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp311-cp311-manylinux_2_28_x86_64.whl" },
|
| 3704 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp311-cp311-win_amd64.whl" },
|
| 3705 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp311-cp311-win_arm64.whl" },
|
| 3706 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp312-cp312-manylinux_2_28_aarch64.whl" },
|
| 3707 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp312-cp312-manylinux_2_28_x86_64.whl" },
|
| 3708 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp312-cp312-win_amd64.whl" },
|
| 3709 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp312-cp312-win_arm64.whl" },
|
| 3710 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp313-cp313-manylinux_2_28_aarch64.whl" },
|
| 3711 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp313-cp313-manylinux_2_28_x86_64.whl" },
|
| 3712 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp313-cp313-win_amd64.whl" },
|
| 3713 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp313-cp313-win_arm64.whl" },
|
| 3714 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp313-cp313t-manylinux_2_28_aarch64.whl" },
|
| 3715 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp313-cp313t-manylinux_2_28_x86_64.whl" },
|
| 3716 |
-
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp313-cp313t-win_amd64.whl" },
|
| 3717 |
]
|
| 3718 |
|
| 3719 |
[[package]]
|
|
|
|
| 32 |
{ name = "gradio" },
|
| 33 |
{ name = "langchain" },
|
| 34 |
{ name = "langchain-groq" },
|
|
|
|
| 35 |
{ name = "pandas" },
|
| 36 |
+
{ name = "psycopg2-binary" },
|
| 37 |
{ name = "python-dotenv" },
|
| 38 |
{ name = "requests" },
|
| 39 |
{ name = "sentence-transformers" },
|
| 40 |
+
{ name = "sqlmodel" },
|
| 41 |
{ name = "torch", version = "2.9.1", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "sys_platform == 'darwin'" },
|
| 42 |
{ name = "torch", version = "2.9.1+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "sys_platform != 'darwin'" },
|
| 43 |
{ name = "torchvision", version = "0.24.1", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(platform_machine == 'aarch64' and platform_python_implementation == 'CPython' and sys_platform == 'linux') or sys_platform == 'darwin'" },
|
|
|
|
| 59 |
{ name = "gradio", specifier = ">=6.2.0" },
|
| 60 |
{ name = "langchain", specifier = ">=1.1.3" },
|
| 61 |
{ name = "langchain-groq", specifier = ">=1.1.1" },
|
|
|
|
| 62 |
{ name = "pandas", specifier = ">=2.3.3" },
|
| 63 |
+
{ name = "psycopg2-binary", specifier = ">=2.9.11" },
|
| 64 |
{ name = "python-dotenv", specifier = ">=1.2.1" },
|
| 65 |
{ name = "requests", specifier = ">=2.32.5" },
|
| 66 |
{ name = "sentence-transformers", specifier = ">=5.2.0" },
|
| 67 |
+
{ name = "sqlmodel", specifier = ">=0.0.37" },
|
| 68 |
{ name = "torch", specifier = ">=2.9.1", index = "https://download.pytorch.org/whl/cpu" },
|
| 69 |
{ name = "torchvision", specifier = ">=0.24.1", index = "https://download.pytorch.org/whl/cpu" },
|
| 70 |
{ name = "uvicorn", specifier = ">=0.38.0" },
|
|
|
|
| 952 |
{ url = "https://files.pythonhosted.org/packages/a7/a2/a3497afea984202f481de3464b3bfbcb3de1cd83cbbf3714933d40dd7106/gradio_client-2.0.2-py3-none-any.whl", hash = "sha256:46a7f63eaa7758fe2e38be7f78f26a1fff48a7b526ebdd87141b050e08556622", size = 55566, upload-time = "2025-12-19T18:29:47.508Z" },
|
| 953 |
]
|
| 954 |
|
| 955 |
+
[[package]]
|
| 956 |
+
name = "greenlet"
|
| 957 |
+
version = "3.3.2"
|
| 958 |
+
source = { registry = "https://pypi.org/simple" }
|
| 959 |
+
sdist = { url = "https://files.pythonhosted.org/packages/a3/51/1664f6b78fc6ebbd98019a1fd730e83fa78f2db7058f72b1463d3612b8db/greenlet-3.3.2.tar.gz", hash = "sha256:2eaf067fc6d886931c7962e8c6bede15d2f01965560f3359b27c80bde2d151f2", size = 188267, upload-time = "2026-02-20T20:54:15.531Z" }
|
| 960 |
+
wheels = [
|
| 961 |
+
{ url = "https://files.pythonhosted.org/packages/f3/47/16400cb42d18d7a6bb46f0626852c1718612e35dcb0dffa16bbaffdf5dd2/greenlet-3.3.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:c56692189a7d1c7606cb794be0a8381470d95c57ce5be03fb3d0ef57c7853b86", size = 278890, upload-time = "2026-02-20T20:19:39.263Z" },
|
| 962 |
+
{ url = "https://files.pythonhosted.org/packages/a3/90/42762b77a5b6aa96cd8c0e80612663d39211e8ae8a6cd47c7f1249a66262/greenlet-3.3.2-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ebd458fa8285960f382841da585e02201b53a5ec2bac6b156fc623b5ce4499f", size = 581120, upload-time = "2026-02-20T20:47:30.161Z" },
|
| 963 |
+
{ url = "https://files.pythonhosted.org/packages/bf/6f/f3d64f4fa0a9c7b5c5b3c810ff1df614540d5aa7d519261b53fba55d4df9/greenlet-3.3.2-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a443358b33c4ec7b05b79a7c8b466f5d275025e750298be7340f8fc63dff2a55", size = 594363, upload-time = "2026-02-20T20:55:56.965Z" },
|
| 964 |
+
{ url = "https://files.pythonhosted.org/packages/72/83/3e06a52aca8128bdd4dcd67e932b809e76a96ab8c232a8b025b2850264c5/greenlet-3.3.2-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e2cd90d413acbf5e77ae41e5d3c9b3ac1d011a756d7284d7f3f2b806bbd6358", size = 594156, upload-time = "2026-02-20T20:20:59.955Z" },
|
| 965 |
+
{ url = "https://files.pythonhosted.org/packages/70/79/0de5e62b873e08fe3cef7dbe84e5c4bc0e8ed0c7ff131bccb8405cd107c8/greenlet-3.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:442b6057453c8cb29b4fb36a2ac689382fc71112273726e2423f7f17dc73bf99", size = 1554649, upload-time = "2026-02-20T20:49:32.293Z" },
|
| 966 |
+
{ url = "https://files.pythonhosted.org/packages/5a/00/32d30dee8389dc36d42170a9c66217757289e2afb0de59a3565260f38373/greenlet-3.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:45abe8eb6339518180d5a7fa47fa01945414d7cca5ecb745346fc6a87d2750be", size = 1619472, upload-time = "2026-02-20T20:21:07.966Z" },
|
| 967 |
+
{ url = "https://files.pythonhosted.org/packages/f1/3a/efb2cf697fbccdf75b24e2c18025e7dfa54c4f31fab75c51d0fe79942cef/greenlet-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e692b2dae4cc7077cbb11b47d258533b48c8fde69a33d0d8a82e2fe8d8531d5", size = 230389, upload-time = "2026-02-20T20:17:18.772Z" },
|
| 968 |
+
{ url = "https://files.pythonhosted.org/packages/e1/a1/65bbc059a43a7e2143ec4fc1f9e3f673e04f9c7b371a494a101422ac4fd5/greenlet-3.3.2-cp311-cp311-win_arm64.whl", hash = "sha256:02b0a8682aecd4d3c6c18edf52bc8e51eacdd75c8eac52a790a210b06aa295fd", size = 229645, upload-time = "2026-02-20T20:18:18.695Z" },
|
| 969 |
+
{ url = "https://files.pythonhosted.org/packages/ea/ab/1608e5a7578e62113506740b88066bf09888322a311cff602105e619bd87/greenlet-3.3.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:ac8d61d4343b799d1e526db579833d72f23759c71e07181c2d2944e429eb09cd", size = 280358, upload-time = "2026-02-20T20:17:43.971Z" },
|
| 970 |
+
{ url = "https://files.pythonhosted.org/packages/a5/23/0eae412a4ade4e6623ff7626e38998cb9b11e9ff1ebacaa021e4e108ec15/greenlet-3.3.2-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ceec72030dae6ac0c8ed7591b96b70410a8be370b6a477b1dbc072856ad02bd", size = 601217, upload-time = "2026-02-20T20:47:31.462Z" },
|
| 971 |
+
{ url = "https://files.pythonhosted.org/packages/f8/16/5b1678a9c07098ecb9ab2dd159fafaf12e963293e61ee8d10ecb55273e5e/greenlet-3.3.2-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a2a5be83a45ce6188c045bcc44b0ee037d6a518978de9a5d97438548b953a1ac", size = 611792, upload-time = "2026-02-20T20:55:58.423Z" },
|
| 972 |
+
{ url = "https://files.pythonhosted.org/packages/50/1f/5155f55bd71cabd03765a4aac9ac446be129895271f73872c36ebd4b04b6/greenlet-3.3.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43e99d1749147ac21dde49b99c9abffcbc1e2d55c67501465ef0930d6e78e070", size = 613875, upload-time = "2026-02-20T20:21:01.102Z" },
|
| 973 |
+
{ url = "https://files.pythonhosted.org/packages/fc/dd/845f249c3fcd69e32df80cdab059b4be8b766ef5830a3d0aa9d6cad55beb/greenlet-3.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4c956a19350e2c37f2c48b336a3afb4bff120b36076d9d7fb68cb44e05d95b79", size = 1571467, upload-time = "2026-02-20T20:49:33.495Z" },
|
| 974 |
+
{ url = "https://files.pythonhosted.org/packages/2a/50/2649fe21fcc2b56659a452868e695634722a6655ba245d9f77f5656010bf/greenlet-3.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c6f8ba97d17a1e7d664151284cb3315fc5f8353e75221ed4324f84eb162b395", size = 1640001, upload-time = "2026-02-20T20:21:09.154Z" },
|
| 975 |
+
{ url = "https://files.pythonhosted.org/packages/9b/40/cc802e067d02af8b60b6771cea7d57e21ef5e6659912814babb42b864713/greenlet-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:34308836d8370bddadb41f5a7ce96879b72e2fdfb4e87729330c6ab52376409f", size = 231081, upload-time = "2026-02-20T20:17:28.121Z" },
|
| 976 |
+
{ url = "https://files.pythonhosted.org/packages/58/2e/fe7f36ff1982d6b10a60d5e0740c759259a7d6d2e1dc41da6d96de32fff6/greenlet-3.3.2-cp312-cp312-win_arm64.whl", hash = "sha256:d3a62fa76a32b462a97198e4c9e99afb9ab375115e74e9a83ce180e7a496f643", size = 230331, upload-time = "2026-02-20T20:17:23.34Z" },
|
| 977 |
+
{ url = "https://files.pythonhosted.org/packages/ac/48/f8b875fa7dea7dd9b33245e37f065af59df6a25af2f9561efa8d822fde51/greenlet-3.3.2-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:aa6ac98bdfd716a749b84d4034486863fd81c3abde9aa3cf8eff9127981a4ae4", size = 279120, upload-time = "2026-02-20T20:19:01.9Z" },
|
| 978 |
+
{ url = "https://files.pythonhosted.org/packages/49/8d/9771d03e7a8b1ee456511961e1b97a6d77ae1dea4a34a5b98eee706689d3/greenlet-3.3.2-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab0c7e7901a00bc0a7284907273dc165b32e0d109a6713babd04471327ff7986", size = 603238, upload-time = "2026-02-20T20:47:32.873Z" },
|
| 979 |
+
{ url = "https://files.pythonhosted.org/packages/59/0e/4223c2bbb63cd5c97f28ffb2a8aee71bdfb30b323c35d409450f51b91e3e/greenlet-3.3.2-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d248d8c23c67d2291ffd47af766e2a3aa9fa1c6703155c099feb11f526c63a92", size = 614219, upload-time = "2026-02-20T20:55:59.817Z" },
|
| 980 |
+
{ url = "https://files.pythonhosted.org/packages/7a/34/259b28ea7a2a0c904b11cd36c79b8cef8019b26ee5dbe24e73b469dea347/greenlet-3.3.2-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6997d360a4e6a4e936c0f9625b1c20416b8a0ea18a8e19cabbefc712e7397ab", size = 616774, upload-time = "2026-02-20T20:21:02.454Z" },
|
| 981 |
+
{ url = "https://files.pythonhosted.org/packages/0a/03/996c2d1689d486a6e199cb0f1cf9e4aa940c500e01bdf201299d7d61fa69/greenlet-3.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64970c33a50551c7c50491671265d8954046cb6e8e2999aacdd60e439b70418a", size = 1571277, upload-time = "2026-02-20T20:49:34.795Z" },
|
| 982 |
+
{ url = "https://files.pythonhosted.org/packages/d9/c4/2570fc07f34a39f2caf0bf9f24b0a1a0a47bc2e8e465b2c2424821389dfc/greenlet-3.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1a9172f5bf6bd88e6ba5a84e0a68afeac9dc7b6b412b245dd64f52d83c81e55b", size = 1640455, upload-time = "2026-02-20T20:21:10.261Z" },
|
| 983 |
+
{ url = "https://files.pythonhosted.org/packages/91/39/5ef5aa23bc545aa0d31e1b9b55822b32c8da93ba657295840b6b34124009/greenlet-3.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:a7945dd0eab63ded0a48e4dcade82939783c172290a7903ebde9e184333ca124", size = 230961, upload-time = "2026-02-20T20:16:58.461Z" },
|
| 984 |
+
{ url = "https://files.pythonhosted.org/packages/62/6b/a89f8456dcb06becff288f563618e9f20deed8dd29beea14f9a168aef64b/greenlet-3.3.2-cp313-cp313-win_arm64.whl", hash = "sha256:394ead29063ee3515b4e775216cb756b2e3b4a7e55ae8fd884f17fa579e6b327", size = 230221, upload-time = "2026-02-20T20:17:37.152Z" },
|
| 985 |
+
]
|
| 986 |
+
|
| 987 |
[[package]]
|
| 988 |
name = "groovy"
|
| 989 |
version = "0.1.2"
|
|
|
|
| 1976 |
{ url = "https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b", size = 78454, upload-time = "2024-04-04T11:20:34.895Z" },
|
| 1977 |
]
|
| 1978 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1979 |
[[package]]
|
| 1980 |
name = "nest-asyncio"
|
| 1981 |
version = "1.6.0"
|
|
|
|
| 2533 |
{ url = "https://files.pythonhosted.org/packages/c9/ad/33b2ccec09bf96c2b2ef3f9a6f66baac8253d7565d8839e024a6b905d45d/psutil-7.1.3-cp37-abi3-win_arm64.whl", hash = "sha256:bd0d69cee829226a761e92f28140bec9a5ee9d5b4fb4b0cc589068dbfff559b1", size = 244608, upload-time = "2025-11-02T12:26:36.136Z" },
|
| 2534 |
]
|
| 2535 |
|
| 2536 |
+
[[package]]
|
| 2537 |
+
name = "psycopg2-binary"
|
| 2538 |
+
version = "2.9.11"
|
| 2539 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2540 |
+
sdist = { url = "https://files.pythonhosted.org/packages/ac/6c/8767aaa597ba424643dc87348c6f1754dd9f48e80fdc1b9f7ca5c3a7c213/psycopg2-binary-2.9.11.tar.gz", hash = "sha256:b6aed9e096bf63f9e75edf2581aa9a7e7186d97ab5c177aa6c87797cd591236c", size = 379620, upload-time = "2025-10-10T11:14:48.041Z" }
|
| 2541 |
+
wheels = [
|
| 2542 |
+
{ url = "https://files.pythonhosted.org/packages/c7/ae/8d8266f6dd183ab4d48b95b9674034e1b482a3f8619b33a0d86438694577/psycopg2_binary-2.9.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0e8480afd62362d0a6a27dd09e4ca2def6fa50ed3a4e7c09165266106b2ffa10", size = 3756452, upload-time = "2025-10-10T11:11:11.583Z" },
|
| 2543 |
+
{ url = "https://files.pythonhosted.org/packages/4b/34/aa03d327739c1be70e09d01182619aca8ebab5970cd0cfa50dd8b9cec2ac/psycopg2_binary-2.9.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:763c93ef1df3da6d1a90f86ea7f3f806dc06b21c198fa87c3c25504abec9404a", size = 3863957, upload-time = "2025-10-10T11:11:16.932Z" },
|
| 2544 |
+
{ url = "https://files.pythonhosted.org/packages/48/89/3fdb5902bdab8868bbedc1c6e6023a4e08112ceac5db97fc2012060e0c9a/psycopg2_binary-2.9.11-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2e164359396576a3cc701ba8af4751ae68a07235d7a380c631184a611220d9a4", size = 4410955, upload-time = "2025-10-10T11:11:21.21Z" },
|
| 2545 |
+
{ url = "https://files.pythonhosted.org/packages/ce/24/e18339c407a13c72b336e0d9013fbbbde77b6fd13e853979019a1269519c/psycopg2_binary-2.9.11-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:d57c9c387660b8893093459738b6abddbb30a7eab058b77b0d0d1c7d521ddfd7", size = 4468007, upload-time = "2025-10-10T11:11:24.831Z" },
|
| 2546 |
+
{ url = "https://files.pythonhosted.org/packages/91/7e/b8441e831a0f16c159b5381698f9f7f7ed54b77d57bc9c5f99144cc78232/psycopg2_binary-2.9.11-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2c226ef95eb2250974bf6fa7a842082b31f68385c4f3268370e3f3870e7859ee", size = 4165012, upload-time = "2025-10-10T11:11:29.51Z" },
|
| 2547 |
+
{ url = "https://files.pythonhosted.org/packages/0d/61/4aa89eeb6d751f05178a13da95516c036e27468c5d4d2509bb1e15341c81/psycopg2_binary-2.9.11-cp311-cp311-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a311f1edc9967723d3511ea7d2708e2c3592e3405677bf53d5c7246753591fbb", size = 3981881, upload-time = "2025-10-30T02:55:07.332Z" },
|
| 2548 |
+
{ url = "https://files.pythonhosted.org/packages/76/a1/2f5841cae4c635a9459fe7aca8ed771336e9383b6429e05c01267b0774cf/psycopg2_binary-2.9.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ebb415404821b6d1c47353ebe9c8645967a5235e6d88f914147e7fd411419e6f", size = 3650985, upload-time = "2025-10-10T11:11:34.975Z" },
|
| 2549 |
+
{ url = "https://files.pythonhosted.org/packages/84/74/4defcac9d002bca5709951b975173c8c2fa968e1a95dc713f61b3a8d3b6a/psycopg2_binary-2.9.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f07c9c4a5093258a03b28fab9b4f151aa376989e7f35f855088234e656ee6a94", size = 3296039, upload-time = "2025-10-10T11:11:40.432Z" },
|
| 2550 |
+
{ url = "https://files.pythonhosted.org/packages/6d/c2/782a3c64403d8ce35b5c50e1b684412cf94f171dc18111be8c976abd2de1/psycopg2_binary-2.9.11-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:00ce1830d971f43b667abe4a56e42c1e2d594b32da4802e44a73bacacb25535f", size = 3043477, upload-time = "2025-10-30T02:55:11.182Z" },
|
| 2551 |
+
{ url = "https://files.pythonhosted.org/packages/c8/31/36a1d8e702aa35c38fc117c2b8be3f182613faa25d794b8aeaab948d4c03/psycopg2_binary-2.9.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:cffe9d7697ae7456649617e8bb8d7a45afb71cd13f7ab22af3e5c61f04840908", size = 3345842, upload-time = "2025-10-10T11:11:45.366Z" },
|
| 2552 |
+
{ url = "https://files.pythonhosted.org/packages/6e/b4/a5375cda5b54cb95ee9b836930fea30ae5a8f14aa97da7821722323d979b/psycopg2_binary-2.9.11-cp311-cp311-win_amd64.whl", hash = "sha256:304fd7b7f97eef30e91b8f7e720b3db75fee010b520e434ea35ed1ff22501d03", size = 2713894, upload-time = "2025-10-10T11:11:48.775Z" },
|
| 2553 |
+
{ url = "https://files.pythonhosted.org/packages/d8/91/f870a02f51be4a65987b45a7de4c2e1897dd0d01051e2b559a38fa634e3e/psycopg2_binary-2.9.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:be9b840ac0525a283a96b556616f5b4820e0526addb8dcf6525a0fa162730be4", size = 3756603, upload-time = "2025-10-10T11:11:52.213Z" },
|
| 2554 |
+
{ url = "https://files.pythonhosted.org/packages/27/fa/cae40e06849b6c9a95eb5c04d419942f00d9eaac8d81626107461e268821/psycopg2_binary-2.9.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f090b7ddd13ca842ebfe301cd587a76a4cf0913b1e429eb92c1be5dbeb1a19bc", size = 3864509, upload-time = "2025-10-10T11:11:56.452Z" },
|
| 2555 |
+
{ url = "https://files.pythonhosted.org/packages/2d/75/364847b879eb630b3ac8293798e380e441a957c53657995053c5ec39a316/psycopg2_binary-2.9.11-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ab8905b5dcb05bf3fb22e0cf90e10f469563486ffb6a96569e51f897c750a76a", size = 4411159, upload-time = "2025-10-10T11:12:00.49Z" },
|
| 2556 |
+
{ url = "https://files.pythonhosted.org/packages/6f/a0/567f7ea38b6e1c62aafd58375665a547c00c608a471620c0edc364733e13/psycopg2_binary-2.9.11-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:bf940cd7e7fec19181fdbc29d76911741153d51cab52e5c21165f3262125685e", size = 4468234, upload-time = "2025-10-10T11:12:04.892Z" },
|
| 2557 |
+
{ url = "https://files.pythonhosted.org/packages/30/da/4e42788fb811bbbfd7b7f045570c062f49e350e1d1f3df056c3fb5763353/psycopg2_binary-2.9.11-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fa0f693d3c68ae925966f0b14b8edda71696608039f4ed61b1fe9ffa468d16db", size = 4166236, upload-time = "2025-10-10T11:12:11.674Z" },
|
| 2558 |
+
{ url = "https://files.pythonhosted.org/packages/3c/94/c1777c355bc560992af848d98216148be5f1be001af06e06fc49cbded578/psycopg2_binary-2.9.11-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a1cf393f1cdaf6a9b57c0a719a1068ba1069f022a59b8b1fe44b006745b59757", size = 3983083, upload-time = "2025-10-30T02:55:15.73Z" },
|
| 2559 |
+
{ url = "https://files.pythonhosted.org/packages/bd/42/c9a21edf0e3daa7825ed04a4a8588686c6c14904344344a039556d78aa58/psycopg2_binary-2.9.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ef7a6beb4beaa62f88592ccc65df20328029d721db309cb3250b0aae0fa146c3", size = 3652281, upload-time = "2025-10-10T11:12:17.713Z" },
|
| 2560 |
+
{ url = "https://files.pythonhosted.org/packages/12/22/dedfbcfa97917982301496b6b5e5e6c5531d1f35dd2b488b08d1ebc52482/psycopg2_binary-2.9.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:31b32c457a6025e74d233957cc9736742ac5a6cb196c6b68499f6bb51390bd6a", size = 3298010, upload-time = "2025-10-10T11:12:22.671Z" },
|
| 2561 |
+
{ url = "https://files.pythonhosted.org/packages/66/ea/d3390e6696276078bd01b2ece417deac954dfdd552d2edc3d03204416c0c/psycopg2_binary-2.9.11-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:edcb3aeb11cb4bf13a2af3c53a15b3d612edeb6409047ea0b5d6a21a9d744b34", size = 3044641, upload-time = "2025-10-30T02:55:19.929Z" },
|
| 2562 |
+
{ url = "https://files.pythonhosted.org/packages/12/9a/0402ded6cbd321da0c0ba7d34dc12b29b14f5764c2fc10750daa38e825fc/psycopg2_binary-2.9.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:62b6d93d7c0b61a1dd6197d208ab613eb7dcfdcca0a49c42ceb082257991de9d", size = 3347940, upload-time = "2025-10-10T11:12:26.529Z" },
|
| 2563 |
+
{ url = "https://files.pythonhosted.org/packages/b1/d2/99b55e85832ccde77b211738ff3925a5d73ad183c0b37bcbbe5a8ff04978/psycopg2_binary-2.9.11-cp312-cp312-win_amd64.whl", hash = "sha256:b33fabeb1fde21180479b2d4667e994de7bbf0eec22832ba5d9b5e4cf65b6c6d", size = 2714147, upload-time = "2025-10-10T11:12:29.535Z" },
|
| 2564 |
+
{ url = "https://files.pythonhosted.org/packages/ff/a8/a2709681b3ac11b0b1786def10006b8995125ba268c9a54bea6f5ae8bd3e/psycopg2_binary-2.9.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b8fb3db325435d34235b044b199e56cdf9ff41223a4b9752e8576465170bb38c", size = 3756572, upload-time = "2025-10-10T11:12:32.873Z" },
|
| 2565 |
+
{ url = "https://files.pythonhosted.org/packages/62/e1/c2b38d256d0dafd32713e9f31982a5b028f4a3651f446be70785f484f472/psycopg2_binary-2.9.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:366df99e710a2acd90efed3764bb1e28df6c675d33a7fb40df9b7281694432ee", size = 3864529, upload-time = "2025-10-10T11:12:36.791Z" },
|
| 2566 |
+
{ url = "https://files.pythonhosted.org/packages/11/32/b2ffe8f3853c181e88f0a157c5fb4e383102238d73c52ac6d93a5c8bffe6/psycopg2_binary-2.9.11-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8c55b385daa2f92cb64b12ec4536c66954ac53654c7f15a203578da4e78105c0", size = 4411242, upload-time = "2025-10-10T11:12:42.388Z" },
|
| 2567 |
+
{ url = "https://files.pythonhosted.org/packages/10/04/6ca7477e6160ae258dc96f67c371157776564679aefd247b66f4661501a2/psycopg2_binary-2.9.11-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:c0377174bf1dd416993d16edc15357f6eb17ac998244cca19bc67cdc0e2e5766", size = 4468258, upload-time = "2025-10-10T11:12:48.654Z" },
|
| 2568 |
+
{ url = "https://files.pythonhosted.org/packages/3c/7e/6a1a38f86412df101435809f225d57c1a021307dd0689f7a5e7fe83588b1/psycopg2_binary-2.9.11-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5c6ff3335ce08c75afaed19e08699e8aacf95d4a260b495a4a8545244fe2ceb3", size = 4166295, upload-time = "2025-10-10T11:12:52.525Z" },
|
| 2569 |
+
{ url = "https://files.pythonhosted.org/packages/f2/7d/c07374c501b45f3579a9eb761cbf2604ddef3d96ad48679112c2c5aa9c25/psycopg2_binary-2.9.11-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:84011ba3109e06ac412f95399b704d3d6950e386b7994475b231cf61eec2fc1f", size = 3983133, upload-time = "2025-10-30T02:55:24.329Z" },
|
| 2570 |
+
{ url = "https://files.pythonhosted.org/packages/82/56/993b7104cb8345ad7d4516538ccf8f0d0ac640b1ebd8c754a7b024e76878/psycopg2_binary-2.9.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ba34475ceb08cccbdd98f6b46916917ae6eeb92b5ae111df10b544c3a4621dc4", size = 3652383, upload-time = "2025-10-10T11:12:56.387Z" },
|
| 2571 |
+
{ url = "https://files.pythonhosted.org/packages/2d/ac/eaeb6029362fd8d454a27374d84c6866c82c33bfc24587b4face5a8e43ef/psycopg2_binary-2.9.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b31e90fdd0f968c2de3b26ab014314fe814225b6c324f770952f7d38abf17e3c", size = 3298168, upload-time = "2025-10-10T11:13:00.403Z" },
|
| 2572 |
+
{ url = "https://files.pythonhosted.org/packages/2b/39/50c3facc66bded9ada5cbc0de867499a703dc6bca6be03070b4e3b65da6c/psycopg2_binary-2.9.11-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:d526864e0f67f74937a8fce859bd56c979f5e2ec57ca7c627f5f1071ef7fee60", size = 3044712, upload-time = "2025-10-30T02:55:27.975Z" },
|
| 2573 |
+
{ url = "https://files.pythonhosted.org/packages/9c/8e/b7de019a1f562f72ada81081a12823d3c1590bedc48d7d2559410a2763fe/psycopg2_binary-2.9.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:04195548662fa544626c8ea0f06561eb6203f1984ba5b4562764fbeb4c3d14b1", size = 3347549, upload-time = "2025-10-10T11:13:03.971Z" },
|
| 2574 |
+
{ url = "https://files.pythonhosted.org/packages/80/2d/1bb683f64737bbb1f86c82b7359db1eb2be4e2c0c13b947f80efefa7d3e5/psycopg2_binary-2.9.11-cp313-cp313-win_amd64.whl", hash = "sha256:efff12b432179443f54e230fdf60de1f6cc726b6c832db8701227d089310e8aa", size = 2714215, upload-time = "2025-10-10T11:13:07.14Z" },
|
| 2575 |
+
]
|
| 2576 |
+
|
| 2577 |
[[package]]
|
| 2578 |
name = "ptyprocess"
|
| 2579 |
version = "0.7.0"
|
|
|
|
| 3598 |
{ url = "https://files.pythonhosted.org/packages/14/a0/bb38d3b76b8cae341dad93a2dd83ab7462e6dbcdd84d43f54ee60a8dc167/soupsieve-2.8-py3-none-any.whl", hash = "sha256:0cc76456a30e20f5d7f2e14a98a4ae2ee4e5abdc7c5ea0aafe795f344bc7984c", size = 36679, upload-time = "2025-08-27T15:39:50.179Z" },
|
| 3599 |
]
|
| 3600 |
|
| 3601 |
+
[[package]]
|
| 3602 |
+
name = "sqlalchemy"
|
| 3603 |
+
version = "2.0.47"
|
| 3604 |
+
source = { registry = "https://pypi.org/simple" }
|
| 3605 |
+
dependencies = [
|
| 3606 |
+
{ name = "greenlet", marker = "platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'" },
|
| 3607 |
+
{ name = "typing-extensions" },
|
| 3608 |
+
]
|
| 3609 |
+
sdist = { url = "https://files.pythonhosted.org/packages/cd/4b/1e00561093fe2cd8eef09d406da003c8a118ff02d6548498c1ae677d68d9/sqlalchemy-2.0.47.tar.gz", hash = "sha256:e3e7feb57b267fe897e492b9721ae46d5c7de6f9e8dee58aacf105dc4e154f3d", size = 9886323, upload-time = "2026-02-24T16:34:27.947Z" }
|
| 3610 |
+
wheels = [
|
| 3611 |
+
{ url = "https://files.pythonhosted.org/packages/94/13/886338d3e8ab5ddcfe84d54302c749b1793e16c4bba63d7004e3f7baa8ec/sqlalchemy-2.0.47-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a1dbf0913879c443617d6b64403cf2801c941651db8c60e96d204ed9388d6b0", size = 2157124, upload-time = "2026-02-24T16:43:54.706Z" },
|
| 3612 |
+
{ url = "https://files.pythonhosted.org/packages/b6/bb/a897f6a66c9986aa9f27f5cf8550637d8a5ea368fd7fb42f6dac3105b4dc/sqlalchemy-2.0.47-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:775effbb97ea3b00c4dd3aeaf3ba8acba6e3e2b4b41d17d67a27e696843dbc95", size = 3313513, upload-time = "2026-02-24T17:29:00.527Z" },
|
| 3613 |
+
{ url = "https://files.pythonhosted.org/packages/59/fb/69bfae022b681507565ab0d34f0c80aa1e9f954a5a7cbfb0ed054966ac8d/sqlalchemy-2.0.47-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:56cc834a3ffac34270cc2a41875e0f40e97aa651f4f3ca1cfbbf421c044cb62b", size = 3313014, upload-time = "2026-02-24T17:27:11.679Z" },
|
| 3614 |
+
{ url = "https://files.pythonhosted.org/packages/04/f3/0eba329f7c182d53205a228c4fd24651b95489b431ea2bd830887b4c13c4/sqlalchemy-2.0.47-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:49b5e0c7244262f39e767c018e4fdb5e5dbc23cd54c5ddac8eea8f0ba32ef890", size = 3265389, upload-time = "2026-02-24T17:29:02.497Z" },
|
| 3615 |
+
{ url = "https://files.pythonhosted.org/packages/5c/06/654edc084b3b46ac79e04200d7c46467ae80c759c4ee41c897f9272b036f/sqlalchemy-2.0.47-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:15cd822a3f1f6f77b5b841a30c1a07a07f7dee3385f17e638e1722de9ab683be", size = 3287604, upload-time = "2026-02-24T17:27:13.295Z" },
|
| 3616 |
+
{ url = "https://files.pythonhosted.org/packages/78/33/c18c8f63b61981219d3aa12321bb7ccee605034d195e868ed94f9727b27c/sqlalchemy-2.0.47-cp311-cp311-win32.whl", hash = "sha256:9847a19548cd283a65e1ce0afd54016598d55ff72682d6fd3e493af6fc044064", size = 2116916, upload-time = "2026-02-24T17:14:37.392Z" },
|
| 3617 |
+
{ url = "https://files.pythonhosted.org/packages/f5/c6/a59e3f9796fff844e16afbd821db9abfd6e12698db9441a231a96193a100/sqlalchemy-2.0.47-cp311-cp311-win_amd64.whl", hash = "sha256:722abf1c82aeca46a1a0803711244a48a298279eeaec9e02f7bfee9e064182e5", size = 2141587, upload-time = "2026-02-24T17:14:39.746Z" },
|
| 3618 |
+
{ url = "https://files.pythonhosted.org/packages/80/88/74eb470223ff88ea6572a132c0b8de8c1d8ed7b843d3b44a8a3c77f31d39/sqlalchemy-2.0.47-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4fa91b19d6b9821c04cc8f7aa2476429cc8887b9687c762815aa629f5c0edec1", size = 2155687, upload-time = "2026-02-24T17:05:46.451Z" },
|
| 3619 |
+
{ url = "https://files.pythonhosted.org/packages/ef/ba/1447d3d558971b036cb93b557595cb5dcdfe728f1c7ac4dec16505ef5756/sqlalchemy-2.0.47-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7c5bbbd14eff577c8c79cbfe39a0771eecd20f430f3678533476f0087138f356", size = 3336978, upload-time = "2026-02-24T17:18:04.597Z" },
|
| 3620 |
+
{ url = "https://files.pythonhosted.org/packages/8a/07/b47472d2ffd0776826f17ccf0b4d01b224c99fbd1904aeb103dffbb4b1cc/sqlalchemy-2.0.47-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a5a6c555da8d4280a3c4c78c5b7a3f990cee2b2884e5f934f87a226191682ff7", size = 3349939, upload-time = "2026-02-24T17:27:18.937Z" },
|
| 3621 |
+
{ url = "https://files.pythonhosted.org/packages/bb/c6/95fa32b79b57769da3e16f054cf658d90940317b5ca0ec20eac84aa19c4f/sqlalchemy-2.0.47-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ed48a1701d24dff3bb49a5bce94d6bc84cbe33d98af2aa2d3cdcce3dea1709ec", size = 3279648, upload-time = "2026-02-24T17:18:07.038Z" },
|
| 3622 |
+
{ url = "https://files.pythonhosted.org/packages/bb/c8/3d07e7c73928dc59a0bed40961ca4e313e797bce650b088e8d5fdd3ad939/sqlalchemy-2.0.47-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4f3178c920ad98158f0b6309382194df04b14808fa6052ae07099fdde29d5602", size = 3314695, upload-time = "2026-02-24T17:27:20.93Z" },
|
| 3623 |
+
{ url = "https://files.pythonhosted.org/packages/6b/d2/ed32b1611c1e19fdb028eee1adc5a9aa138c2952d09ae11f1670170f80ae/sqlalchemy-2.0.47-cp312-cp312-win32.whl", hash = "sha256:b9c11ac9934dd59ece9619fe42780a08abe2faab7b0543bb00d5eabea4f421b9", size = 2115502, upload-time = "2026-02-24T17:22:52.546Z" },
|
| 3624 |
+
{ url = "https://files.pythonhosted.org/packages/fd/52/9de590356a4dd8e9ef5a881dbba64b2bbc4cbc71bf02bc68e775fb9b1899/sqlalchemy-2.0.47-cp312-cp312-win_amd64.whl", hash = "sha256:db43b72cf8274a99e089755c9c1e0b947159b71adbc2c83c3de2e38d5d607acb", size = 2142435, upload-time = "2026-02-24T17:22:54.268Z" },
|
| 3625 |
+
{ url = "https://files.pythonhosted.org/packages/4a/e5/0af64ce7d8f60ec5328c10084e2f449e7912a9b8bdbefdcfb44454a25f49/sqlalchemy-2.0.47-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:456a135b790da5d3c6b53d0ef71ac7b7d280b7f41eb0c438986352bf03ca7143", size = 2152551, upload-time = "2026-02-24T17:05:47.675Z" },
|
| 3626 |
+
{ url = "https://files.pythonhosted.org/packages/63/79/746b8d15f6940e2ac469ce22d7aa5b1124b1ab820bad9b046eb3000c88a6/sqlalchemy-2.0.47-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09a2f7698e44b3135433387da5d8846cf7cc7c10e5425af7c05fee609df978b6", size = 3278782, upload-time = "2026-02-24T17:18:10.012Z" },
|
| 3627 |
+
{ url = "https://files.pythonhosted.org/packages/91/b1/bd793ddb34345d1ed43b13ab2d88c95d7d4eb2e28f5b5a99128b9cc2bca2/sqlalchemy-2.0.47-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a0bbc72e6a177c78d724f9106aaddc0d26a2ada89c6332b5935414eccf04cbd5", size = 3295155, upload-time = "2026-02-24T17:27:22.827Z" },
|
| 3628 |
+
{ url = "https://files.pythonhosted.org/packages/97/84/7213def33f94e5ca6f5718d259bc9f29de0363134648425aa218d4356b23/sqlalchemy-2.0.47-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:75460456b043b78b6006e41bdf5b86747ee42eafaf7fffa3b24a6e9a456a2092", size = 3226834, upload-time = "2026-02-24T17:18:11.465Z" },
|
| 3629 |
+
{ url = "https://files.pythonhosted.org/packages/ef/06/456810204f4dc29b5f025b1b0a03b4bd6b600ebf3c1040aebd90a257fa33/sqlalchemy-2.0.47-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5d9adaa616c3bc7d80f9ded57cd84b51d6617cad6a5456621d858c9f23aaee01", size = 3265001, upload-time = "2026-02-24T17:27:24.813Z" },
|
| 3630 |
+
{ url = "https://files.pythonhosted.org/packages/fb/20/df3920a4b2217dbd7390a5bd277c1902e0393f42baaf49f49b3c935e7328/sqlalchemy-2.0.47-cp313-cp313-win32.whl", hash = "sha256:76e09f974382a496a5ed985db9343628b1cb1ac911f27342e4cc46a8bac10476", size = 2113647, upload-time = "2026-02-24T17:22:55.747Z" },
|
| 3631 |
+
{ url = "https://files.pythonhosted.org/packages/46/06/7873ddf69918efbfabd7211829f4bd8019739d0a719253112d305d3ba51d/sqlalchemy-2.0.47-cp313-cp313-win_amd64.whl", hash = "sha256:0664089b0bf6724a0bfb49a0cf4d4da24868a0a5c8e937cd7db356d5dcdf2c66", size = 2139425, upload-time = "2026-02-24T17:22:57.033Z" },
|
| 3632 |
+
{ url = "https://files.pythonhosted.org/packages/54/fa/61ad9731370c90ac7ea5bf8f5eaa12c48bb4beec41c0fa0360becf4ac10d/sqlalchemy-2.0.47-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ed0c967c701ae13da98eb220f9ddab3044ab63504c1ba24ad6a59b26826ad003", size = 3558809, upload-time = "2026-02-24T17:12:15.232Z" },
|
| 3633 |
+
{ url = "https://files.pythonhosted.org/packages/33/d5/221fac96f0529391fe374875633804c866f2b21a9c6d3a6ca57d9c12cfd7/sqlalchemy-2.0.47-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3537943a61fd25b241e976426a0c6814434b93cf9b09d39e8e78f3c9eb9a487", size = 3525480, upload-time = "2026-02-24T17:27:59.602Z" },
|
| 3634 |
+
{ url = "https://files.pythonhosted.org/packages/ec/55/8247d53998c3673e4a8d1958eba75c6f5cc3b39082029d400bb1f2a911ae/sqlalchemy-2.0.47-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:57f7e336a64a0dba686c66392d46b9bc7af2c57d55ce6dc1697b4ef32b043ceb", size = 3466569, upload-time = "2026-02-24T17:12:16.94Z" },
|
| 3635 |
+
{ url = "https://files.pythonhosted.org/packages/6b/b5/c1f0eea1bac6790845f71420a7fe2f2a0566203aa57543117d4af3b77d1c/sqlalchemy-2.0.47-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dff735a621858680217cb5142b779bad40ef7322ddbb7c12062190db6879772e", size = 3475770, upload-time = "2026-02-24T17:28:02.034Z" },
|
| 3636 |
+
{ url = "https://files.pythonhosted.org/packages/c5/ed/2f43f92474ea0c43c204657dc47d9d002cd738b96ca2af8e6d29a9b5e42d/sqlalchemy-2.0.47-cp313-cp313t-win32.whl", hash = "sha256:3893dc096bb3cca9608ea3487372ffcea3ae9b162f40e4d3c51dd49db1d1b2dc", size = 2141300, upload-time = "2026-02-24T17:14:37.024Z" },
|
| 3637 |
+
{ url = "https://files.pythonhosted.org/packages/cc/a9/8b73f9f1695b6e92f7aaf1711135a1e3bbeb78bca9eded35cb79180d3c6d/sqlalchemy-2.0.47-cp313-cp313t-win_amd64.whl", hash = "sha256:b5103427466f4b3e61f04833ae01f9a914b1280a2a8bcde3a9d7ab11f3755b42", size = 2173053, upload-time = "2026-02-24T17:14:38.688Z" },
|
| 3638 |
+
{ url = "https://files.pythonhosted.org/packages/15/9f/7c378406b592fcf1fc157248607b495a40e3202ba4a6f1372a2ba6447717/sqlalchemy-2.0.47-py3-none-any.whl", hash = "sha256:e2647043599297a1ef10e720cf310846b7f31b6c841fee093d2b09d81215eb93", size = 1940159, upload-time = "2026-02-24T17:15:07.158Z" },
|
| 3639 |
+
]
|
| 3640 |
+
|
| 3641 |
+
[[package]]
|
| 3642 |
+
name = "sqlmodel"
|
| 3643 |
+
version = "0.0.37"
|
| 3644 |
+
source = { registry = "https://pypi.org/simple" }
|
| 3645 |
+
dependencies = [
|
| 3646 |
+
{ name = "pydantic" },
|
| 3647 |
+
{ name = "sqlalchemy" },
|
| 3648 |
+
]
|
| 3649 |
+
sdist = { url = "https://files.pythonhosted.org/packages/fb/26/1d2faa0fd5a765267f49751de533adac6b9ff9366c7c6e7692df4f32230f/sqlmodel-0.0.37.tar.gz", hash = "sha256:d2c19327175794faf50b1ee31cc966764f55b1dedefc046450bc5741a3d68352", size = 85527, upload-time = "2026-02-21T16:39:47.038Z" }
|
| 3650 |
+
wheels = [
|
| 3651 |
+
{ url = "https://files.pythonhosted.org/packages/b1/e1/7c8d18e737433f3b5bbe27b56a9072a9fcb36342b48f1bef34b6da1d61f2/sqlmodel-0.0.37-py3-none-any.whl", hash = "sha256:2137a4045ef3fd66a917a7717ada959a1ceb3630d95e1f6aaab39dd2c0aef278", size = 27224, upload-time = "2026-02-21T16:39:47.781Z" },
|
| 3652 |
+
]
|
| 3653 |
+
|
| 3654 |
[[package]]
|
| 3655 |
name = "stack-data"
|
| 3656 |
version = "0.6.3"
|
|
|
|
| 3787 |
{ name = "typing-extensions", marker = "sys_platform == 'darwin'" },
|
| 3788 |
]
|
| 3789 |
wheels = [
|
| 3790 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:a52952a8c90a422c14627ea99b9826b7557203b46b4d0772d3ca5c7699692425" },
|
| 3791 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:287242dd1f830846098b5eca847f817aa5c6015ea57ab4c1287809efea7b77eb" },
|
| 3792 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8924d10d36eac8fe0652a060a03fc2ae52980841850b9a1a2ddb0f27a4f181cd" },
|
| 3793 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1-cp313-none-macosx_11_0_arm64.whl", hash = "sha256:bcee64ae7aa65876ceeae6dcaebe75109485b213528c74939602208a20706e3f" },
|
| 3794 |
]
|
| 3795 |
|
| 3796 |
[[package]]
|
|
|
|
| 3815 |
{ name = "typing-extensions", marker = "sys_platform != 'darwin'" },
|
| 3816 |
]
|
| 3817 |
wheels = [
|
| 3818 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:0e611cfb16724e62252b67d31073bc5c490cb83e92ecdc1192762535e0e44487" },
|
| 3819 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:3de2adb9b4443dc9210ef1f1b16da3647ace53553166d6360bbbd7edd6f16e4d" },
|
| 3820 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp311-cp311-win_amd64.whl", hash = "sha256:69b3785d28be5a9c56ab525788ec5000349ec59132a74b7d5e954b905015b992" },
|
| 3821 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp311-cp311-win_arm64.whl", hash = "sha256:15b4ae6fe371d96bffb8e1e9af62164797db20a0dc1337345781659cfd0b8bb1" },
|
| 3822 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3bf9b442a51a2948e41216a76d7ab00f0694cfcaaa51b6f9bcab57b7f89843e6" },
|
| 3823 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:7417d8c565f219d3455654cb431c6d892a3eb40246055e14d645422de13b9ea1" },
|
| 3824 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp312-cp312-win_amd64.whl", hash = "sha256:a4e06b4f441675d26b462123c8a83e77c55f1ec8ebc081203be2db1ea8054add" },
|
| 3825 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp312-cp312-win_arm64.whl", hash = "sha256:1abe31f14b560c1f062699e966cb08ef5b67518a1cfac2d8547a3dbcd8387b06" },
|
| 3826 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:3e532e553b37ee859205a9b2d1c7977fd6922f53bbb1b9bfdd5bdc00d1a60ed4" },
|
| 3827 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:39b3dff6d8fba240ae0d1bede4ca11c2531ae3b47329206512d99e17907ff74b" },
|
| 3828 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp313-cp313-win_amd64.whl", hash = "sha256:404a7ab2fffaf2ca069e662f331eb46313692b2f1630df2720094284f390ccef" },
|
| 3829 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp313-cp313-win_arm64.whl", hash = "sha256:161decbff26a33f13cb5ba6d2c8f458bbf56193bcc32ecc70be6dd4c7a3ee79d" },
|
| 3830 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:01b1884f724977a20c7da2f640f1c7b37f4a2c117a7f4a6c1c0424d14cb86322" },
|
| 3831 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:031a597147fa81b1e6d79ccf1ad3ccc7fafa27941d6cf26ff5caaa384fb20e92" },
|
| 3832 |
+
{ url = "https://download.pytorch.org/whl/cpu/torch-2.9.1%2Bcpu-cp313-cp313t-win_amd64.whl", hash = "sha256:e586ab1363e3f86aa4cc133b7fdcf98deb1d2c13d43a7a6e5a6a18e9c5364893" },
|
| 3833 |
]
|
| 3834 |
|
| 3835 |
[[package]]
|