diff --git a/src/backend/app/db/database.py b/src/backend/app/db/database.py index 2f6581f5..ed3a2ebd 100644 --- a/src/backend/app/db/database.py +++ b/src/backend/app/db/database.py @@ -1,25 +1,49 @@ """Config for the DTM database connection.""" - +from databases import Database +from app.config import settings from sqlalchemy import create_engine from sqlalchemy.orm import declarative_base, sessionmaker -from app.config import settings - -engine = create_engine( - settings.DTM_DB_URL.unicode_string(), - pool_size=20, - max_overflow=-1, -) -SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) - Base = declarative_base() -DtmMetadata = Base.metadata - -def get_db(): - """Create SQLAlchemy DB session.""" - db = SessionLocal() +class DatabaseConnection: + """Manages database connection (sqlalchemy & encode databases)""" + def __init__(self): + self.database = Database(settings.DTM_DB_URL.unicode_string(), min_size=5, max_size=20) + # self.database = Database(settings.DTM_DB_URL.unicode_string()) + self.engine = create_engine( + settings.DTM_DB_URL.unicode_string(), + pool_size=20, + max_overflow=-1, + ) + self.SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=self.engine) + + async def connect(self): + """Connect to the database.""" + await self.database.connect() + + async def disconnect(self): + """Disconnect from the database.""" + await self.database.disconnect() + + def create_db_session(self): + """Create a new SQLAlchemy DB session.""" + db = self.SessionLocal() try: - yield db + return db finally: - db.close() + db.close() + +db_connection = DatabaseConnection() # Create a single instance + +def get_db(): + """Yield a new database session.""" + return db_connection.create_db_session() + +async def encode_db(): + """Get the encode database connection""" + try: + await db_connection.connect() + yield db_connection.database + finally: + await db_connection.disconnect() \ No newline at end of file diff --git a/src/backend/app/projects/project_crud.py b/src/backend/app/projects/project_crud.py index 69e06d46..195addab 100644 --- a/src/backend/app/projects/project_crud.py +++ b/src/backend/app/projects/project_crud.py @@ -7,12 +7,51 @@ import shapely.wkb as wkblib from shapely.geometry import shape from fastapi import HTTPException -from app.utils import geometry_to_geojson, merge_multipolygon +from app.utils import geometry_to_geojson, merge_multipolygon, str_to_geojson from fmtm_splitter.splitter import split_by_square from fastapi.concurrency import run_in_threadpool from app.db import database from fastapi import Depends from asyncio import gather +from databases import Database + +async def create_project_with_project_info(db: Database, project_metadata: project_schemas.ProjectIn): + """Create a project in database.""" + query = f""" + INSERT INTO projects ( + author_id, name, short_description, description, per_task_instructions, status, visibility, mapper_level, priority, outline, created + ) + VALUES ( + 1, + '{project_metadata.name}', + '{project_metadata.short_description}', + '{project_metadata.description}', + '{project_metadata.per_task_instructions}', + 'DRAFT', + 'PUBLIC', + 'INTERMEDIATE', + 'MEDIUM', + '{str(project_metadata.outline)}', + CURRENT_TIMESTAMP + ) + RETURNING id + """ + new_project_id = await db.execute(query) + + if not new_project_id: + raise HTTPException( + status_code=500, + detail="Project could not be created" + ) + # Fetch the newly created project using the returned ID + select_query = f""" + SELECT id, name, short_description, description, per_task_instructions, outline + FROM projects + WHERE id = '{new_project_id}' + """ + new_project = await db.fetch_one(query=select_query) + return new_project + async def get_project_by_id( @@ -26,41 +65,37 @@ async def get_project_by_id( ) return await convert_to_app_project(db_project) - -async def convert_to_app_project(db_project: db_models.DbProject): - """Legacy function to convert db models --> Pydantic. - - TODO refactor to use Pydantic model methods instead. - """ - if not db_project: - log.debug("convert_to_app_project called, but no project provided") - return None - - app_project = db_project - - if db_project.outline: - app_project.outline_geojson = geometry_to_geojson( - db_project.outline, {"id": db_project.id}, db_project.id - ) - app_project.tasks = db_project.tasks - return app_project - - async def get_projects( - db: Session, + db:Database, skip: int = 0, limit: int = 100, ): """Get all projects.""" - db_projects = ( - db.query(db_models.DbProject) - .order_by(db_models.DbProject.id.desc()) - .offset(skip) - .limit(limit) - .all() - ) - project_count = db.query(db_models.DbProject).count() - return project_count, await convert_to_app_projects(db_projects) + raw_sql = """ + SELECT id, name, short_description, description, per_task_instructions, outline + FROM projects + ORDER BY id DESC + OFFSET :skip + LIMIT :limit; + """ + db_projects = await db.fetch_all(raw_sql, {'skip': skip, 'limit': limit}) + return await convert_to_app_projects(db_projects) + +# async def get_projects( +# db: Session, +# skip: int = 0, +# limit: int = 100, +# ): +# """Get all projects.""" +# db_projects = ( +# db.query(db_models.DbProject) +# .order_by(db_models.DbProject.id.desc()) +# .offset(skip) +# .limit(limit) +# .all() +# ) +# project_count = db.query(db_models.DbProject).count() +# return project_count, await convert_to_app_projects(db_projects) async def convert_to_app_projects( @@ -82,22 +117,22 @@ async def convert_project(project): else: return [] +async def convert_to_app_project(db_project: db_models.DbProject): + """Legacy function to convert db models --> Pydantic.""" + if not db_project: + log.debug("convert_to_app_project called, but no project provided") + return None + app_project = db_project -async def create_project_with_project_info( - db: Session, project_metadata: project_schemas.ProjectIn -): - """Create a project in database.""" - db_project = db_models.DbProject( - author_id=1, **project_metadata.model_dump(exclude=["outline_geojson"]) - ) - db.add(db_project) - db.commit() - db.refresh(db_project) - return db_project - + if db_project.outline: + + app_project.outline_geojson = str_to_geojson( + db_project.outline, {"id": db_project.id}, db_project.id + ) + return app_project async def create_tasks_from_geojson( - db: Session, + db: Database, project_id: int, boundaries: str, ): @@ -119,26 +154,18 @@ async def create_tasks_from_geojson( polygon["geometry"]["type"] = "Polygon" polygon["geometry"]["coordinates"] = polygon["geometry"]["coordinates"][ 0 - ] - - db_task = db_models.DbTask( - project_id=project_id, - outline=wkblib.dumps(shape(polygon["geometry"]), hex=True), - project_task_index=index + 1, - ) - db.add(db_task) - log.debug( - "Created database task | " - f"Project ID {project_id} | " - f"Task index {index}" - ) - - # Commit all tasks and update project location in db - db.commit() - - log.debug("COMPLETE: creating project boundary, based on task boundaries") - - return True + ] + query = f""" INSERT INTO tasks (project_id,outline,project_task_index) VALUES ( '{project_id}', '{wkblib.dumps(shape(polygon["geometry"]), hex=True)}', '{index + 1}');""" + + result = await db.execute(query) + if result: + log.debug( + "Created database task | " + f"Project ID {project_id} | " + f"Task index {index}" + ) + log.debug("COMPLETE: creating project boundary, based on task boundaries") + return True except Exception as e: log.exception(e) raise HTTPException(e) from e diff --git a/src/backend/app/projects/project_routes.py b/src/backend/app/projects/project_routes.py index 60e28cea..084ebf8b 100644 --- a/src/backend/app/projects/project_routes.py +++ b/src/backend/app/projects/project_routes.py @@ -13,9 +13,9 @@ from app.utils import multipolygon_to_polygon from app.s3 import s3_client from app.config import settings +from databases import Database from app.db import db_models - router = APIRouter( prefix=f"{settings.API_PREFIX}/projects", responses={404: {"description": "Not found"}}, @@ -66,21 +66,14 @@ def delete_project_by_id(project_id: int, db: Session = Depends(database.get_db) ) async def create_project( project_info: project_schemas.ProjectIn, - db: Session = Depends(database.get_db), + db: Database = Depends(database.encode_db), ): """Create a project in database.""" - - log.info( - f"Attempting creation of project " - f"{project_info.name} in organisation {project_info.organisation_id}" - ) - project = await project_crud.create_project_with_project_info(db, project_info) if not project: raise HTTPException( status_code=HTTPStatus.BAD_REQUEST, detail="Project creation failed" ) - return project @@ -88,7 +81,7 @@ async def create_project( async def upload_project_task_boundaries( project_id: int, task_geojson: UploadFile = File(...), - db: Session = Depends(database.get_db), + db: Database = Depends(database.encode_db), ): """Set project task boundaries using split GeoJSON from frontend. @@ -100,8 +93,7 @@ async def upload_project_task_boundaries( Returns: dict: JSON containing success message, project ID, and number of tasks. - """ - + """ # read entire file content = await task_geojson.read() task_boundaries = json.loads(content) @@ -173,10 +165,10 @@ async def generate_presigned_url(data: project_schemas.PresignedUrlRequest): async def read_projects( skip: int = 0, limit: int = 100, - db: Session = Depends(database.get_db), + db: Database = Depends(database.encode_db) ): - """Return all projects.""" - total_count, projects = await project_crud.get_projects(db, skip, limit) + "Return all projects" + projects = await project_crud.get_projects(db, skip, limit) return projects diff --git a/src/backend/app/projects/project_schemas.py b/src/backend/app/projects/project_schemas.py index d71ee32a..c4993caa 100644 --- a/src/backend/app/projects/project_schemas.py +++ b/src/backend/app/projects/project_schemas.py @@ -8,6 +8,7 @@ geojson_to_geometry, read_wkb, merge_multipolygon, + str_to_geojson, write_wkb, geometry_to_geojson, ) @@ -15,7 +16,7 @@ class ProjectInfo(BaseModel): """Basic project info.""" - + id: int name: str short_description: str description: str @@ -69,9 +70,11 @@ def outline_geojson(self) -> Optional[Feature]: """Compute the geojson outline from WKBElement outline.""" if not self.outline: return None - geometry = wkb.loads(bytes(self.outline.data)) - bbox = geometry.bounds # Calculate bounding box - return geometry_to_geojson(self.outline, {"id": self.id, "bbox": bbox}, self.id) + wkb_data = bytes.fromhex(self.outline) + geom = wkb.loads(wkb_data) + # geometry = wkb.loads(bytes(self.outline.data)) + bbox = geom.bounds # Calculate bounding box + return str_to_geojson(self.outline, {"id": self.id, "bbox": bbox}, self.id) class PresignedUrlRequest(BaseModel): diff --git a/src/backend/app/users/user_crud.py b/src/backend/app/users/user_crud.py index b262473b..a4ab7831 100644 --- a/src/backend/app/users/user_crud.py +++ b/src/backend/app/users/user_crud.py @@ -7,9 +7,9 @@ from app.db import db_models from app.users.user_schemas import UserCreate from sqlalchemy import text +from databases import Database from fastapi import HTTPException - pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") @@ -61,18 +61,22 @@ def get_password_hash(password: str) -> str: return pwd_context.hash(password) -# def get_user_by_email(db: Session, email: str) -> db_models.DbUser | None: -# output = db.query(db_models.DbUser).filter(db_models.DbUser.email_address == email).first() -# print("output = ",output) -# return output - - def get_user_by_email(db: Session, email: str): query = text(f"SELECT * FROM users WHERE email_address = '{email}' LIMIT 1;") result = db.execute(query) data = result.fetchone() return data +async def get_user_email(db: Database, email: str): + query = f"SELECT * FROM users WHERE email_address = '{email}' LIMIT 1;" + result = await db.fetch_one(query) + return result + + +async def get_user_username(db: Database, username: str): + query = f"SELECT * FROM users WHERE username = '{username}' LIMIT 1;" + result = await db.fetch_one(query=query) + return result def get_user_by_username(db: Session, username: str): query = text(f"SELECT * FROM users WHERE username = '{username}' LIMIT 1;") @@ -80,28 +84,35 @@ def get_user_by_username(db: Session, username: str): data = result.fetchone() return data - -# def get_user_by_username(db: Session, username: str): -# return db.query(db_models.DbUser).filter(db_models.DbUser.username==username).first() - - -def authenticate(db: Session, username: str, password: str) -> db_models.DbUser | None: - db_user = get_user_by_username(db, username) +async def authenticate(db: Database, username: str, password: str) -> db_models.DbUser | None: + db_user = await get_user_username(db, username) if not db_user: return None - if not verify_password(password, db_user.password): + if not verify_password(password, db_user['password']): return None return db_user +# def authenticate(db: Session, username: str, password: str) -> db_models.DbUser | None: +# db_user = get_user_by_username(db, username) +# if not db_user: +# return None +# if not verify_password(password, db_user.password): +# return None +# return db_user -def create_user(db: Session, user_create: UserCreate): - db_obj = db_models.DbUser( - is_active=True, # FIXME: set to false by default, activate through email - password=get_password_hash(user_create.password), - **user_create.model_dump(exclude=["password"]), - ) - db.add(db_obj) - db.commit() - db.refresh(db_obj) +async def create_user(db: Database, user_create: UserCreate): + query = f""" + INSERT INTO users (username, password, is_active, name, email_address, is_superuser) + VALUES ('{user_create.username}', '{get_password_hash(user_create.password)}', {True}, '{user_create.name}', '{user_create.email_address}', {False}) + RETURNING id + """ + _id = await db.execute(query) + raw_query = f"SELECT * from users WHERE id = {_id} LIMIT 1" + db_obj = await db.fetch_one(query=raw_query) + if not db_obj: + raise HTTPException( + status_code=500, + detail="User could not be created" + ) return db_obj diff --git a/src/backend/app/users/user_deps.py b/src/backend/app/users/user_deps.py index 44357b07..c56434d1 100644 --- a/src/backend/app/users/user_deps.py +++ b/src/backend/app/users/user_deps.py @@ -1,6 +1,6 @@ import jwt from typing import Annotated - +from databases import Database from fastapi import Depends, HTTPException, Request, status, Header from fastapi.security import OAuth2PasswordBearer from jwt.exceptions import InvalidTokenError @@ -16,7 +16,10 @@ reusable_oauth2 = OAuth2PasswordBearer(tokenUrl=f"{settings.API_PREFIX}/users/login") - +# SessionDep = Annotated[ +# Database, +# Depends(database.encode_db), +# ] SessionDep = Annotated[ Session, Depends(database.get_db), diff --git a/src/backend/app/users/user_routes.py b/src/backend/app/users/user_routes.py index 5f4da862..641fa15f 100644 --- a/src/backend/app/users/user_routes.py +++ b/src/backend/app/users/user_routes.py @@ -1,4 +1,4 @@ -from typing import Any +from typing import Any, List from datetime import timedelta from fastapi import APIRouter, HTTPException, Depends from sqlalchemy.orm import Session @@ -9,6 +9,9 @@ from app.config import settings from app.users import user_crud from app.db import database +from databases import Database +from app.users import user_schemas +from app.config import settings router = APIRouter( prefix=f"{settings.API_PREFIX}/users", @@ -16,16 +19,15 @@ responses={404: {"description": "Not found"}}, ) - @router.post("/login/") -def login_access_token( +async def login_access_token( form_data: Annotated[OAuth2PasswordRequestForm, Depends()], - db: Session = Depends(database.get_db), + db: Database = Depends(database.encode_db), ) -> Token: """ OAuth2 compatible token login, get an access token for future requests """ - user = user_crud.authenticate(db, form_data.username, form_data.password) + user = await user_crud.authenticate(db, form_data.username, form_data.password) if not user: raise HTTPException(status_code=400, detail="Incorrect email or password") @@ -38,29 +40,52 @@ def login_access_token( return Token(access_token=access_token, refresh_token=refresh_token) +# @router.post("/login/") +# def login_access_token( +# form_data: Annotated[OAuth2PasswordRequestForm, Depends()], +# db: Session = Depends(database.get_db), +# ) -> Token: +# """ +# OAuth2 compatible token login, get an access token for future requests +# """ +# user = user_crud.authenticate(db, form_data.username, form_data.password) + +# if not user: +# raise HTTPException(status_code=400, detail="Incorrect email or password") +# elif not user.is_active: +# raise HTTPException(status_code=400, detail="Inactive user") +# access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES) +# refresh_token_expires = timedelta(minutes=settings.REFRESH_TOKEN_EXPIRE_MINUTES) + +# access_token, refresh_token = user_crud.create_access_token( +# user.id, +# expires_delta=access_token_expires, +# refresh_token_expiry=refresh_token_expires, +# ) +# return Token(access_token=access_token, refresh_token=refresh_token) + @router.post("/signup", response_model=UserPublic) -def register_user( +async def register_user( user_in: UserRegister, - db: Session = Depends(database.get_db), + db: Database = Depends(database.encode_db), ): """ Create new user without the need to be logged in. """ - user = user_crud.get_user_by_email(db, user_in.email_address) + user = await user_crud.get_user_email(db, user_in.email_address) if user: raise HTTPException( status_code=400, detail="The user with this email already exists in the system", ) - user = user_crud.get_user_by_username(db, user_in.username) + user = await user_crud.get_user_username(db, user_in.username) if user: raise HTTPException( status_code=400, detail="The user with this username already exists in the system", ) - - user = user_crud.create_user(db, user_in) + user = await user_crud.create_user(db, user_in) return user diff --git a/src/backend/app/users/user_schemas.py b/src/backend/app/users/user_schemas.py index 309f16da..01330c99 100644 --- a/src/backend/app/users/user_schemas.py +++ b/src/backend/app/users/user_schemas.py @@ -17,8 +17,7 @@ class UserBase(BaseModel): is_active: bool = True is_superuser: bool = False name: str - - + class User(BaseModel): email_address: EmailStr is_active: bool diff --git a/src/backend/app/utils.py b/src/backend/app/utils.py index a431952e..db287cad 100644 --- a/src/backend/app/utils.py +++ b/src/backend/app/utils.py @@ -11,6 +11,7 @@ from shapely.geometry import mapping, shape from shapely.ops import unary_union from fastapi import HTTPException +from shapely import wkb log = logging.getLogger(__name__) @@ -24,6 +25,22 @@ def timestamp(): return datetime.now(timezone.utc) +def str_to_geojson( + result: str, properties: Optional[dict] = None, id: Optional[int] = None +) -> Union[Feature, dict]: + """Convert SQLAlchemy geometry to GeoJSON.""" + if result: + wkb_data = bytes.fromhex(result) + geom = wkb.loads(wkb_data) + geojson = { + "type": "Feature", + "geometry": mapping(geom), + "properties": properties, + "id": id, + } + return Feature(**geojson) + return {} + def geometry_to_geojson( geometry: WKBElement, properties: Optional[dict] = None, id: Optional[int] = None ) -> Union[Feature, dict]: @@ -40,7 +57,6 @@ def geometry_to_geojson( return Feature(**geojson) return {} - def geojson_to_geometry( geojson: Union[FeatCol, Feature, MultiPolygon, Polygon], ) -> Optional[WKBElement]: diff --git a/src/backend/pdm.lock b/src/backend/pdm.lock index 1fae06e2..290327d3 100644 --- a/src/backend/pdm.lock +++ b/src/backend/pdm.lock @@ -3,23 +3,24 @@ [metadata] groups = ["default"] -strategy = ["cross_platform"] -lock_version = "4.4.2" -content_hash = "sha256:2290067fa88e5b96a1155bc80250f5d0aa1c49d4ccc8ede2b68b052ae9797216" +strategy = ["cross_platform", "inherit_metadata"] +lock_version = "4.4.1" +content_hash = "sha256:290d9c3f29acfe809ff147f097a4a0ddd95fd5ca93cdd7f1509537775cd02541" [[package]] name = "alembic" -version = "1.13.1" +version = "1.13.2" requires_python = ">=3.8" summary = "A database migration tool for SQLAlchemy." +groups = ["default"] dependencies = [ "Mako", "SQLAlchemy>=1.3.0", "typing-extensions>=4", ] files = [ - {file = "alembic-1.13.1-py3-none-any.whl", hash = "sha256:2edcc97bed0bd3272611ce3a98d98279e9c209e7186e43e75bbb1b2bdfdbcc43"}, - {file = "alembic-1.13.1.tar.gz", hash = "sha256:4932c8558bf68f2ee92b9bbcb8218671c627064d5b08939437af6d77dc05e595"}, + {file = "alembic-1.13.2-py3-none-any.whl", hash = "sha256:6b8733129a6224a9a711e17c99b08462dbf7cc9670ba8f2e2ae9af860ceb1953"}, + {file = "alembic-1.13.2.tar.gz", hash = "sha256:1ff0ae32975f4fd96028c39ed9bb3c867fe3af956bd7bb37343b54c9fe7445ef"}, ] [[package]] @@ -27,6 +28,7 @@ name = "annotated-types" version = "0.7.0" requires_python = ">=3.8" summary = "Reusable constraint types to use with typing.Annotated" +groups = ["default"] files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, @@ -37,6 +39,7 @@ name = "anyio" version = "3.7.1" requires_python = ">=3.7" summary = "High level compatibility layer for multiple asynchronous event loop implementations" +groups = ["default"] dependencies = [ "exceptiongroup; python_version < \"3.11\"", "idna>=2.8", @@ -52,6 +55,8 @@ name = "appnope" version = "0.1.4" requires_python = ">=3.6" summary = "Disable App Nap on macOS >= 10.9" +groups = ["default"] +marker = "sys_platform == \"darwin\"" files = [ {file = "appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c"}, {file = "appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee"}, @@ -62,6 +67,7 @@ name = "argon2-cffi" version = "23.1.0" requires_python = ">=3.7" summary = "Argon2 for Python" +groups = ["default"] dependencies = [ "argon2-cffi-bindings", ] @@ -75,6 +81,7 @@ name = "argon2-cffi-bindings" version = "21.2.0" requires_python = ">=3.6" summary = "Low-level CFFI bindings for Argon2" +groups = ["default"] dependencies = [ "cffi>=1.0.1", ] @@ -106,6 +113,7 @@ files = [ name = "asttokens" version = "2.4.1" summary = "Annotate AST trees with source code positions" +groups = ["default"] dependencies = [ "six>=1.12.0", ] @@ -114,10 +122,60 @@ files = [ {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"}, ] +[[package]] +name = "async-timeout" +version = "4.0.3" +requires_python = ">=3.7" +summary = "Timeout context manager for asyncio programs" +groups = ["default"] +marker = "python_version < \"3.12.0\"" +files = [ + {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, + {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, +] + +[[package]] +name = "asyncpg" +version = "0.29.0" +requires_python = ">=3.8.0" +summary = "An asyncio PostgreSQL driver" +groups = ["default"] +dependencies = [ + "async-timeout>=4.0.3; python_version < \"3.12.0\"", +] +files = [ + {file = "asyncpg-0.29.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72fd0ef9f00aeed37179c62282a3d14262dbbafb74ec0ba16e1b1864d8a12169"}, + {file = "asyncpg-0.29.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52e8f8f9ff6e21f9b39ca9f8e3e33a5fcdceaf5667a8c5c32bee158e313be385"}, + {file = "asyncpg-0.29.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e6823a7012be8b68301342ba33b4740e5a166f6bbda0aee32bc01638491a22"}, + {file = "asyncpg-0.29.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:746e80d83ad5d5464cfbf94315eb6744222ab00aa4e522b704322fb182b83610"}, + {file = "asyncpg-0.29.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ff8e8109cd6a46ff852a5e6bab8b0a047d7ea42fcb7ca5ae6eaae97d8eacf397"}, + {file = "asyncpg-0.29.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:97eb024685b1d7e72b1972863de527c11ff87960837919dac6e34754768098eb"}, + {file = "asyncpg-0.29.0-cp310-cp310-win32.whl", hash = "sha256:5bbb7f2cafd8d1fa3e65431833de2642f4b2124be61a449fa064e1a08d27e449"}, + {file = "asyncpg-0.29.0-cp310-cp310-win_amd64.whl", hash = "sha256:76c3ac6530904838a4b650b2880f8e7af938ee049e769ec2fba7cd66469d7772"}, + {file = "asyncpg-0.29.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4900ee08e85af01adb207519bb4e14b1cae8fd21e0ccf80fac6aa60b6da37b4"}, + {file = "asyncpg-0.29.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a65c1dcd820d5aea7c7d82a3fdcb70e096f8f70d1a8bf93eb458e49bfad036ac"}, + {file = "asyncpg-0.29.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b52e46f165585fd6af4863f268566668407c76b2c72d366bb8b522fa66f1870"}, + {file = "asyncpg-0.29.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc600ee8ef3dd38b8d67421359779f8ccec30b463e7aec7ed481c8346decf99f"}, + {file = "asyncpg-0.29.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:039a261af4f38f949095e1e780bae84a25ffe3e370175193174eb08d3cecab23"}, + {file = "asyncpg-0.29.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6feaf2d8f9138d190e5ec4390c1715c3e87b37715cd69b2c3dfca616134efd2b"}, + {file = "asyncpg-0.29.0-cp311-cp311-win32.whl", hash = "sha256:1e186427c88225ef730555f5fdda6c1812daa884064bfe6bc462fd3a71c4b675"}, + {file = "asyncpg-0.29.0-cp311-cp311-win_amd64.whl", hash = "sha256:cfe73ffae35f518cfd6e4e5f5abb2618ceb5ef02a2365ce64f132601000587d3"}, + {file = "asyncpg-0.29.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6011b0dc29886ab424dc042bf9eeb507670a3b40aece3439944006aafe023178"}, + {file = "asyncpg-0.29.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b544ffc66b039d5ec5a7454667f855f7fec08e0dfaf5a5490dfafbb7abbd2cfb"}, + {file = "asyncpg-0.29.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d84156d5fb530b06c493f9e7635aa18f518fa1d1395ef240d211cb563c4e2364"}, + {file = "asyncpg-0.29.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54858bc25b49d1114178d65a88e48ad50cb2b6f3e475caa0f0c092d5f527c106"}, + {file = "asyncpg-0.29.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bde17a1861cf10d5afce80a36fca736a86769ab3579532c03e45f83ba8a09c59"}, + {file = "asyncpg-0.29.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:37a2ec1b9ff88d8773d3eb6d3784dc7e3fee7756a5317b67f923172a4748a175"}, + {file = "asyncpg-0.29.0-cp312-cp312-win32.whl", hash = "sha256:bb1292d9fad43112a85e98ecdc2e051602bce97c199920586be83254d9dafc02"}, + {file = "asyncpg-0.29.0-cp312-cp312-win_amd64.whl", hash = "sha256:2245be8ec5047a605e0b454c894e54bf2ec787ac04b1cb7e0d3c67aa1e32f0fe"}, + {file = "asyncpg-0.29.0.tar.gz", hash = "sha256:d1c49e1f44fffafd9a55e1a9b101590859d881d639ea2922516f5d9c512d354e"}, +] + [[package]] name = "backcall" version = "0.2.0" summary = "Specifications for callback functions passed in to an API" +groups = ["default"] files = [ {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, @@ -128,6 +186,7 @@ name = "bcrypt" version = "4.0.1" requires_python = ">=3.6" summary = "Modern password hashing for your software and your servers" +groups = ["default"] files = [ {file = "bcrypt-4.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:b1023030aec778185a6c16cf70f359cbb6e0c289fd564a7cfa29e727a1c38f8f"}, {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:08d2947c490093a11416df18043c27abe3921558d2c03e2076ccb28a116cb6d0"}, @@ -154,12 +213,13 @@ files = [ [[package]] name = "certifi" -version = "2024.2.2" +version = "2024.6.2" requires_python = ">=3.6" summary = "Python package for providing Mozilla's CA Bundle." +groups = ["default"] files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, + {file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"}, + {file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"}, ] [[package]] @@ -167,6 +227,7 @@ name = "cffi" version = "1.16.0" requires_python = ">=3.8" summary = "Foreign Function Interface for Python calling C code." +groups = ["default"] dependencies = [ "pycparser", ] @@ -211,6 +272,7 @@ name = "charset-normalizer" version = "3.3.2" requires_python = ">=3.7.0" summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +groups = ["default"] files = [ {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, @@ -266,6 +328,7 @@ name = "click" version = "8.1.7" requires_python = ">=3.7" summary = "Composable command line interface toolkit" +groups = ["default"] dependencies = [ "colorama; platform_system == \"Windows\"", ] @@ -279,6 +342,8 @@ name = "colorama" version = "0.4.6" requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" summary = "Cross-platform colored terminal text." +groups = ["default"] +marker = "sys_platform == \"win32\" or platform_system == \"Windows\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -286,45 +351,60 @@ files = [ [[package]] name = "cryptography" -version = "42.0.7" +version = "42.0.8" requires_python = ">=3.7" summary = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +groups = ["default"] dependencies = [ "cffi>=1.12; platform_python_implementation != \"PyPy\"", ] files = [ - {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477"}, - {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7"}, - {file = "cryptography-42.0.7-cp37-abi3-win32.whl", hash = "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b"}, - {file = "cryptography-42.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678"}, - {file = "cryptography-42.0.7-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886"}, - {file = "cryptography-42.0.7-cp39-abi3-win32.whl", hash = "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda"}, - {file = "cryptography-42.0.7-cp39-abi3-win_amd64.whl", hash = "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68"}, - {file = "cryptography-42.0.7.tar.gz", hash = "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2"}, + {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"}, + {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7"}, + {file = "cryptography-42.0.8-cp37-abi3-win32.whl", hash = "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2"}, + {file = "cryptography-42.0.8-cp37-abi3-win_amd64.whl", hash = "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba"}, + {file = "cryptography-42.0.8-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14"}, + {file = "cryptography-42.0.8-cp39-abi3-win32.whl", hash = "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c"}, + {file = "cryptography-42.0.8-cp39-abi3-win_amd64.whl", hash = "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad"}, + {file = "cryptography-42.0.8.tar.gz", hash = "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2"}, +] + +[[package]] +name = "databases" +version = "0.9.0" +requires_python = ">=3.8" +summary = "Async database support for Python." +groups = ["default"] +dependencies = [ + "sqlalchemy>=2.0.7", +] +files = [ + {file = "databases-0.9.0-py3-none-any.whl", hash = "sha256:9ee657c9863b34f8d3a06c06eafbe1bda68af2a434b56996312edf1f1c0b6297"}, + {file = "databases-0.9.0.tar.gz", hash = "sha256:d2f259677609bf187737644c95fa41701072e995dfeb8d2882f335795c5b61b0"}, ] [[package]] @@ -332,6 +412,7 @@ name = "decorator" version = "5.1.1" requires_python = ">=3.5" summary = "Decorators for Humans" +groups = ["default"] files = [ {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, @@ -342,6 +423,7 @@ name = "dnspython" version = "2.6.1" requires_python = ">=3.8" summary = "DNS toolkit" +groups = ["default"] files = [ {file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"}, {file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"}, @@ -352,6 +434,7 @@ name = "ecdsa" version = "0.19.0" requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.6" summary = "ECDSA cryptographic signature library (pure python)" +groups = ["default"] dependencies = [ "six>=1.9.0", ] @@ -362,16 +445,17 @@ files = [ [[package]] name = "email-validator" -version = "2.1.1" +version = "2.2.0" requires_python = ">=3.8" summary = "A robust email address syntax and deliverability validation library." +groups = ["default"] dependencies = [ "dnspython>=2.0.0", "idna>=2.0.0", ] files = [ - {file = "email_validator-2.1.1-py3-none-any.whl", hash = "sha256:97d882d174e2a65732fb43bfce81a3a834cbc1bde8bf419e30ef5ea976370a05"}, - {file = "email_validator-2.1.1.tar.gz", hash = "sha256:200a70680ba08904be6d1eef729205cc0d687634399a5924d842533efb824b84"}, + {file = "email_validator-2.2.0-py3-none-any.whl", hash = "sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631"}, + {file = "email_validator-2.2.0.tar.gz", hash = "sha256:cb690f344c617a714f22e66ae771445a1ceb46821152df8e165c5f9a364582b7"}, ] [[package]] @@ -379,6 +463,8 @@ name = "exceptiongroup" version = "1.2.1" requires_python = ">=3.7" summary = "Backport of PEP 654 (exception groups)" +groups = ["default"] +marker = "python_version < \"3.11\"" files = [ {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, @@ -389,6 +475,7 @@ name = "executing" version = "2.0.1" requires_python = ">=3.5" summary = "Get the currently executing AST node of a frame, and other information" +groups = ["default"] files = [ {file = "executing-2.0.1-py2.py3-none-any.whl", hash = "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc"}, {file = "executing-2.0.1.tar.gz", hash = "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147"}, @@ -399,6 +486,7 @@ name = "fastapi" version = "0.104.1" requires_python = ">=3.8" summary = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" +groups = ["default"] dependencies = [ "anyio<4.0.0,>=3.7.1", "pydantic!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0,>=1.7.4", @@ -414,15 +502,17 @@ files = [ name = "flatdict" version = "4.0.1" summary = "Python module for interacting with nested dicts as a single level dict with delimited keys." +groups = ["default"] files = [ {file = "flatdict-4.0.1.tar.gz", hash = "sha256:cd32f08fd31ed21eb09ebc76f06b6bd12046a24f77beb1fd0281917e47f26742"}, ] [[package]] name = "fmtm-splitter" -version = "1.2.1" +version = "1.2.2" requires_python = ">=3.10" summary = "A utility for splitting an AOI into multiple tasks." +groups = ["default"] dependencies = [ "geojson>=2.5.0", "numpy>=1.21.0", @@ -431,8 +521,8 @@ dependencies = [ "shapely>=1.8.1", ] files = [ - {file = "fmtm-splitter-1.2.1.tar.gz", hash = "sha256:51e79cc8f15e4e2ad571d5bff4403dcfff2c0d0a75f4c0a26c4469557708403c"}, - {file = "fmtm_splitter-1.2.1-py3-none-any.whl", hash = "sha256:80d2ae657a2596668a19f193a874d091b153d203415c9e87d76b7f76810b6180"}, + {file = "fmtm-splitter-1.2.2.tar.gz", hash = "sha256:9384dbf00c0e53e24e1f13046ae6693e13567ff3dc0f59f29f4a96ac4a54105e"}, + {file = "fmtm_splitter-1.2.2-py3-none-any.whl", hash = "sha256:bbef78cf0e1f2b67f8c8aeaadb7fd2927bfd333d216927059a12abbbb04a5742"}, ] [[package]] @@ -440,6 +530,7 @@ name = "geoalchemy2" version = "0.14.2" requires_python = ">=3.7" summary = "Using SQLAlchemy with Spatial Databases" +groups = ["default"] dependencies = [ "SQLAlchemy>=1.4", "packaging", @@ -454,6 +545,7 @@ name = "geojson" version = "3.1.0" requires_python = ">=3.7" summary = "Python bindings and utilities for GeoJSON" +groups = ["default"] files = [ {file = "geojson-3.1.0-py3-none-any.whl", hash = "sha256:68a9771827237adb8c0c71f8527509c8f5bef61733aa434cefc9c9d4f0ebe8f3"}, {file = "geojson-3.1.0.tar.gz", hash = "sha256:58a7fa40727ea058efc28b0e9ff0099eadf6d0965e04690830208d3ef571adac"}, @@ -464,6 +556,7 @@ name = "geojson-pydantic" version = "1.0.1" requires_python = ">=3.8" summary = "Pydantic data models for the GeoJSON spec." +groups = ["default"] dependencies = [ "pydantic~=2.0", ] @@ -477,6 +570,8 @@ name = "greenlet" version = "3.0.3" requires_python = ">=3.7" summary = "Lightweight in-process concurrent programming" +groups = ["default"] +marker = "platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\"" files = [ {file = "greenlet-3.0.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9da2bd29ed9e4f15955dd1595ad7bc9320308a3b766ef7f837e23ad4b4aac31a"}, {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d353cadd6083fdb056bb46ed07e4340b0869c305c8ca54ef9da3421acbdf6881"}, @@ -513,6 +608,7 @@ name = "h11" version = "0.14.0" requires_python = ">=3.7" summary = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +groups = ["default"] files = [ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, @@ -523,6 +619,7 @@ name = "idna" version = "3.7" requires_python = ">=3.5" summary = "Internationalized Domain Names in Applications (IDNA)" +groups = ["default"] files = [ {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, @@ -533,6 +630,7 @@ name = "ipython" version = "8.14.0" requires_python = ">=3.9" summary = "IPython: Productive Interactive Computing" +groups = ["default"] dependencies = [ "appnope; sys_platform == \"darwin\"", "backcall", @@ -557,6 +655,7 @@ name = "itsdangerous" version = "2.2.0" requires_python = ">=3.8" summary = "Safely pass data to untrusted environments and back." +groups = ["default"] files = [ {file = "itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef"}, {file = "itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"}, @@ -567,6 +666,7 @@ name = "jedi" version = "0.19.1" requires_python = ">=3.6" summary = "An autocompletion tool for Python that can be used for text editors." +groups = ["default"] dependencies = [ "parso<0.9.0,>=0.8.3", ] @@ -580,6 +680,7 @@ name = "jinja2" version = "3.1.4" requires_python = ">=3.7" summary = "A very fast and expressive template engine." +groups = ["default"] dependencies = [ "MarkupSafe>=2.0", ] @@ -593,6 +694,7 @@ name = "loguru" version = "0.7.2" requires_python = ">=3.5" summary = "Python logging made (stupidly) simple" +groups = ["default"] dependencies = [ "colorama>=0.3.4; sys_platform == \"win32\"", "win32-setctime>=1.0.0; sys_platform == \"win32\"", @@ -607,6 +709,7 @@ name = "mako" version = "1.3.5" requires_python = ">=3.8" summary = "A super-fast templating language that borrows the best ideas from the existing templating languages." +groups = ["default"] dependencies = [ "MarkupSafe>=0.9.2", ] @@ -620,6 +723,7 @@ name = "markupsafe" version = "2.1.5" requires_python = ">=3.7" summary = "Safely add untrusted strings to HTML/XML markup." +groups = ["default"] files = [ {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, @@ -659,6 +763,7 @@ name = "matplotlib-inline" version = "0.1.7" requires_python = ">=3.8" summary = "Inline Matplotlib backend for Jupyter" +groups = ["default"] dependencies = [ "traitlets", ] @@ -671,6 +776,7 @@ files = [ name = "minio" version = "7.2.7" summary = "MinIO Python SDK for Amazon S3 Compatible Cloud Storage" +groups = ["default"] dependencies = [ "argon2-cffi", "certifi", @@ -688,6 +794,7 @@ name = "numpy" version = "1.26.4" requires_python = ">=3.9" summary = "Fundamental package for array computing in Python" +groups = ["default"] files = [ {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, @@ -724,6 +831,7 @@ name = "oauthlib" version = "3.2.2" requires_python = ">=3.6" summary = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" +groups = ["default"] files = [ {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"}, {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"}, @@ -734,6 +842,7 @@ name = "osm-rawdata" version = "0.3.0" requires_python = ">=3.10" summary = "Make data extracts from OSM data." +groups = ["default"] dependencies = [ "GeoAlchemy2>=0.11.0", "PyYAML>=6.0.0", @@ -753,12 +862,13 @@ files = [ [[package]] name = "packaging" -version = "24.0" -requires_python = ">=3.7" +version = "24.1" +requires_python = ">=3.8" summary = "Core utilities for Python packages" +groups = ["default"] files = [ - {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, - {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, + {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, + {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] [[package]] @@ -766,6 +876,7 @@ name = "parso" version = "0.8.4" requires_python = ">=3.6" summary = "A Python Parser" +groups = ["default"] files = [ {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"}, {file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"}, @@ -775,6 +886,7 @@ files = [ name = "passlib" version = "1.7.4" summary = "comprehensive password hashing framework supporting over 30 schemes" +groups = ["default"] files = [ {file = "passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1"}, {file = "passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"}, @@ -785,6 +897,7 @@ name = "passlib" version = "1.7.4" extras = ["bcrypt"] summary = "comprehensive password hashing framework supporting over 30 schemes" +groups = ["default"] dependencies = [ "bcrypt>=3.1.0", "passlib==1.7.4", @@ -798,6 +911,8 @@ files = [ name = "pexpect" version = "4.9.0" summary = "Pexpect allows easy control of interactive console applications." +groups = ["default"] +marker = "sys_platform != \"win32\"" dependencies = [ "ptyprocess>=0.5", ] @@ -810,6 +925,7 @@ files = [ name = "pickleshare" version = "0.7.5" summary = "Tiny 'shelve'-like database with concurrency support" +groups = ["default"] files = [ {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, @@ -817,15 +933,16 @@ files = [ [[package]] name = "prompt-toolkit" -version = "3.0.45" +version = "3.0.47" requires_python = ">=3.7.0" summary = "Library for building powerful interactive command lines in Python" +groups = ["default"] dependencies = [ "wcwidth", ] files = [ - {file = "prompt_toolkit-3.0.45-py3-none-any.whl", hash = "sha256:a29b89160e494e3ea8622b09fa5897610b437884dcdcd054fdc1308883326c2a"}, - {file = "prompt_toolkit-3.0.45.tar.gz", hash = "sha256:07c60ee4ab7b7e90824b61afa840c8f5aad2d46b3e2e10acc33d8ecc94a49089"}, + {file = "prompt_toolkit-3.0.47-py3-none-any.whl", hash = "sha256:0d7bfa67001d5e39d02c224b663abc33687405033a8c422d0d675a5a13361d10"}, + {file = "prompt_toolkit-3.0.47.tar.gz", hash = "sha256:1e1b29cb58080b1e69f207c893a1a7bf16d127a5c30c9d17a25a5d77792e5360"}, ] [[package]] @@ -833,6 +950,7 @@ name = "psycopg2" version = "2.9.9" requires_python = ">=3.7" summary = "psycopg2 - Python-PostgreSQL Database Adapter" +groups = ["default"] files = [ {file = "psycopg2-2.9.9-cp310-cp310-win32.whl", hash = "sha256:38a8dcc6856f569068b47de286b472b7c473ac7977243593a288ebce0dc89516"}, {file = "psycopg2-2.9.9-cp310-cp310-win_amd64.whl", hash = "sha256:426f9f29bde126913a20a96ff8ce7d73fd8a216cfb323b1f04da402d452853c3"}, @@ -848,6 +966,7 @@ name = "psycopg2-binary" version = "2.9.9" requires_python = ">=3.7" summary = "psycopg2 - Python-PostgreSQL Database Adapter" +groups = ["default"] files = [ {file = "psycopg2-binary-2.9.9.tar.gz", hash = "sha256:7f01846810177d829c7692f1f5ada8096762d9172af1b1a28d4ab5b77c923c1c"}, {file = "psycopg2_binary-2.9.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c2470da5418b76232f02a2fcd2229537bb2d5a7096674ce61859c3229f2eb202"}, @@ -892,6 +1011,8 @@ files = [ name = "ptyprocess" version = "0.7.0" summary = "Run a subprocess in a pseudo terminal" +groups = ["default"] +marker = "sys_platform != \"win32\"" files = [ {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, @@ -901,6 +1022,7 @@ files = [ name = "pure-eval" version = "0.2.2" summary = "Safely evaluate AST nodes without side effects" +groups = ["default"] files = [ {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, @@ -911,6 +1033,7 @@ name = "pyarrow" version = "16.1.0" requires_python = ">=3.8" summary = "Python library for Apache Arrow" +groups = ["default"] dependencies = [ "numpy>=1.16.6", ] @@ -944,6 +1067,7 @@ name = "pyasn1" version = "0.6.0" requires_python = ">=3.8" summary = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" +groups = ["default"] files = [ {file = "pyasn1-0.6.0-py2.py3-none-any.whl", hash = "sha256:cca4bb0f2df5504f02f6f8a775b6e416ff9b0b3b16f7ee80b5a3153d9b804473"}, {file = "pyasn1-0.6.0.tar.gz", hash = "sha256:3a35ab2c4b5ef98e17dfdec8ab074046fbda76e281c5a706ccd82328cfc8f64c"}, @@ -954,6 +1078,7 @@ name = "pycparser" version = "2.22" requires_python = ">=3.8" summary = "C parser in Python" +groups = ["default"] files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, @@ -964,6 +1089,7 @@ name = "pycryptodome" version = "3.20.0" requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" summary = "Cryptographic library for Python" +groups = ["default"] files = [ {file = "pycryptodome-3.20.0-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:ac1c7c0624a862f2e53438a15c9259d1655325fc2ec4392e66dc46cdae24d044"}, {file = "pycryptodome-3.20.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:76658f0d942051d12a9bd08ca1b6b34fd762a8ee4240984f7c06ddfb55eaf15a"}, @@ -993,6 +1119,7 @@ name = "pydantic" version = "2.5.2" requires_python = ">=3.7" summary = "Data validation using Python type hints" +groups = ["default"] dependencies = [ "annotated-types>=0.4.0", "pydantic-core==2.14.5", @@ -1008,6 +1135,7 @@ name = "pydantic-core" version = "2.14.5" requires_python = ">=3.7" summary = "" +groups = ["default"] dependencies = [ "typing-extensions!=4.7.0,>=4.6.0", ] @@ -1088,6 +1216,7 @@ name = "pydantic-settings" version = "2.1.0" requires_python = ">=3.8" summary = "Settings management using Pydantic" +groups = ["default"] dependencies = [ "pydantic>=2.3.0", "python-dotenv>=0.21.0", @@ -1102,6 +1231,7 @@ name = "pygments" version = "2.18.0" requires_python = ">=3.8" summary = "Pygments is a syntax highlighting package written in Python." +groups = ["default"] files = [ {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, @@ -1112,6 +1242,7 @@ name = "pyjwt" version = "2.8.0" requires_python = ">=3.7" summary = "JSON Web Token implementation in Python" +groups = ["default"] files = [ {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"}, {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, @@ -1122,6 +1253,7 @@ name = "python-dotenv" version = "1.0.0" requires_python = ">=3.8" summary = "Read key-value pairs from a .env file and set them as environment variables" +groups = ["default"] files = [ {file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"}, {file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"}, @@ -1131,6 +1263,7 @@ files = [ name = "python-jose" version = "3.3.0" summary = "JOSE implementation in Python" +groups = ["default"] dependencies = [ "ecdsa!=0.15", "pyasn1", @@ -1146,6 +1279,7 @@ name = "python-jose" version = "3.3.0" extras = ["cryptography"] summary = "JOSE implementation in Python" +groups = ["default"] dependencies = [ "cryptography>=3.4.0", "python-jose==3.3.0", @@ -1160,6 +1294,7 @@ name = "python-multipart" version = "0.0.9" requires_python = ">=3.8" summary = "A streaming multipart parser for Python" +groups = ["default"] files = [ {file = "python_multipart-0.0.9-py3-none-any.whl", hash = "sha256:97ca7b8ea7b05f977dc3849c3ba99d51689822fab725c3703af7c866a0c2b215"}, {file = "python_multipart-0.0.9.tar.gz", hash = "sha256:03f54688c663f1b7977105f021043b0793151e4cb1c1a9d4a11fc13d622c4026"}, @@ -1170,6 +1305,7 @@ name = "pyyaml" version = "6.0.1" requires_python = ">=3.6" summary = "YAML parser and emitter for Python" +groups = ["default"] files = [ {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, @@ -1202,6 +1338,7 @@ name = "requests" version = "2.32.3" requires_python = ">=3.8" summary = "Python HTTP for Humans." +groups = ["default"] dependencies = [ "certifi>=2017.4.17", "charset-normalizer<4,>=2", @@ -1218,6 +1355,7 @@ name = "requests-oauthlib" version = "2.0.0" requires_python = ">=3.4" summary = "OAuthlib authentication support for Requests." +groups = ["default"] dependencies = [ "oauthlib>=3.0.0", "requests>=2.0.0", @@ -1232,6 +1370,7 @@ name = "rsa" version = "4.9" requires_python = ">=3.6,<4" summary = "Pure-Python RSA implementation" +groups = ["default"] dependencies = [ "pyasn1>=0.1.3", ] @@ -1245,6 +1384,7 @@ name = "shapely" version = "2.0.2" requires_python = ">=3.7" summary = "Manipulation and analysis of geometric objects" +groups = ["default"] dependencies = [ "numpy>=1.14", ] @@ -1278,6 +1418,7 @@ name = "six" version = "1.16.0" requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" summary = "Python 2 and 3 compatibility utilities" +groups = ["default"] files = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, @@ -1288,6 +1429,7 @@ name = "sniffio" version = "1.3.1" requires_python = ">=3.7" summary = "Sniff out which async library your code is running under" +groups = ["default"] files = [ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, @@ -1298,6 +1440,7 @@ name = "sqlalchemy" version = "2.0.23" requires_python = ">=3.7" summary = "Database Abstraction Library" +groups = ["default"] dependencies = [ "greenlet!=0.4.17; platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\"", "typing-extensions>=4.2.0", @@ -1336,6 +1479,7 @@ name = "sqlalchemy-utils" version = "0.41.1" requires_python = ">=3.6" summary = "Various utility functions for SQLAlchemy." +groups = ["default"] dependencies = [ "SQLAlchemy>=1.3", ] @@ -1348,6 +1492,7 @@ files = [ name = "stack-data" version = "0.6.3" summary = "Extract data from python stack frames and tracebacks for informative displays" +groups = ["default"] dependencies = [ "asttokens>=2.1.0", "executing>=1.2.0", @@ -1363,6 +1508,7 @@ name = "starlette" version = "0.27.0" requires_python = ">=3.7" summary = "The little ASGI library that shines." +groups = ["default"] dependencies = [ "anyio<5,>=3.4.0", ] @@ -1376,6 +1522,7 @@ name = "traitlets" version = "5.14.3" requires_python = ">=3.8" summary = "Traitlets Python configuration system" +groups = ["default"] files = [ {file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"}, {file = "traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"}, @@ -1383,22 +1530,24 @@ files = [ [[package]] name = "typing-extensions" -version = "4.12.0" +version = "4.12.2" requires_python = ">=3.8" summary = "Backported and Experimental Type Hints for Python 3.8+" +groups = ["default"] files = [ - {file = "typing_extensions-4.12.0-py3-none-any.whl", hash = "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594"}, - {file = "typing_extensions-4.12.0.tar.gz", hash = "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8"}, + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] [[package]] name = "urllib3" -version = "2.2.1" +version = "2.2.2" requires_python = ">=3.8" summary = "HTTP library with thread-safe connection pooling, file post, and more." +groups = ["default"] files = [ - {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, - {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, + {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, + {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, ] [[package]] @@ -1406,6 +1555,7 @@ name = "uvicorn" version = "0.24.0" requires_python = ">=3.8" summary = "The lightning-fast ASGI server." +groups = ["default"] dependencies = [ "click>=7.0", "h11>=0.8", @@ -1420,6 +1570,7 @@ files = [ name = "wcwidth" version = "0.2.13" summary = "Measures the displayed width of unicode strings in a terminal" +groups = ["default"] files = [ {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, @@ -1430,6 +1581,7 @@ name = "werkzeug" version = "3.0.1" requires_python = ">=3.8" summary = "The comprehensive WSGI web application library." +groups = ["default"] dependencies = [ "MarkupSafe>=2.1.1", ] @@ -1443,6 +1595,8 @@ name = "win32-setctime" version = "1.1.0" requires_python = ">=3.5" summary = "A small Python utility to set file creation time on Windows" +groups = ["default"] +marker = "sys_platform == \"win32\"" files = [ {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"}, {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"}, diff --git a/src/backend/pyproject.toml b/src/backend/pyproject.toml index 4c6cc35b..19d72990 100644 --- a/src/backend/pyproject.toml +++ b/src/backend/pyproject.toml @@ -34,7 +34,10 @@ dependencies = [ "psycopg2-binary>=2.9.9", "requests-oauthlib>=2.0.0", "itsdangerous>=2.2.0", + "databases>=0.9.0", + "asyncpg>=0.29.0", "Jinja2>=3.1.4", + "numpy==1.26.4", ] requires-python = ">=3.10" license = {text = "GPL-3.0-only"}