From 4d664d1d7279fce915edbc6d84d38475e9c05fd3 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Thu, 17 Oct 2024 10:54:33 +0545 Subject: [PATCH 001/390] feat: update role coumn in use profilem, now role will be store in array --- src/backend/app/db/db_models.py | 3 +- .../app/migrations/versions/b36a13183a83_.py | 47 +++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/backend/app/migrations/versions/b36a13183a83_.py diff --git a/src/backend/app/db/db_models.py b/src/backend/app/db/db_models.py index 8a38d19f..e34d5424 100644 --- a/src/backend/app/db/db_models.py +++ b/src/backend/app/db/db_models.py @@ -277,7 +277,8 @@ class GroundControlPoint(Base): class DbUserProfile(Base): __tablename__ = "user_profile" user_id = cast(str, Column(String, ForeignKey("users.id"), primary_key=True)) - role = cast(UserRole, Column(Enum(UserRole), default=UserRole.DRONE_PILOT)) + role = cast(list, Column(ARRAY(Enum(UserRole)))) + # role = cast(UserRole, Column(Enum(UserRole), default=UserRole.DRONE_PILOT)) phone_number = cast(str, Column(String)) country = cast(str, Column(String)) city = cast(str, Column(String)) diff --git a/src/backend/app/migrations/versions/b36a13183a83_.py b/src/backend/app/migrations/versions/b36a13183a83_.py new file mode 100644 index 00000000..cc8fcb08 --- /dev/null +++ b/src/backend/app/migrations/versions/b36a13183a83_.py @@ -0,0 +1,47 @@ +from typing import Sequence, Union +from alembic import op +from app.models.enums import UserRole +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql +from sqlalchemy.sql import text + + +# revision identifiers, used by Alembic. +revision: str = "b36a13183a83" +down_revision: Union[str, None] = "5235ef4afa9c" +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + +def upgrade() -> None: + # Check if the enum type 'userrole' already exists + conn = op.get_bind() + result = conn.execute(text("SELECT 1 FROM pg_type WHERE typname = 'userrole';")).scalar() + + if not result: + # Create a new enum type for user roles if it doesn't exist + userrole_enum = sa.Enum(UserRole, name="userrole") + userrole_enum.create(op.get_bind()) + + # Change the column from a single enum value to an array of enums + # We need to cast each enum value to text and back to an array of enums + op.alter_column("user_profile", "role", + existing_type=sa.Enum(UserRole, name="userrole"), + type_=sa.ARRAY(postgresql.ENUM("PROJECT_CREATOR", "DRONE_PILOT", name="userrole")), + postgresql_using="ARRAY[role]::userrole[]", # Convert the single enum to an array + nullable=True) + +def downgrade() -> None: + # Change the column back from an array to a single enum value + op.alter_column("user_profile", "role", + existing_type=sa.ARRAY(postgresql.ENUM("PROJECT_CREATOR", "DRONE_PILOT", name="userrole")), + type_=sa.Enum(UserRole, name="userrole"), + postgresql_using="role[1]", + nullable=True) + + # Drop the enum type only if it exists + conn = op.get_bind() + result = conn.execute(text("SELECT 1 FROM pg_type WHERE typname = 'userrole';")).scalar() + + if result: + userrole_enum = sa.Enum(UserRole, name="userrole") + userrole_enum.drop(op.get_bind()) From b6852f2bf0ebe8f033928e54cf1b0a9544d8b348 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Thu, 17 Oct 2024 12:20:54 +0545 Subject: [PATCH 002/390] fix: fix role issues of user in profile update endpoint --- .../app/migrations/versions/b36a13183a83_.py | 40 +++++--- src/backend/app/users/user_schemas.py | 91 ++++++++++++++++++- 2 files changed, 115 insertions(+), 16 deletions(-) diff --git a/src/backend/app/migrations/versions/b36a13183a83_.py b/src/backend/app/migrations/versions/b36a13183a83_.py index cc8fcb08..78ce2cee 100644 --- a/src/backend/app/migrations/versions/b36a13183a83_.py +++ b/src/backend/app/migrations/versions/b36a13183a83_.py @@ -12,10 +12,13 @@ branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None + def upgrade() -> None: # Check if the enum type 'userrole' already exists conn = op.get_bind() - result = conn.execute(text("SELECT 1 FROM pg_type WHERE typname = 'userrole';")).scalar() + result = conn.execute( + text("SELECT 1 FROM pg_type WHERE typname = 'userrole';") + ).scalar() if not result: # Create a new enum type for user roles if it doesn't exist @@ -24,23 +27,36 @@ def upgrade() -> None: # Change the column from a single enum value to an array of enums # We need to cast each enum value to text and back to an array of enums - op.alter_column("user_profile", "role", - existing_type=sa.Enum(UserRole, name="userrole"), - type_=sa.ARRAY(postgresql.ENUM("PROJECT_CREATOR", "DRONE_PILOT", name="userrole")), - postgresql_using="ARRAY[role]::userrole[]", # Convert the single enum to an array - nullable=True) + op.alter_column( + "user_profile", + "role", + existing_type=sa.Enum(UserRole, name="userrole"), + type_=sa.ARRAY( + postgresql.ENUM("PROJECT_CREATOR", "DRONE_PILOT", name="userrole") + ), + postgresql_using="ARRAY[role]::userrole[]", # Convert the single enum to an array + nullable=True, + ) + def downgrade() -> None: # Change the column back from an array to a single enum value - op.alter_column("user_profile", "role", - existing_type=sa.ARRAY(postgresql.ENUM("PROJECT_CREATOR", "DRONE_PILOT", name="userrole")), - type_=sa.Enum(UserRole, name="userrole"), - postgresql_using="role[1]", - nullable=True) + op.alter_column( + "user_profile", + "role", + existing_type=sa.ARRAY( + postgresql.ENUM("PROJECT_CREATOR", "DRONE_PILOT", name="userrole") + ), + type_=sa.Enum(UserRole, name="userrole"), + postgresql_using="role[1]", + nullable=True, + ) # Drop the enum type only if it exists conn = op.get_bind() - result = conn.execute(text("SELECT 1 FROM pg_type WHERE typname = 'userrole';")).scalar() + result = conn.execute( + text("SELECT 1 FROM pg_type WHERE typname = 'userrole';") + ).scalar() if result: userrole_enum = sa.Enum(UserRole, name="userrole") diff --git a/src/backend/app/users/user_schemas.py b/src/backend/app/users/user_schemas.py index 0ff79814..a55d0bfd 100644 --- a/src/backend/app/users/user_schemas.py +++ b/src/backend/app/users/user_schemas.py @@ -2,7 +2,7 @@ from app.models.enums import HTTPStatus, State, UserRole from pydantic import BaseModel, EmailStr, ValidationInfo, Field from pydantic.functional_validators import field_validator -from typing import Optional +from typing import List, Optional from psycopg import Connection from psycopg.rows import class_row import psycopg @@ -95,20 +95,31 @@ class BaseUserProfile(BaseModel): drone_you_own: Optional[str] = None experience_years: Optional[int] = None certified_drone_operator: Optional[bool] = False - role: Optional[UserRole] = None + role: Optional[List[UserRole]] = None @field_validator("role", mode="after") @classmethod def integer_role_to_string(cls, value: UserRole): + if isinstance(value, list): + value = [str(role.name) for role in value] + if isinstance(value, int): value = UserRole(value) - return str(value.name) + + unique_roles = set(value) + value = list(unique_roles) + return value @field_validator("role", mode="before") @classmethod def srting_role_to_integer(cls, value: UserRole) -> str: if isinstance(value, str): - value = UserRole[value].value + role_list = value.strip("{}").split(",") + value = [ + UserRole[role.strip()].value + for role in role_list + if role.strip() in UserRole.__members__ + ] return value @@ -130,6 +141,26 @@ async def update(db: Connection, user_id: int, profile_update: UserProfileIn): model_dump = profile_update.model_dump( exclude_none=True, exclude=["password", "old_password"] ) + + # If there are new roles, update the existing roles + if "role" in model_dump and model_dump["role"] is not None: + new_roles = model_dump["role"] + + # Create a query to update roles + role_update_query = """ + UPDATE user_profile + SET role = ( + SELECT ARRAY( + SELECT DISTINCT unnest(array_cat(role, %s)) + ) + ) + WHERE user_id = %s; + """ + + async with db.cursor() as cur: + await cur.execute(role_update_query, (new_roles, user_id)) + + # Prepare the columns and placeholders for the main update columns = ", ".join(model_dump.keys()) value_placeholders = ", ".join(f"%({key})s" for key in model_dump.keys()) sql = f""" @@ -169,6 +200,58 @@ async def update(db: Connection, user_id: int, profile_update: UserProfileIn): ) return True + # class DbUserProfile(BaseUserProfile): + # """UserProfile model for interacting with the user_profile table.""" + + # user_id: int + + # @staticmethod + # async def update(db: Connection, user_id: int, profile_update: UserProfileIn): + # """Update or insert a user profile.""" + + # # Prepare data for insert or update + # model_dump = profile_update.model_dump( + # exclude_none=True, exclude=["password", "old_password"] + # ) + # columns = ", ".join(model_dump.keys()) + # value_placeholders = ", ".join(f"%({key})s" for key in model_dump.keys()) + # sql = f""" + # INSERT INTO user_profile ( + # user_id, {columns} + # ) + # VALUES ( + # %(user_id)s, {value_placeholders} + # ) + # ON CONFLICT (user_id) + # DO UPDATE SET + # {', '.join(f"{key} = EXCLUDED.{key}" for key in model_dump.keys())}; + # """ + + # # Prepare password update query if a new password is provided + # password_update_query = """ + # UPDATE users + # SET password = %(password)s + # WHERE id = %(user_id)s; + # """ + + # model_dump["user_id"] = user_id + + # async with db.cursor() as cur: + # await cur.execute(sql, model_dump) + + # if profile_update.password: + # # Update password if provided + # await cur.execute( + # password_update_query, + # { + # "password": user_logic.get_password_hash( + # profile_update.password + # ), + # "user_id": user_id, + # }, + # ) + # return True + async def get_userprofile_by_userid(db: Connection, user_id: str): """Fetch the user profile by user ID.""" query = """ From 505aeb70616c56dedb02c6019921618f9f382206 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Thu, 17 Oct 2024 12:56:03 +0545 Subject: [PATCH 003/390] feat: added new endpoints for project centroids --- src/backend/app/projects/project_logic.py | 14 ++++++++++++++ src/backend/app/projects/project_routes.py | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/backend/app/projects/project_logic.py b/src/backend/app/projects/project_logic.py index f9a91bf7..1d8ba785 100644 --- a/src/backend/app/projects/project_logic.py +++ b/src/backend/app/projects/project_logic.py @@ -19,6 +19,20 @@ from app.projects.image_processing import DroneImageProcessor from app.projects import project_schemas from minio import S3Error +from psycopg.rows import dict_row + + +async def get_centroids(db: Connection): + try: + async with db.cursor(row_factory=dict_row) as cur: + await cur.execute( + """SELECT ST_AsGeoJSON(centroid)::jsonb AS centroid FROM projects""" + ) + centroids = await cur.fetchall() + + return centroids + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) async def upload_file_to_s3( diff --git a/src/backend/app/projects/project_routes.py b/src/backend/app/projects/project_routes.py index 9bbbf841..2aab3752 100644 --- a/src/backend/app/projects/project_routes.py +++ b/src/backend/app/projects/project_routes.py @@ -42,6 +42,26 @@ ) +@router.get("/centroids", tags=["Projects"]) +async def read_project_centroids( + db: Annotated[Connection, Depends(database.get_db)], + user_data: Annotated[AuthUser, Depends(login_required)] +): + """ + Get all project centroids. + """ + try: + centroids = await project_logic.get_centroids( + db, + ) + if not centroids: + return [] + + return centroids + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + + @router.get("/{project_id}/download-boundaries", tags=["Projects"]) async def download_boundaries( project_id: Annotated[ From 73c68b426cbacf9122785ca1ee4be207d6ef4bd7 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Thu, 17 Oct 2024 13:37:51 +0545 Subject: [PATCH 004/390] feat: update status & ongoing task on project endpoint --- src/backend/app/projects/project_logic.py | 24 +++++++++++++++--- src/backend/app/projects/project_routes.py | 6 +++-- src/backend/app/projects/project_schemas.py | 27 +++++++++++++++++++++ 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/backend/app/projects/project_logic.py b/src/backend/app/projects/project_logic.py index 1d8ba785..30b74fdd 100644 --- a/src/backend/app/projects/project_logic.py +++ b/src/backend/app/projects/project_logic.py @@ -25,11 +25,29 @@ async def get_centroids(db: Connection): try: async with db.cursor(row_factory=dict_row) as cur: - await cur.execute( - """SELECT ST_AsGeoJSON(centroid)::jsonb AS centroid FROM projects""" - ) + await cur.execute(""" + SELECT + p.id, + p.slug, + p.name, + ST_AsGeoJSON(p.centroid)::jsonb AS centroid, + COUNT(t.id) AS total_task_count, + COUNT(CASE WHEN te.state IN ('LOCKED_FOR_MAPPING', 'REQUEST_FOR_MAPPING', 'IMAGE_UPLOADED', 'UNFLYABLE_TASK') THEN 1 END) AS ongoing_task_count, + COUNT(CASE WHEN te.state = 'IMAGE_PROCESSED' THEN 1 END) AS completed_task_count + FROM + projects p + LEFT JOIN + tasks t ON p.id = t.project_id + LEFT JOIN + task_events te ON t.id = te.task_id + GROUP BY + p.id, p.slug, p.name, p.centroid; + """) centroids = await cur.fetchall() + if not centroids: + raise HTTPException(status_code=404, detail="No centroids found.") + return centroids except Exception as e: raise HTTPException(status_code=500, detail=str(e)) diff --git a/src/backend/app/projects/project_routes.py b/src/backend/app/projects/project_routes.py index 2aab3752..f4ca8e06 100644 --- a/src/backend/app/projects/project_routes.py +++ b/src/backend/app/projects/project_routes.py @@ -42,10 +42,12 @@ ) -@router.get("/centroids", tags=["Projects"]) +@router.get( + "/centroids", tags=["Projects"], response_model=list[project_schemas.CentroidOut] +) async def read_project_centroids( db: Annotated[Connection, Depends(database.get_db)], - user_data: Annotated[AuthUser, Depends(login_required)] + # user_data: Annotated[AuthUser, Depends(login_required)], ): """ Get all project centroids. diff --git a/src/backend/app/projects/project_schemas.py b/src/backend/app/projects/project_schemas.py index 42986800..ce2e51f7 100644 --- a/src/backend/app/projects/project_schemas.py +++ b/src/backend/app/projects/project_schemas.py @@ -26,6 +26,33 @@ from app.s3 import get_presigned_url +class CentroidOut(BaseModel): + id: uuid.UUID + slug: str + name: str + centroid: dict + total_task_count: int + ongoing_task_count: int + completed_task_count: int + status: str = None + + @model_validator(mode="after") + def calculate_status(cls, values): + """Set the project status based on task counts.""" + ongoing_task_count = values.ongoing_task_count + completed_task_count = values.completed_task_count + total_task_count = values.total_task_count + + if completed_task_count == 0 and ongoing_task_count == 0: + values.status = "not-started" + elif completed_task_count == total_task_count: + values.status = "completed" + else: + values.status = "ongoing" + + return values + + class AssetsInfo(BaseModel): project_id: str task_id: str From b8bef9f89af20a82e6a9c6db5471395e189873b1 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Thu, 17 Oct 2024 13:40:21 +0545 Subject: [PATCH 005/390] fix: remove unused code from update profile --- src/backend/app/db/db_models.py | 1 - src/backend/app/users/user_schemas.py | 52 --------------------------- 2 files changed, 53 deletions(-) diff --git a/src/backend/app/db/db_models.py b/src/backend/app/db/db_models.py index e34d5424..7704ceef 100644 --- a/src/backend/app/db/db_models.py +++ b/src/backend/app/db/db_models.py @@ -278,7 +278,6 @@ class DbUserProfile(Base): __tablename__ = "user_profile" user_id = cast(str, Column(String, ForeignKey("users.id"), primary_key=True)) role = cast(list, Column(ARRAY(Enum(UserRole)))) - # role = cast(UserRole, Column(Enum(UserRole), default=UserRole.DRONE_PILOT)) phone_number = cast(str, Column(String)) country = cast(str, Column(String)) city = cast(str, Column(String)) diff --git a/src/backend/app/users/user_schemas.py b/src/backend/app/users/user_schemas.py index a55d0bfd..87d4880c 100644 --- a/src/backend/app/users/user_schemas.py +++ b/src/backend/app/users/user_schemas.py @@ -200,58 +200,6 @@ async def update(db: Connection, user_id: int, profile_update: UserProfileIn): ) return True - # class DbUserProfile(BaseUserProfile): - # """UserProfile model for interacting with the user_profile table.""" - - # user_id: int - - # @staticmethod - # async def update(db: Connection, user_id: int, profile_update: UserProfileIn): - # """Update or insert a user profile.""" - - # # Prepare data for insert or update - # model_dump = profile_update.model_dump( - # exclude_none=True, exclude=["password", "old_password"] - # ) - # columns = ", ".join(model_dump.keys()) - # value_placeholders = ", ".join(f"%({key})s" for key in model_dump.keys()) - # sql = f""" - # INSERT INTO user_profile ( - # user_id, {columns} - # ) - # VALUES ( - # %(user_id)s, {value_placeholders} - # ) - # ON CONFLICT (user_id) - # DO UPDATE SET - # {', '.join(f"{key} = EXCLUDED.{key}" for key in model_dump.keys())}; - # """ - - # # Prepare password update query if a new password is provided - # password_update_query = """ - # UPDATE users - # SET password = %(password)s - # WHERE id = %(user_id)s; - # """ - - # model_dump["user_id"] = user_id - - # async with db.cursor() as cur: - # await cur.execute(sql, model_dump) - - # if profile_update.password: - # # Update password if provided - # await cur.execute( - # password_update_query, - # { - # "password": user_logic.get_password_hash( - # profile_update.password - # ), - # "user_id": user_id, - # }, - # ) - # return True - async def get_userprofile_by_userid(db: Connection, user_id: str): """Fetch the user profile by user ID.""" query = """ From dc5b9413bfe3c79e07472f56387e006bbe8908de Mon Sep 17 00:00:00 2001 From: Sujit Date: Thu, 17 Oct 2024 15:21:17 +0545 Subject: [PATCH 006/390] feat: update role text on signin/signup --- .../src/components/LandingPage/SignInOverlay/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/components/LandingPage/SignInOverlay/index.tsx b/src/frontend/src/components/LandingPage/SignInOverlay/index.tsx index 9bb4b529..2b22ce23 100644 --- a/src/frontend/src/components/LandingPage/SignInOverlay/index.tsx +++ b/src/frontend/src/components/LandingPage/SignInOverlay/index.tsx @@ -46,7 +46,7 @@ export default function SignInOverlay() { className="naxatw-whitespace-nowrap !naxatw-bg-landing-red" rightIcon="east" onClick={() => { - localStorage.setItem('signedInAs', 'Project Creator'); + localStorage.setItem('signedInAs', 'PROJECT_CREATOR'); if (isAuthenticated()) { navigate('/projects'); } else { @@ -67,7 +67,7 @@ export default function SignInOverlay() { className="naxatw-whitespace-nowrap !naxatw-bg-landing-red" rightIcon="east" onClick={() => { - localStorage.setItem('signedInAs', 'Drone Operator'); + localStorage.setItem('signedInAs', 'DRONE_OPERATOR'); if (isAuthenticated()) { navigate('/projects'); } else { From 5984a3c92f68996976d47c562cbfabaa570dee87 Mon Sep 17 00:00:00 2001 From: Sujit Date: Thu, 17 Oct 2024 15:25:38 +0545 Subject: [PATCH 007/390] feat: redirect to complete profile page if the current signin role is not includes in role list --- .../src/components/common/UserProfile/index.tsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/frontend/src/components/common/UserProfile/index.tsx b/src/frontend/src/components/common/UserProfile/index.tsx index b64f406b..a8da0ce5 100644 --- a/src/frontend/src/components/common/UserProfile/index.tsx +++ b/src/frontend/src/components/common/UserProfile/index.tsx @@ -15,12 +15,21 @@ export default function UserProfile() { const { data: userDetails, isFetching }: Record = useGetUserDetailsQuery(); + const userProfile = getLocalStorageValue('userprofile'); + const role = localStorage.getItem('signedInAs'); useEffect(() => { - if (userDetails?.has_user_profile || isFetching) return; - if (!userDetails?.has_user_profile) navigate('/complete-profile'); - }, [userDetails?.has_user_profile, navigate, isFetching]); + if (userDetails?.role?.includes(role) || isFetching) return; + if (!userDetails?.has_user_profile || !userDetails?.role?.includes(role)) + navigate('/complete-profile'); + }, [ + userDetails?.has_user_profile, + userDetails?.role, + role, + navigate, + isFetching, + ]); const settingOptions = [ { From d23227447b2e0b5e639292359e91c28445aa0126 Mon Sep 17 00:00:00 2001 From: Sujit Date: Thu, 17 Oct 2024 15:32:57 +0545 Subject: [PATCH 008/390] feat: update text `Drone Oprerator` to `DRONE_OPERATOR` and `Project Creator` to `PROJECT_CREATOR` --- .../src/components/Projects/ProjectsHeader/index.tsx | 4 ++-- .../src/components/Authentication/Login/index.tsx | 2 +- src/frontend/src/views/CompleteUserProfile/index.tsx | 6 +++--- src/frontend/src/views/Dashboard/index.tsx | 6 +++--- src/frontend/src/views/UpdateUserProfile/index.tsx | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/frontend/src/components/Projects/ProjectsHeader/index.tsx b/src/frontend/src/components/Projects/ProjectsHeader/index.tsx index c4761e15..c997b02c 100644 --- a/src/frontend/src/components/Projects/ProjectsHeader/index.tsx +++ b/src/frontend/src/components/Projects/ProjectsHeader/index.tsx @@ -13,7 +13,7 @@ import useDebounceListener from '@Hooks/useDebouncedListener'; export default function ProjectsHeader() { const dispatch = useTypedDispatch(); const navigate = useNavigate(); - const signedInAs = localStorage.getItem('signedInAs') || 'Project Creator'; + const signedInAs = localStorage.getItem('signedInAs') || 'PROJECT_CREATOR'; const showMap = useTypedSelector(state => state.common.showMap); const projectsFilterByOwner = useTypedSelector( state => state.createproject.ProjectsFilterByOwner, @@ -75,7 +75,7 @@ export default function ProjectsHeader() { /> - {signedInAs === 'Project Creator' && ( + {signedInAs === 'PROJECT_CREATOR' && ( )} + {taskAssetsInformation?.state === 'IMAGE_PROCESSING_FAILED' && ( +
+ +
+ )} + {taskAssetsInformation?.state === 'IMAGE_PROCESSING_FAILED' && ( +
+ +
+ )} )} From d8ce4fe434e87c94e3d14de3a63f7d2685d33708 Mon Sep 17 00:00:00 2001 From: Sujit Date: Tue, 22 Oct 2024 16:45:27 +0545 Subject: [PATCH 060/390] feat: upload image component UI and functionality --- .../DescriptionSection/UploadsBox/index.tsx | 41 ++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/frontend/src/components/DroneOperatorTask/DescriptionSection/UploadsBox/index.tsx b/src/frontend/src/components/DroneOperatorTask/DescriptionSection/UploadsBox/index.tsx index 4df0ea89..c88c0ae0 100644 --- a/src/frontend/src/components/DroneOperatorTask/DescriptionSection/UploadsBox/index.tsx +++ b/src/frontend/src/components/DroneOperatorTask/DescriptionSection/UploadsBox/index.tsx @@ -6,7 +6,7 @@ import { toggleModal } from '@Store/actions/common'; import { setFiles } from '@Store/actions/droneOperatorTask'; import { useTypedDispatch, useTypedSelector } from '@Store/hooks'; -const UploadsBox = () => { +const UploadsBox = ({ label = 'Upload Raw Image' }: { label?: string }) => { const dispatch = useTypedDispatch(); const files = useTypedSelector(state => state.droneOperatorTask.files); const handleFileChange = (event: any) => { @@ -22,17 +22,38 @@ const UploadsBox = () => {

- Upload Raw Image + {label}

- + + {files.length > 0 && (
)} - {taskAssetsInformation?.state === 'IMAGE_PROCESSING_FAILED' && ( -
- -
- )} + {/* {taskAssetsInformation?.state === 'IMAGE_PROCESSING_FAILED' && ( */} +
+ +
+ {/* )} */} {taskAssetsInformation?.state === 'IMAGE_PROCESSING_FAILED' && (
From 3d9b278f6b86f4bc66ad8f7c61cd2323693181b8 Mon Sep 17 00:00:00 2001 From: Sujit Date: Tue, 22 Oct 2024 17:00:16 +0545 Subject: [PATCH 064/390] fix(task-description): make rerun button visible only on imnage process failure --- .../DescriptionBox/index.tsx | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx b/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx index c20e3268..ef2f4157 100644 --- a/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx +++ b/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx @@ -197,19 +197,19 @@ const DescriptionBox = () => {
)} - {/* {taskAssetsInformation?.state === 'IMAGE_PROCESSING_FAILED' && ( */} -
- -
- {/* )} */} + {taskAssetsInformation?.state === 'IMAGE_PROCESSING_FAILED' && ( +
+ +
+ )} {taskAssetsInformation?.state === 'IMAGE_PROCESSING_FAILED' && (
From 4f154d82665f3da8965806ad821b04f37bba7d76 Mon Sep 17 00:00:00 2001 From: Sujit Date: Tue, 22 Oct 2024 17:00:16 +0545 Subject: [PATCH 065/390] fix(task-description): make rerun button visible only on image process failure --- .../DescriptionBox/index.tsx | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx b/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx index c20e3268..ef2f4157 100644 --- a/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx +++ b/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx @@ -197,19 +197,19 @@ const DescriptionBox = () => {
)} - {/* {taskAssetsInformation?.state === 'IMAGE_PROCESSING_FAILED' && ( */} -
- -
- {/* )} */} + {taskAssetsInformation?.state === 'IMAGE_PROCESSING_FAILED' && ( +
+ +
+ )} {taskAssetsInformation?.state === 'IMAGE_PROCESSING_FAILED' && (
From d72a76f543f091f752538fc615c82e2d1fcee9b8 Mon Sep 17 00:00:00 2001 From: Sujit Date: Tue, 22 Oct 2024 17:24:28 +0545 Subject: [PATCH 066/390] feat: create utill function to format the string with the help of regex remove underscore make first character uppercase and rest of the character lowercase --- src/frontend/src/utils/index.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/frontend/src/utils/index.ts b/src/frontend/src/utils/index.ts index a413c1a8..b55fc37a 100644 --- a/src/frontend/src/utils/index.ts +++ b/src/frontend/src/utils/index.ts @@ -76,3 +76,12 @@ export const getFrontOverlap = (agl: number, forwardSpacing: number) => { const frontOverlap = (frontOverlapDistance * 100) / frontPhotoHeight; return frontOverlap.toFixed(2); }; + +// remove underscore and capitalize the word +export const formatString = (value: string) => { + if (!value) return ''; + return value + .replace(/_/g, ' ') + .toLowerCase() + .replace(/^\w/, char => char.toUpperCase()); +}; From 2ba818646c8506dc91373d9fd2afe438e1076a7e Mon Sep 17 00:00:00 2001 From: Sujit Date: Tue, 22 Oct 2024 17:26:50 +0545 Subject: [PATCH 067/390] feat: convert the task state into readable text --- .../src/components/Dashboard/TaskLogs/TaskLogsTable.tsx | 3 ++- .../DescriptionSection/DescriptionBox/index.tsx | 6 +++++- .../IndividualProject/Contributions/TableSection/index.tsx | 3 ++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/frontend/src/components/Dashboard/TaskLogs/TaskLogsTable.tsx b/src/frontend/src/components/Dashboard/TaskLogs/TaskLogsTable.tsx index d54574f2..a46a31f2 100644 --- a/src/frontend/src/components/Dashboard/TaskLogs/TaskLogsTable.tsx +++ b/src/frontend/src/components/Dashboard/TaskLogs/TaskLogsTable.tsx @@ -1,3 +1,4 @@ +import { formatString } from '@Utils/index'; import { format } from 'date-fns'; import { useNavigate } from 'react-router-dom'; @@ -47,7 +48,7 @@ const TaskLogsTable = ({ data: taskList }: ITaskLogsTableProps) => { {format(new Date(task.created_at), 'yyyy-MM-dd')} - {task.state} + {formatString(task.state)}
{ name: 'Orthophoto available', value: taskAssetsInformation?.assets_url ? 'Yes' : 'No', }, - { name: 'Image Status', value: taskAssetsInformation?.state }, + { + name: 'Image Status', + value: formatString(taskAssetsInformation?.state), + }, ]} /> diff --git a/src/frontend/src/components/IndividualProject/Contributions/TableSection/index.tsx b/src/frontend/src/components/IndividualProject/Contributions/TableSection/index.tsx index f0834341..9f09fb73 100644 --- a/src/frontend/src/components/IndividualProject/Contributions/TableSection/index.tsx +++ b/src/frontend/src/components/IndividualProject/Contributions/TableSection/index.tsx @@ -2,6 +2,7 @@ import { useGetAllAssetsUrlQuery } from '@Api/projects'; import DataTable from '@Components/common/DataTable'; import Icon from '@Components/common/Icon'; import { useTypedSelector } from '@Store/hooks'; +import { formatString } from '@Utils/index'; import { useMemo } from 'react'; import { useParams } from 'react-router-dom'; import { toast } from 'react-toastify'; @@ -79,7 +80,7 @@ export default function TableSection({ isFetching }: { isFetching: boolean }) { { user: curr?.name || '-', task_mapped: `Task# ${curr?.project_task_index}`, - task_state: curr?.state, + task_state: formatString(curr?.state), assets_url: selectedAssetsDetails?.assets_url, image_count: selectedAssetsDetails?.image_count, }, From 18a832e0f0d7e8ec14e61eadcef49d044f360271 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Thu, 24 Oct 2024 11:47:15 +0545 Subject: [PATCH 068/390] feat: added the get orthophoto tile endpoints --- src/backend/app/projects/image_processing.py | 26 ++ src/backend/app/projects/project_logic.py | 1 + src/backend/app/projects/project_routes.py | 43 +++- src/backend/app/s3.py | 18 ++ src/backend/pdm.lock | 258 ++++++++++++++++++- src/backend/pyproject.toml | 1 + 6 files changed, 345 insertions(+), 2 deletions(-) diff --git a/src/backend/app/projects/image_processing.py b/src/backend/app/projects/image_processing.py index 018b05dc..57725ae2 100644 --- a/src/backend/app/projects/image_processing.py +++ b/src/backend/app/projects/image_processing.py @@ -13,6 +13,7 @@ from psycopg import Connection from asgiref.sync import async_to_sync from app.config import settings +import zipfile class DroneImageProcessor: @@ -235,6 +236,31 @@ async def download_and_upload_assets_from_odm_to_s3( log.info(f"Assets for task {task_id} successfully uploaded to S3.") + # Extract the zip file to find the orthophoto + with zipfile.ZipFile(assets_path, "r") as zip_ref: + zip_ref.extractall(output_file_path) + + # Locate the orthophoto (odm_orthophoto.tif) + orthophoto_path = os.path.join( + output_file_path, "odm_orthophoto", "odm_orthophoto.tif" + ) + if not os.path.exists(orthophoto_path): + log.error(f"Orthophoto file not found at {orthophoto_path}") + raise FileNotFoundError(f"Orthophoto not found in {output_file_path}") + + log.info(f"Orthophoto found at {orthophoto_path}") + + # Upload the orthophoto to S3 + s3_ortho_path = ( + f"projects/{dtm_project_id}/{dtm_task_id}/orthophoto/odm_orthophoto.tif" + ) + log.info(f"Uploading orthophoto to S3 path: {s3_ortho_path}") + add_file_to_bucket(settings.S3_BUCKET_NAME, orthophoto_path, s3_ortho_path) + + log.info( + f"Orthophoto for task {task_id} successfully uploaded to S3 at {s3_ortho_path}" + ) + # Update background task status to COMPLETED await task_logic.update_task_state( db, diff --git a/src/backend/app/projects/project_logic.py b/src/backend/app/projects/project_logic.py index 30b74fdd..2dcb2c3d 100644 --- a/src/backend/app/projects/project_logic.py +++ b/src/backend/app/projects/project_logic.py @@ -209,6 +209,7 @@ def process_drone_images( options = [ {"name": "dsm", "value": True}, {"name": "orthophoto-resolution", "value": 5}, + {"name": "cog", "value": True}, ] webhook_url = f"{settings.BACKEND_URL}/api/projects/odm/webhook/{user_id}/{project_id}/{task_id}/" diff --git a/src/backend/app/projects/project_routes.py b/src/backend/app/projects/project_routes.py index bfed3700..c670ee7b 100644 --- a/src/backend/app/projects/project_routes.py +++ b/src/backend/app/projects/project_routes.py @@ -27,13 +27,15 @@ from app.projects import project_schemas, project_deps, project_logic, image_processing from app.db import database from app.models.enums import HTTPStatus, State -from app.s3 import s3_client +from app.s3 import get_cog_path, s3_client from app.config import settings from app.users.user_deps import login_required from app.users.user_schemas import AuthUser from app.tasks import task_schemas from app.utils import geojson_to_kml, timestamp from app.users import user_schemas +from rio_tiler.io import Reader +from rio_tiler.errors import TileOutsideBounds router = APIRouter( @@ -524,3 +526,42 @@ async def odm_webhook( log.info(f"Task ID: {task_id}, Status: Webhook received") return {"message": "Webhook received", "task_id": task_id} + + +@router.get( + "/orthophoto/{z}/{x}/{y}.png", + tags=["Image Processing"], +) +async def get_orthophoto_tile( + user_data: Annotated[AuthUser, Depends(login_required)], + project_id: str, + task_id: str, + z: int, + x: int, + y: int, +): + """ + Endpoint to serve COG tiles as PNG images. + + :param project_id: ID of the project. + :param task_id: ID of the task. + :param z: Zoom level. + :param x: Tile X coordinate. + :param y: Tile Y coordinate. + :return: PNG image tile. + """ + try: + cog_path = get_cog_path("dtm-data", project_id, task_id) + with Reader(cog_path) as tiff: + try: + img = tiff.tile(int(x), int(y), int(z), tilesize=256, expression=None) + tile = img.render() + return Response(content=tile, media_type="image/png") + + except TileOutsideBounds: + raise HTTPException( + status_code=400, detail="Tile is outside the bounds of the image." + ) + + except Exception as e: + raise HTTPException(status_code=500, detail=f"Error generating tile: {str(e)}") diff --git a/src/backend/app/s3.py b/src/backend/app/s3.py index fb036633..63aabe97 100644 --- a/src/backend/app/s3.py +++ b/src/backend/app/s3.py @@ -213,3 +213,21 @@ def get_object_metadata(bucket_name: str, object_name: str): """ client = s3_client() return client.stat_object(bucket_name, object_name) + + +def get_cog_path(bucket_name: str, project_id: str, task_id: str): + """Generate the presigned URL for a COG file in an S3 bucket. + + Args: + bucket_name (str): The name of the S3 bucket. + project_id (str): The unique project identifier. + orthophoto_name (str): The name of the COG file. + + Returns: + str: The presigned URL to access the COG file. + """ + # Construct the S3 path for the COG file + s3_path = f"projects/{project_id}/{task_id}/orthophoto/odm_orthophoto.tif" + + # Get the presigned URL + return get_presigned_url(bucket_name, s3_path) diff --git a/src/backend/pdm.lock b/src/backend/pdm.lock index ecf946b8..1e47dd04 100644 --- a/src/backend/pdm.lock +++ b/src/backend/pdm.lock @@ -5,11 +5,21 @@ groups = ["default"] strategy = ["cross_platform"] lock_version = "4.5.0" -content_hash = "sha256:5af1cd91bffbaffb22f9affb9a5dea337d37697f4a6b024b7ace22cd9c73c6a2" +content_hash = "sha256:9f4782e0a7e1d39c893cf6d319a5d68362566cfdc4baccaf56d51f8254da0afb" [[metadata.targets]] requires_python = ">=3.11" +[[package]] +name = "affine" +version = "2.4.0" +requires_python = ">=3.7" +summary = "Matrices describing affine transformation of the plane" +files = [ + {file = "affine-2.4.0-py3-none-any.whl", hash = "sha256:8a3df80e2b2378aef598a83c1392efd47967afec4242021a0b06b4c7cbc61a92"}, + {file = "affine-2.4.0.tar.gz", hash = "sha256:a24d818d6a836c131976d22f8c27b8d3ca32d0af64c1d8d29deb7bafa4da1eea"}, +] + [[package]] name = "aiosmtplib" version = "3.0.2" @@ -115,6 +125,19 @@ files = [ {file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"}, ] +[[package]] +name = "attrs" +version = "24.2.0" +requires_python = ">=3.7" +summary = "Classes Without Boilerplate" +dependencies = [ + "importlib-metadata; python_version < \"3.8\"", +] +files = [ + {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, + {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, +] + [[package]] name = "bcrypt" version = "4.2.0" @@ -146,6 +169,16 @@ files = [ {file = "bcrypt-4.2.0.tar.gz", hash = "sha256:cf69eaf5185fd58f268f805b505ce31f9b9fc2d64b376642164e9244540c1221"}, ] +[[package]] +name = "cachetools" +version = "5.5.0" +requires_python = ">=3.7" +summary = "Extensible memoizing collections and decorators" +files = [ + {file = "cachetools-5.5.0-py3-none-any.whl", hash = "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292"}, + {file = "cachetools-5.5.0.tar.gz", hash = "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a"}, +] + [[package]] name = "certifi" version = "2024.8.30" @@ -271,6 +304,55 @@ files = [ {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, ] +[[package]] +name = "click-plugins" +version = "1.1.1" +summary = "An extension module for click to enable registering CLI commands via setuptools entry-points." +dependencies = [ + "click>=4.0", +] +files = [ + {file = "click-plugins-1.1.1.tar.gz", hash = "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b"}, + {file = "click_plugins-1.1.1-py2.py3-none-any.whl", hash = "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8"}, +] + +[[package]] +name = "cligj" +version = "0.7.2" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, <4" +summary = "Click params for commmand line interfaces to GeoJSON" +dependencies = [ + "click>=4.0", +] +files = [ + {file = "cligj-0.7.2-py3-none-any.whl", hash = "sha256:c1ca117dbce1fe20a5809dc96f01e1c2840f6dcc939b3ddbb1111bf330ba82df"}, + {file = "cligj-0.7.2.tar.gz", hash = "sha256:a4bc13d623356b373c2c27c53dbd9c68cae5d526270bfa71f6c6fa69669c6b27"}, +] + +[[package]] +name = "color-operations" +version = "0.1.6" +requires_python = ">=3.8" +summary = "Apply basic color-oriented image operations." +dependencies = [ + "numpy", +] +files = [ + {file = "color_operations-0.1.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:65662664bb1d39e4d48a16ccd010e4fd2281a5abb7102ebf1d65245319ee1268"}, + {file = "color_operations-0.1.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6faaa11e03fa88cdf3564a6abaadd02068c7f88df968cefa3bd33d1a1e30d6c2"}, + {file = "color_operations-0.1.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fbe49f8b91ed0c93dd1c5ec4baa144fcfe6a70ecaa81d9ca8c8ae2ad84dc560e"}, + {file = "color_operations-0.1.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3770e4e7bd0a972a65c5df313d5e32532db42b2f10898c417f769de93a7ba167"}, + {file = "color_operations-0.1.6-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6d499de4d820183e9a0599b6e9ad445b7bc84c50c9162e7c3ba05660c34a668"}, + {file = "color_operations-0.1.6-cp311-cp311-win_amd64.whl", hash = "sha256:5c6d35dc7c194595b1391e0ccc2e38cbd7cb87be37dd27ed49a058bb7c1a5442"}, + {file = "color_operations-0.1.6-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:906316d4e67d057496d4547a8050f1c555c49d712e0f4f79908ee5da8ca7aef3"}, + {file = "color_operations-0.1.6-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e6fce57bcda78a871b58b30df05b478c4b2da9736ef500554bb1c9c41e02aca2"}, + {file = "color_operations-0.1.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c0d3fb1085d83f0082a223901a91325a68b8d03b10ed9d40881d4489dcc641f0"}, + {file = "color_operations-0.1.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:715672ee6d827d4b068f7558f9e473de54eafced3c9a195641b0cf39d9aea700"}, + {file = "color_operations-0.1.6-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59b6fea23da0d19afc15bb56c4707275d5ac6c7fd27936c5c64fcdf628c82a53"}, + {file = "color_operations-0.1.6-cp312-cp312-win_amd64.whl", hash = "sha256:375226cdc52b8b3fe576efb47e0fb4b3dc2c9a8ecbb82c208e86df7153a76882"}, + {file = "color_operations-0.1.6.tar.gz", hash = "sha256:9b5ff7409d189b8254a3524fc78202e2db4021be973592875d61722abe027ec6"}, +] + [[package]] name = "colorama" version = "0.4.6" @@ -437,6 +519,37 @@ files = [ {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, ] +[[package]] +name = "httpcore" +version = "1.0.6" +requires_python = ">=3.8" +summary = "A minimal low-level HTTP client." +dependencies = [ + "certifi", + "h11<0.15,>=0.13", +] +files = [ + {file = "httpcore-1.0.6-py3-none-any.whl", hash = "sha256:27b59625743b85577a8c0e10e55b50b5368a4f2cfe8cc7bcfa9cf00829c2682f"}, + {file = "httpcore-1.0.6.tar.gz", hash = "sha256:73f6dbd6eb8c21bbf7ef8efad555481853f5f6acdeaff1edb0694289269ee17f"}, +] + +[[package]] +name = "httpx" +version = "0.27.2" +requires_python = ">=3.8" +summary = "The next generation HTTP client." +dependencies = [ + "anyio", + "certifi", + "httpcore==1.*", + "idna", + "sniffio", +] +files = [ + {file = "httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0"}, + {file = "httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2"}, +] + [[package]] name = "idna" version = "3.10" @@ -564,6 +677,47 @@ files = [ {file = "minio-7.2.9.tar.gz", hash = "sha256:a83c2fcd981944602a8dc11e8e07543ed9cda0a9462264e3f46a13171c56bccb"}, ] +[[package]] +name = "morecantile" +version = "5.4.2" +requires_python = ">=3.8" +summary = "Construct and use map tile grids (a.k.a TileMatrixSet / TMS)." +dependencies = [ + "attrs", + "pydantic~=2.0", + "pyproj~=3.1", +] +files = [ + {file = "morecantile-5.4.2-py3-none-any.whl", hash = "sha256:2f09ab980aa4ff519cd3891018d963e4a2c42e232f854b441137cc727359322d"}, + {file = "morecantile-5.4.2.tar.gz", hash = "sha256:19b5a1550b2151e9abeffd348f987587f98b08cd7dce4af9362466fc74e3f3e6"}, +] + +[[package]] +name = "numexpr" +version = "2.10.1" +requires_python = ">=3.9" +summary = "Fast numerical expression evaluator for NumPy" +dependencies = [ + "numpy>=1.23.0", +] +files = [ + {file = "numexpr-2.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a3c0b0bf165b2d886eb981afa4e77873ca076f5d51c491c4d7b8fc10f17c876f"}, + {file = "numexpr-2.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56648a04679063175681195670ad53e5c8ca19668166ed13875199b5600089c7"}, + {file = "numexpr-2.10.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce04ae6efe2a9d0be1a0e114115c3ae70c68b8b8fbc615c5c55c15704b01e6a4"}, + {file = "numexpr-2.10.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:45f598182b4f5c153222e47d5163c3bee8d5ebcaee7e56dd2a5898d4d97e4473"}, + {file = "numexpr-2.10.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6a50370bea77ba94c3734a44781c716751354c6bfda2d369af3aed3d67d42871"}, + {file = "numexpr-2.10.1-cp311-cp311-win32.whl", hash = "sha256:fa4009d84a8e6e21790e718a80a22d57fe7f215283576ef2adc4183f7247f3c7"}, + {file = "numexpr-2.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:fcbf013bb8494e8ef1d11fa3457827c1571c6a3153982d709e5d17594999d4dd"}, + {file = "numexpr-2.10.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:82fc95c301b15ff4823f98989ee363a2d5555d16a7cfd3710e98ddee726eaaaa"}, + {file = "numexpr-2.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cbf79fef834f88607f977ab9867061dcd9b40ccb08bb28547c6dc6c73e560895"}, + {file = "numexpr-2.10.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:552c8d4b2e3b87cdb2abb40a781b9a61a9090a9f66ac7357fc5a0b93aff76be3"}, + {file = "numexpr-2.10.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22cc65e9121aeb3187a2b50827715b2b087ea70e8ab21416ea52662322087b43"}, + {file = "numexpr-2.10.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:00204e5853713b5eba5f3d0bc586a5d8d07f76011b597c8b4087592cc2ec2928"}, + {file = "numexpr-2.10.1-cp312-cp312-win32.whl", hash = "sha256:82bf04a1495ac475de4ab49fbe0a3a2710ed3fd1a00bc03847316b5d7602402d"}, + {file = "numexpr-2.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:300e577b3c006dd7a8270f1bb2e8a00ee15bf235b1650fe2a6febec2954bc2c3"}, + {file = "numexpr-2.10.1.tar.gz", hash = "sha256:9bba99d354a65f1a008ab8b87f07d84404c668e66bab624df5b6b5373403cf81"}, +] + [[package]] name = "numpy" version = "1.26.4" @@ -834,6 +988,16 @@ files = [ {file = "pyodm-1.5.11.tar.gz", hash = "sha256:bb97710171bfaee92e145bd97b1ac77db8beef580b89d6585a622ff6fb424c53"}, ] +[[package]] +name = "pyparsing" +version = "3.2.0" +requires_python = ">=3.9" +summary = "pyparsing module - Classes and methods to define and execute parsing grammars" +files = [ + {file = "pyparsing-3.2.0-py3-none-any.whl", hash = "sha256:93d9577b88da0bbea8cc8334ee8b918ed014968fd2ec383e868fb8afb1ccef84"}, + {file = "pyparsing-3.2.0.tar.gz", hash = "sha256:cbf74e27246d595d9a74b186b810f6fbb86726dbf3b9532efb343f6d7294fe9c"}, +] + [[package]] name = "pyproj" version = "3.7.0" @@ -864,6 +1028,32 @@ files = [ {file = "pyproj-3.7.0.tar.gz", hash = "sha256:bf658f4aaf815d9d03c8121650b6f0b8067265c36e31bc6660b98ef144d81813"}, ] +[[package]] +name = "pystac" +version = "1.11.0" +requires_python = ">=3.10" +summary = "Python library for working with the SpatioTemporal Asset Catalog (STAC) specification" +dependencies = [ + "python-dateutil>=2.7.0", +] +files = [ + {file = "pystac-1.11.0-py3-none-any.whl", hash = "sha256:10ac7c7b4ea6c5ec8333829a09ec1a33b596f02d1a97ffbbd72cd1b6c10598c1"}, + {file = "pystac-1.11.0.tar.gz", hash = "sha256:acb1e04be398a0cda2d8870ab5e90457783a8014a206590233171d8b2ae0d9e7"}, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +summary = "Extensions to the standard Python datetime module" +dependencies = [ + "six>=1.5", +] +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + [[package]] name = "python-dotenv" version = "1.0.1" @@ -897,6 +1087,38 @@ files = [ {file = "python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8"}, ] +[[package]] +name = "rasterio" +version = "1.4.1" +requires_python = ">=3.9" +summary = "Fast and direct raster I/O for use with Numpy and SciPy" +dependencies = [ + "affine", + "attrs", + "certifi", + "click-plugins", + "click>=4.0", + "cligj>=0.5", + "importlib-metadata; python_version < \"3.10\"", + "numpy>=1.24", + "pyparsing", +] +files = [ + {file = "rasterio-1.4.1-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:5037188f3582cdb21a308d6cacfc6a4f2828cd05d382f8b848c8bb405a0778b4"}, + {file = "rasterio-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:50fb06c2895cc055f34d813600cb5dc56b170d02c216913fdf80b573d771e972"}, + {file = "rasterio-1.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef99c77d2c52bd95b42ff862c252a74c7528ec3b3cbb665c783e3948ebd811cf"}, + {file = "rasterio-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:6832fb300615e5d8649346b4aad557330cfae23bc5499832d106c415cc85173b"}, + {file = "rasterio-1.4.1-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:a0cd7b8eda7d3b0097a42a047d2604c3f1f27b4093e2a4e1e7ad379c9f639f65"}, + {file = "rasterio-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:af5e0559eb8da3cf0adbc1d26ce86e505ea82814012b7b6711855674ae3f6425"}, + {file = "rasterio-1.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b85f7d912b868ce8dd25e01d5042c8426cc9208a715f093081503ee864e870b"}, + {file = "rasterio-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:e7b18c4ccf0d813b6056704af86e14d6841e29ec558a9bce2f1ce2e3ee2ef70d"}, + {file = "rasterio-1.4.1-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:c5b626dc0c08dc593e462265ce974266f3e1dd90fa67807bef33704d88c62a28"}, + {file = "rasterio-1.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0c2f21b4fe0f6f8af0a902c4f86fb51d25a058fabf4dada1d453f8dce6be7938"}, + {file = "rasterio-1.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2466adf39009115de23209a4b343fdb0db9a3aef97119d826d09df26b7f3beb9"}, + {file = "rasterio-1.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:2e6a8fbdf31053a3ff95c138976ffc8ee547f361326cb42bd26fcee26422e157"}, + {file = "rasterio-1.4.1.tar.gz", hash = "sha256:d750362bb792d2311f94803ff309baec48486ecba75c9b905ea9b1f5eb06ef9f"}, +] + [[package]] name = "requests" version = "2.32.3" @@ -940,6 +1162,30 @@ files = [ {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, ] +[[package]] +name = "rio-tiler" +version = "7.0.0" +requires_python = ">=3.8" +summary = "User friendly Rasterio plugin to read raster datasets." +dependencies = [ + "attrs", + "cachetools", + "color-operations", + "httpx", + "importlib-resources>=1.1.0; python_version < \"3.9\"", + "morecantile<7.0,>=5.0", + "numexpr", + "numpy", + "pydantic~=2.0", + "pystac>=0.5.4", + "rasterio>=1.3.0", + "typing-extensions", +] +files = [ + {file = "rio_tiler-7.0.0-py3-none-any.whl", hash = "sha256:4a6220c488cfe3c94a3127be7f889d3d4ce9500f53f06dc1ccd53c66780a9242"}, + {file = "rio_tiler-7.0.0.tar.gz", hash = "sha256:bfaecc399ee03f2eb4c90f07fc2f1aa276fc6a55f72a3837c0d75b2d7b01403d"}, +] + [[package]] name = "shapely" version = "2.0.5" @@ -964,6 +1210,16 @@ files = [ {file = "shapely-2.0.5.tar.gz", hash = "sha256:bff2366bc786bfa6cb353d6b47d0443c570c32776612e527ee47b6df63fcfe32"}, ] +[[package]] +name = "six" +version = "1.16.0" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +summary = "Python 2 and 3 compatibility utilities" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + [[package]] name = "sniffio" version = "1.3.1" diff --git a/src/backend/pyproject.toml b/src/backend/pyproject.toml index 857ea7e8..c21864f4 100644 --- a/src/backend/pyproject.toml +++ b/src/backend/pyproject.toml @@ -34,6 +34,7 @@ dependencies = [ "pyodm>=1.5.11", "asgiref>=3.8.1", "drone-flightplan>=0.3.1", + "rio-tiler>=7.0.0", ] requires-python = ">=3.11" license = {text = "GPL-3.0-only"} From 6cdc985a3be27ef4ccbcc15698bae9af83237e2a Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Sat, 26 Oct 2024 10:21:45 +0545 Subject: [PATCH 069/390] hotfix: update task status as completed after image processing... --- src/backend/app/projects/image_processing.py | 26 +++++++++++--------- src/backend/app/projects/project_routes.py | 11 ++++----- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/backend/app/projects/image_processing.py b/src/backend/app/projects/image_processing.py index 6549d999..92940894 100644 --- a/src/backend/app/projects/image_processing.py +++ b/src/backend/app/projects/image_processing.py @@ -12,6 +12,7 @@ from psycopg import Connection from asgiref.sync import async_to_sync from app.config import settings +from app.db import database class DroneImageProcessor: @@ -192,7 +193,6 @@ def process_images_from_s3(self, bucket_name, name=None, options=[], webhook=Non async def download_and_upload_assets_from_odm_to_s3( - db: Connection, node_odm_url: str, task_id: str, dtm_project_id: uuid.UUID, @@ -207,7 +207,6 @@ async def download_and_upload_assets_from_odm_to_s3( :param dtm_task_id: UUID of the task. """ log.info(f"Starting download for task {task_id}") - # Replace with actual ODM node details and URL node = Node.from_url(node_odm_url) @@ -231,16 +230,19 @@ async def download_and_upload_assets_from_odm_to_s3( log.info(f"Assets for task {task_id} successfully uploaded to S3.") # Update background task status to COMPLETED - await task_logic.update_task_state( - db, - dtm_project_id, - dtm_task_id, - user_id, - "Task completed.", - State.IMAGE_UPLOADED, - State.IMAGE_PROCESSED, - timestamp(), - ) + pool = await database.get_db_connection_pool() + + async with pool.connection() as conn: + await task_logic.update_task_state( + db=conn, + project_id=dtm_project_id, + task_id=dtm_task_id, + user_id=user_id, + comment="Task completed.", + initial_state=State.IMAGE_UPLOADED, + final_state=State.IMAGE_PROCESSED, + updated_at=timestamp(), + ) except Exception as e: log.error(f"Error downloading or uploading assets for task {task_id}: {e}") diff --git a/src/backend/app/projects/project_routes.py b/src/backend/app/projects/project_routes.py index 9bbbf841..07d1a65a 100644 --- a/src/backend/app/projects/project_routes.py +++ b/src/backend/app/projects/project_routes.py @@ -460,12 +460,11 @@ async def odm_webhook( # Call function to download assets from ODM and upload to S3 background_tasks.add_task( image_processing.download_and_upload_assets_from_odm_to_s3, - db, - settings.NODE_ODM_URL, - task_id, - dtm_project_id, - dtm_task_id, - dtm_user_id, + node_odm_url=settings.NODE_ODM_URL, + task_id=task_id, + dtm_project_id=dtm_project_id, + dtm_task_id=dtm_task_id, + user_id=dtm_user_id, ) elif status["code"] == 30: # failed task From 974cc557b9cb626fb813cfb29cf4b0a383b3f2b8 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Sat, 26 Oct 2024 10:59:56 +0545 Subject: [PATCH 070/390] hotfix: update task status as completed after image processing... --- src/backend/app/projects/image_processing.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/backend/app/projects/image_processing.py b/src/backend/app/projects/image_processing.py index 0a65a05f..0bffdef4 100644 --- a/src/backend/app/projects/image_processing.py +++ b/src/backend/app/projects/image_processing.py @@ -199,8 +199,6 @@ async def download_and_upload_assets_from_odm_to_s3( dtm_project_id: uuid.UUID, dtm_task_id: uuid.UUID, user_id: str, - current_state: State, - comment: str, ): """ Downloads results from ODM and uploads them to S3 (Minio). From 775cde99e0d294f113676aa86ed6c87d568488f9 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Sat, 26 Oct 2024 11:04:58 +0545 Subject: [PATCH 071/390] hotfix(taskStatus): update task status as completed after image processing... --- src/backend/app/projects/project_routes.py | 46 +++++----------------- 1 file changed, 9 insertions(+), 37 deletions(-) diff --git a/src/backend/app/projects/project_routes.py b/src/backend/app/projects/project_routes.py index 49227c0a..63807e1c 100644 --- a/src/backend/app/projects/project_routes.py +++ b/src/backend/app/projects/project_routes.py @@ -470,6 +470,7 @@ async def odm_webhook( task_id = payload.get("uuid") status = payload.get("status") + if not task_id or not status: raise HTTPException(status_code=400, detail="Invalid webhook payload") @@ -478,46 +479,17 @@ async def odm_webhook( # If status is 'success', download and upload assets to S3. # 40 is the status code for success in odm if status["code"] == 40: - log.info(f"Task ID: {task_id}, Status: going for download......") - # Call function to download assets from ODM and upload to S3 background_tasks.add_task( image_processing.download_and_upload_assets_from_odm_to_s3, - node_odm_url=settings.NODE_ODM_URL, - task_id=task_id, - dtm_project_id=dtm_project_id, - dtm_task_id=dtm_task_id, - user_id=dtm_user_id, + db, + settings.NODE_ODM_URL, + task_id, + dtm_project_id, + dtm_task_id, + dtm_user_id, ) elif status["code"] == 30: - current_state = await task_logic.get_current_state( - db, dtm_project_id, dtm_task_id - ) - # If the current state is not already IMAGE_PROCESSING_FAILED, update it - if current_state != State.IMAGE_PROCESSING_FAILED: - await task_logic.update_task_state( - db, - dtm_project_id, - dtm_task_id, - dtm_user_id, - "Image processing failed.", - State.IMAGE_UPLOADED, - State.IMAGE_PROCESSING_FAILED, - timestamp(), - ) - - background_tasks.add_task( - image_processing.download_and_upload_assets_from_odm_to_s3, - db, - settings.NODE_ODM_URL, - task_id, - dtm_project_id, - dtm_task_id, - dtm_user_id, - State.IMAGE_PROCESSING_FAILED, - "Image processing failed.", - ) - - log.info(f"Task ID: {task_id}, Status: Webhook received") - + # failed task + log.error(f'ODM task {task_id} failed: {status["errorMessage"]}') return {"message": "Webhook received", "task_id": task_id} From abb334e1f9c4c37d36b0da031a02f624b1f0fe5f Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Sat, 26 Oct 2024 11:36:00 +0545 Subject: [PATCH 072/390] fix: pass the matching args to download_and_upload_assets_from_odm_to_s3 --- src/backend/app/projects/project_routes.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/backend/app/projects/project_routes.py b/src/backend/app/projects/project_routes.py index 63807e1c..de6ea197 100644 --- a/src/backend/app/projects/project_routes.py +++ b/src/backend/app/projects/project_routes.py @@ -482,7 +482,6 @@ async def odm_webhook( # Call function to download assets from ODM and upload to S3 background_tasks.add_task( image_processing.download_and_upload_assets_from_odm_to_s3, - db, settings.NODE_ODM_URL, task_id, dtm_project_id, From 408b88a5216719cf3af15cf7c9b9d0963d9cf5b2 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Sat, 26 Oct 2024 13:08:57 +0545 Subject: [PATCH 073/390] fix: update state of task after image processes --- src/backend/app/projects/image_processing.py | 25 +++++++++++--------- src/backend/app/projects/project_routes.py | 3 --- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/backend/app/projects/image_processing.py b/src/backend/app/projects/image_processing.py index 018b05dc..9f4c3d0b 100644 --- a/src/backend/app/projects/image_processing.py +++ b/src/backend/app/projects/image_processing.py @@ -6,6 +6,7 @@ from app.tasks import task_logic from app.models.enums import State from app.utils import timestamp +from app.db import database from pyodm import Node from app.s3 import get_file_from_bucket, list_objects_from_bucket, add_file_to_bucket from loguru import logger as log @@ -193,7 +194,6 @@ def process_images_from_s3(self, bucket_name, name=None, options=[], webhook=Non async def download_and_upload_assets_from_odm_to_s3( - db: Connection, node_odm_url: str, task_id: str, dtm_project_id: uuid.UUID, @@ -236,16 +236,19 @@ async def download_and_upload_assets_from_odm_to_s3( log.info(f"Assets for task {task_id} successfully uploaded to S3.") # Update background task status to COMPLETED - await task_logic.update_task_state( - db, - dtm_project_id, - dtm_task_id, - user_id, - comment, - current_state, - State.IMAGE_PROCESSED, - timestamp(), - ) + pool = await database.get_db_connection_pool() + + async with pool.connection() as conn: + await task_logic.update_task_state( + db=conn, + project_id=dtm_project_id, + task_id=dtm_task_id, + user_id=user_id, + comment="Task completed.", + initial_state=current_state, + final_state=State.IMAGE_PROCESSED, + updated_at=timestamp(), + ) except Exception as e: log.error(f"Error downloading or uploading assets for task {task_id}: {e}") diff --git a/src/backend/app/projects/project_routes.py b/src/backend/app/projects/project_routes.py index d8532f51..ec3e8bb2 100644 --- a/src/backend/app/projects/project_routes.py +++ b/src/backend/app/projects/project_routes.py @@ -482,7 +482,6 @@ async def odm_webhook( # Call function to download assets from ODM and upload to S3 background_tasks.add_task( image_processing.download_and_upload_assets_from_odm_to_s3, - db, settings.NODE_ODM_URL, task_id, dtm_project_id, @@ -499,7 +498,6 @@ async def odm_webhook( # Call function to download assets from ODM and upload to S3 background_tasks.add_task( image_processing.download_and_upload_assets_from_odm_to_s3, - db, settings.NODE_ODM_URL, task_id, dtm_project_id, @@ -531,7 +529,6 @@ async def odm_webhook( background_tasks.add_task( image_processing.download_and_upload_assets_from_odm_to_s3, - db, settings.NODE_ODM_URL, task_id, dtm_project_id, From f3145aa7e65e703c266b90ca74cba4ee9640b1aa Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Mon, 28 Oct 2024 11:02:23 +0545 Subject: [PATCH 074/390] feat: re-upload the images from pre-signed urls --- src/backend/app/projects/project_routes.py | 57 ++++++++++++++++++---- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/src/backend/app/projects/project_routes.py b/src/backend/app/projects/project_routes.py index 44c378cd..b2ec8316 100644 --- a/src/backend/app/projects/project_routes.py +++ b/src/backend/app/projects/project_routes.py @@ -34,6 +34,7 @@ from app.tasks import task_schemas from app.utils import geojson_to_kml, timestamp from app.users import user_schemas +from minio.deleteobjects import DeleteObject router = APIRouter( @@ -287,8 +288,9 @@ async def preview_split_by_square( @router.post("/generate-presigned-url/", tags=["Image Upload"]) async def generate_presigned_url( - data: project_schemas.PresignedUrlRequest, user: Annotated[AuthUser, Depends(login_required)], + data: project_schemas.PresignedUrlRequest, + replace_existing: bool = False, ): """ Generate a pre-signed URL for uploading an image to S3 Bucket. @@ -297,21 +299,57 @@ async def generate_presigned_url( an S3 bucket. The URL expires after a specified duration. Args: - - image_name: The name of the image you want to upload - expiry : Expiry time in hours + image_name: The name of the image(s) you want to upload. + expiry : Expiry time in hours. + replace_existing: A boolean flag to indicate if the image should be replaced. Returns: - - str: The pre-signed URL to upload the image + list: A list of dictionaries with the image name and the pre-signed URL to upload. """ try: - # Generate a pre-signed URL for an object + # Initialize the S3 client client = s3_client() urls = [] - for image in data.image_name: - image_path = f"projects/{data.project_id}/{data.task_id}/images/{image}" + # Process each image in the request + for image in data.image_name: + # Construct the image path + image_path = ( + f"projects/{data.project_id}/{data.task_id}/images/" + if replace_existing + else f"projects/{data.project_id}/{data.task_id}/images/{image}" + ) + # If replace_existing is True, delete the image first + if replace_existing: + try: + # Prepare the list of objects to delete (recursively if necessary) + delete_object_list = map( + lambda x: DeleteObject(x.object_name), + client.list_objects( + settings.S3_BUCKET_NAME, image_path, recursive=True + ), + ) + + # Remove the objects (images) + errors = client.remove_objects( + settings.S3_BUCKET_NAME, delete_object_list + ) + + # Handle deletion errors, if any + for error in errors: + log.error("Error occurred when deleting object", error) + raise HTTPException( + status_code=HTTPStatus.BAD_REQUEST, + detail=f"Failed to delete existing image: {error}", + ) + + except Exception as e: + raise HTTPException( + status_code=HTTPStatus.BAD_REQUEST, + detail=f"Failed to delete existing image. {e}", + ) + + # Generate a new pre-signed URL for the image upload url = client.get_presigned_url( "PUT", settings.S3_BUCKET_NAME, @@ -321,6 +359,7 @@ async def generate_presigned_url( urls.append({"image_name": image, "url": url}) return urls + except Exception as e: raise HTTPException( status_code=HTTPStatus.BAD_REQUEST, From 6e2ae417fe674f4e7b46d17a3d103d7e4b402696 Mon Sep 17 00:00:00 2001 From: Sujit Date: Mon, 28 Oct 2024 11:08:15 +0545 Subject: [PATCH 075/390] feat(individual-project): show image-processed/task-completed on map --- .../IndividualProject/MapSection/index.tsx | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/frontend/src/components/IndividualProject/MapSection/index.tsx b/src/frontend/src/components/IndividualProject/MapSection/index.tsx index 1d69991b..dc6a7591 100644 --- a/src/frontend/src/components/IndividualProject/MapSection/index.tsx +++ b/src/frontend/src/components/IndividualProject/MapSection/index.tsx @@ -262,32 +262,41 @@ const MapSection = ({ projectData }: { projectData: Record }) => { 'fill-opacity': 0.5, }, } - : taskStatusObj?.[`${task?.id}`] === 'IMAGE_UPLOADED' + : taskStatusObj?.[`${task?.id}`] === 'IMAGE_PROCESSED' ? { type: 'fill', paint: { - 'fill-color': '#9C77B2', + 'fill-color': '#ACD2C4', 'fill-outline-color': '#484848', - 'fill-opacity': 0.5, + 'fill-opacity': 0.7, }, } - : taskStatusObj?.[`${task?.id}`] === 'UNFLYABLE_TASK' + : taskStatusObj?.[`${task?.id}`] === 'IMAGE_UPLOADED' ? { type: 'fill', paint: { - 'fill-color': '#9EA5AD', - 'fill-outline-color': '#484848', - 'fill-opacity': 0.7, - }, - } - : { - type: 'fill', - paint: { - 'fill-color': '#ffffff', + 'fill-color': '#9C77B2', 'fill-outline-color': '#484848', 'fill-opacity': 0.5, }, } + : taskStatusObj?.[`${task?.id}`] === 'UNFLYABLE_TASK' + ? { + type: 'fill', + paint: { + 'fill-color': '#9EA5AD', + 'fill-outline-color': '#484848', + 'fill-opacity': 0.7, + }, + } + : { + type: 'fill', + paint: { + 'fill-color': '#ffffff', + 'fill-outline-color': '#484848', + 'fill-opacity': 0.5, + }, + } } hasImage={ taskStatusObj?.[`${task?.id}`] === 'LOCKED_FOR_MAPPING' || false From f125093ce483fd9e42aafa388990707577f09cb3 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Mon, 28 Oct 2024 11:53:47 +0545 Subject: [PATCH 076/390] feat: handle state event for image re-upload --- src/backend/app/projects/project_routes.py | 16 +++++++++++++ src/backend/app/tasks/task_routes.py | 26 +++++++++++++--------- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/backend/app/projects/project_routes.py b/src/backend/app/projects/project_routes.py index b2ec8316..b05c9a4b 100644 --- a/src/backend/app/projects/project_routes.py +++ b/src/backend/app/projects/project_routes.py @@ -343,6 +343,22 @@ async def generate_presigned_url( detail=f"Failed to delete existing image: {error}", ) + # # Update task as images uploaded + # pool = await database.get_db_connection_pool() + # current_task_state = await task_logic.get_task_state( + # conn, data.project_id, data.task_id + # ) + # async with pool.connection() as conn: + # await task_logic.update_task_state( + # conn, + # data.project_id, + # data.task_id, + # data.user_id, + # "Image re-upload", + # current_task_state, + # final_state=State.IMAGE_UPLOADED, + # updated_at=timestamp(), + # ) except Exception as e: raise HTTPException( status_code=HTTPStatus.BAD_REQUEST, diff --git a/src/backend/app/tasks/task_routes.py b/src/backend/app/tasks/task_routes.py index a031e4ae..c4cdd2b4 100644 --- a/src/backend/app/tasks/task_routes.py +++ b/src/backend/app/tasks/task_routes.py @@ -405,18 +405,24 @@ async def new_event( current_task_state = await task_logic.get_task_state( db, project_id, task_id ) + if not current_task_state: + raise HTTPException( + status_code=400, detail="Task is not ready for image upload." + ) state = current_task_state.get("state") locked_user_id = current_task_state.get("user_id") - # # Determine error conditions - # if ( - # state != State.LOCKED_FOR_MAPPING.name - # or State.IMAGE_PROCESSING_FAILED.name - # ): - # raise HTTPException( - # status_code=400, - # detail="Task state does not match expected state for image upload.", - # ) + # Determine error conditions: Current State must be IMAGE_UPLOADED or IMAGE_PROCESSING_FAILED or lokec for mapping. + if state not in ( + State.IMAGE_UPLOADED.name, + State.IMAGE_PROCESSING_FAILED.name, + State.LOCKED_FOR_MAPPING.name, + ): + raise HTTPException( + status_code=400, + detail="Task state does not match expected state for image upload.", + ) + if user_id != locked_user_id: raise HTTPException( status_code=403, @@ -429,7 +435,7 @@ async def new_event( task_id, user_id, f"Task image uploaded by user {user_data.name}.", - State.LOCKED_FOR_MAPPING, + State[state], State.IMAGE_UPLOADED, detail.updated_at, ) From 800bf61a80da822386d859e3ce00bb102e2de781 Mon Sep 17 00:00:00 2001 From: Sujit Date: Mon, 28 Oct 2024 12:12:50 +0545 Subject: [PATCH 077/390] feat(project-description): add `image processing failed` state of map task on map --- .../IndividualProject/MapSection/Legend.tsx | 6 ++- .../IndividualProject/MapSection/index.tsx | 37 +++++++++++++------ 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/frontend/src/components/IndividualProject/MapSection/Legend.tsx b/src/frontend/src/components/IndividualProject/MapSection/Legend.tsx index 21cc42fb..f3b3417e 100644 --- a/src/frontend/src/components/IndividualProject/MapSection/Legend.tsx +++ b/src/frontend/src/components/IndividualProject/MapSection/Legend.tsx @@ -5,7 +5,7 @@ import { useState } from 'react'; const Legend = () => { const [showLegendItems, setShowLegendItems] = useState(true); return ( -
+
Legend
{
Image Processing
+
+
+
Image Processing Failed
+
Requested Tasks
diff --git a/src/frontend/src/components/IndividualProject/MapSection/index.tsx b/src/frontend/src/components/IndividualProject/MapSection/index.tsx index dc6a7591..52cb242c 100644 --- a/src/frontend/src/components/IndividualProject/MapSection/index.tsx +++ b/src/frontend/src/components/IndividualProject/MapSection/index.tsx @@ -143,7 +143,8 @@ const MapSection = ({ projectData }: { projectData: Record }) => { return `This task's Images has been uploaded ${properties.locked_user_name ? `by ${userDetails?.id === properties?.locked_user_id ? 'you' : properties?.locked_user_name}` : ''}`; case 'IMAGE_PROCESSED': return `This task is completed ${properties.locked_user_name ? `by ${userDetails?.id === properties?.locked_user_id ? 'you' : properties?.locked_user_name}` : ''}`; - + case 'IMAGE_PROCESSING_FAILED': + return `This task's image processing is failed started ${properties.locked_user_name ? `by ${userDetails?.id === properties?.locked_user_id ? 'you' : properties?.locked_user_name}` : ''}`; default: return ''; } @@ -280,23 +281,34 @@ const MapSection = ({ projectData }: { projectData: Record }) => { 'fill-opacity': 0.5, }, } - : taskStatusObj?.[`${task?.id}`] === 'UNFLYABLE_TASK' + : taskStatusObj?.[`${task?.id}`] === + 'IMAGE_PROCESSING_FAILED' ? { type: 'fill', paint: { - 'fill-color': '#9EA5AD', - 'fill-outline-color': '#484848', - 'fill-opacity': 0.7, - }, - } - : { - type: 'fill', - paint: { - 'fill-color': '#ffffff', + 'fill-color': '#f00000', 'fill-outline-color': '#484848', 'fill-opacity': 0.5, }, } + : taskStatusObj?.[`${task?.id}`] === + 'UNFLYABLE_TASK' + ? { + type: 'fill', + paint: { + 'fill-color': '#9EA5AD', + 'fill-outline-color': '#484848', + 'fill-opacity': 0.7, + }, + } + : { + type: 'fill', + paint: { + 'fill-color': '#ffffff', + 'fill-outline-color': '#484848', + 'fill-opacity': 0.5, + }, + } } hasImage={ taskStatusObj?.[`${task?.id}`] === 'LOCKED_FOR_MAPPING' || false @@ -327,7 +339,8 @@ const MapSection = ({ projectData }: { projectData: Record }) => { (taskStatusObj?.[selectedTaskId] === 'LOCKED_FOR_MAPPING' && lockedUser?.id === userDetails?.id) || taskStatusObj?.[selectedTaskId] === 'IMAGE_UPLOADED' || - taskStatusObj?.[selectedTaskId] === 'IMAGE_PROCESSED' + taskStatusObj?.[selectedTaskId] === 'IMAGE_PROCESSED' || + taskStatusObj?.[selectedTaskId] === 'IMAGE_PROCESSING_FAILED' ) } buttonText={ From 4e9a33de88701517e5210efe4e0d451441cfbf5e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 16:48:00 +0000 Subject: [PATCH 078/390] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/commitizen-tools/commitizen: v3.29.1 → v3.30.0](https://github.com/commitizen-tools/commitizen/compare/v3.29.1...v3.30.0) - [github.com/astral-sh/ruff-pre-commit: v0.7.0 → v0.7.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.7.0...v0.7.1) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 835f89c2..a1e7f9b2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -79,7 +79,7 @@ repos: # Versioning: Commit messages & changelog - repo: https://github.com/commitizen-tools/commitizen - rev: v3.29.1 + rev: v3.30.0 hooks: - id: commitizen stages: [commit-msg] @@ -87,7 +87,7 @@ repos: # Lint / autoformat: Python code - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: "v0.7.0" + rev: "v0.7.1" hooks: # Run the linter - id: ruff From d313f067d66cccbead1aa77e7ebc78899cca80eb Mon Sep 17 00:00:00 2001 From: Sujit Date: Tue, 29 Oct 2024 09:38:24 +0545 Subject: [PATCH 079/390] feat(task-description): save uploading image (replace/add) on redux store --- src/frontend/src/store/actions/droneOperatorTask.ts | 1 + src/frontend/src/store/slices/droneOperartorTask.ts | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/frontend/src/store/actions/droneOperatorTask.ts b/src/frontend/src/store/actions/droneOperatorTask.ts index 19e24a36..eb6d031b 100644 --- a/src/frontend/src/store/actions/droneOperatorTask.ts +++ b/src/frontend/src/store/actions/droneOperatorTask.ts @@ -12,4 +12,5 @@ export const { setFiles, setSelectedTakeOffPointOption, setSelectedTakeOffPoint, + setUploadedImagesType, } = droneOperatorTaskSlice.actions; diff --git a/src/frontend/src/store/slices/droneOperartorTask.ts b/src/frontend/src/store/slices/droneOperartorTask.ts index 85f33d4a..5f942271 100644 --- a/src/frontend/src/store/slices/droneOperartorTask.ts +++ b/src/frontend/src/store/slices/droneOperartorTask.ts @@ -10,6 +10,7 @@ export interface IDroneOperatorTaskState { files: any[]; selectedTakeOffPointOption: string; selectedTakeOffPoint: any[] | string | null; + uploadedImagesType: 'add' | 'replace'; } const initialState: IDroneOperatorTaskState = { @@ -21,6 +22,7 @@ const initialState: IDroneOperatorTaskState = { files: [], selectedTakeOffPointOption: 'current_location', selectedTakeOffPoint: null, + uploadedImagesType: 'add', }; export const droneOperatorTaskSlice = createSlice({ @@ -65,6 +67,10 @@ export const droneOperatorTaskSlice = createSlice({ setSelectedTakeOffPoint: (state, action) => { state.selectedTakeOffPoint = action.payload; }, + + setUploadedImagesType: (state, action) => { + state.uploadedImagesType = action.payload; + }, }, }); From b6be4e77dd1f41a64b492056016020e8351fa593 Mon Sep 17 00:00:00 2001 From: Sujit Date: Tue, 29 Oct 2024 09:39:45 +0545 Subject: [PATCH 080/390] feat(task-description): add options to choose want to replace the image or add on existing imags while uploading images --- .../DescriptionBox/index.tsx | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx b/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx index 8b357d3a..f2dc2eba 100644 --- a/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx +++ b/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx @@ -1,5 +1,6 @@ import { useState } from 'react'; import { useParams } from 'react-router-dom'; +import { useDispatch } from 'react-redux'; import { toast } from 'react-toastify'; import { useGetIndividualTaskQuery, @@ -10,14 +11,22 @@ import { useMutation } from '@tanstack/react-query'; import { postProcessImagery } from '@Services/tasks'; import { formatString } from '@Utils/index'; import { Button } from '@Components/RadixComponents/Button'; +import { Label } from '@Components/common/FormUI'; +import SwitchTab from '@Components/common/SwitchTab'; +import { setUploadedImagesType } from '@Store/actions/droneOperatorTask'; +import { useTypedSelector } from '@Store/hooks'; import DescriptionBoxComponent from './DescriptionComponent'; import QuestionBox from '../QuestionBox'; import UploadsInformation from '../UploadsInformation'; import UploadsBox from '../UploadsBox'; const DescriptionBox = () => { + const dispatch = useDispatch(); const [flyable, setFlyable] = useState('yes'); const { taskId, projectId } = useParams(); + const uploadedImageType = useTypedSelector( + state => state.droneOperatorTask.uploadedImagesType, + ); const { data: taskWayPoints }: any = useGetTaskWaypointQuery( projectId as string, @@ -215,8 +224,39 @@ const DescriptionBox = () => {
)} {taskAssetsInformation?.state === 'IMAGE_PROCESSING_FAILED' && ( -
- +
+ + ) => { + dispatch(setUploadedImagesType(selected.value)); + }} + /> +

+ Note:{' '} + {uploadedImageType === 'add' + ? 'Uploaded images will be added with the existing images.' + : 'Uploaded images will be replaced with all the existing images and starts processing.'} +

+
)}
From 0716d370dd562980552fd934454a6ff9eb6c9124 Mon Sep 17 00:00:00 2001 From: Sujit Date: Tue, 29 Oct 2024 09:41:41 +0545 Subject: [PATCH 081/390] feat(task-description): get presigned url as per the type(replace the images/ add to existing images) --- .../PopoverBox/ImageBox/index.tsx | 9 +++++++-- src/frontend/src/services/droneOperator.ts | 14 +++++++++----- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/frontend/src/components/DroneOperatorTask/DescriptionSection/PopoverBox/ImageBox/index.tsx b/src/frontend/src/components/DroneOperatorTask/DescriptionSection/PopoverBox/ImageBox/index.tsx index 863f0eca..789b3f58 100644 --- a/src/frontend/src/components/DroneOperatorTask/DescriptionSection/PopoverBox/ImageBox/index.tsx +++ b/src/frontend/src/components/DroneOperatorTask/DescriptionSection/PopoverBox/ImageBox/index.tsx @@ -23,7 +23,6 @@ import PreviewImage from './PreviewImage'; const ImageBoxPopOver = () => { const dispatch = useTypedDispatch(); - const pathname = window.location.pathname?.split('/'); const projectId = pathname?.[2]; const taskId = pathname?.[4]; @@ -41,6 +40,9 @@ const ImageBoxPopOver = () => { const checkedImages = useTypedSelector( state => state.droneOperatorTask.checkedImages, ); + const uploadedImageType = useTypedSelector( + state => state.droneOperatorTask.uploadedImagesType, + ); const { mutate: updateStatus } = useMutation({ mutationFn: postTaskStatus, @@ -64,7 +66,10 @@ const ImageBoxPopOver = () => { // function that gets the signed urls for the images and again puts them in chunks of 4 const { mutate } = useMutation({ mutationFn: async (data: any) => { - const urlsData = await getImageUploadLink(data); + const urlsData = await getImageUploadLink( + uploadedImageType === 'replace', + data, + ); // urls fromm array of objects is retrieved and stored in value const urls = urlsData.data.map((url: any) => url.url); diff --git a/src/frontend/src/services/droneOperator.ts b/src/frontend/src/services/droneOperator.ts index fb4f0a32..fae23836 100644 --- a/src/frontend/src/services/droneOperator.ts +++ b/src/frontend/src/services/droneOperator.ts @@ -16,9 +16,13 @@ export const postUnflyableComment = ({ }, }); -export const getImageUploadLink = (data: any) => - authenticated(api).post(`/projects/generate-presigned-url/`, data, { - headers: { - 'Content-Type': 'application/json', +export const getImageUploadLink = (replaceExistingImages: boolean, data: any) => + authenticated(api).post( + `/projects/generate-presigned-url/?replace_existing=${replaceExistingImages}`, + data, + { + headers: { + 'Content-Type': 'application/json', + }, }, - }); + ); From fcc2a20ce8faca38581d22893232c2ef738496be Mon Sep 17 00:00:00 2001 From: Sujit Date: Tue, 29 Oct 2024 09:53:41 +0545 Subject: [PATCH 082/390] fix: update status text on formating `Image Processed` to `Completed` --- src/frontend/src/utils/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/frontend/src/utils/index.ts b/src/frontend/src/utils/index.ts index b55fc37a..82620b4a 100644 --- a/src/frontend/src/utils/index.ts +++ b/src/frontend/src/utils/index.ts @@ -80,6 +80,7 @@ export const getFrontOverlap = (agl: number, forwardSpacing: number) => { // remove underscore and capitalize the word export const formatString = (value: string) => { if (!value) return ''; + if (value === 'IMAGE_PROCESSED') return 'Completed'; return value .replace(/_/g, ' ') .toLowerCase() From 0ca557d6e1a962547fbb0e48e79b4371132f52e4 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Tue, 29 Oct 2024 10:12:49 +0545 Subject: [PATCH 083/390] fix: issues slove on updated imgaes delete on s3 buckets --- src/backend/app/projects/project_routes.py | 27 ++++------------------ 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/src/backend/app/projects/project_routes.py b/src/backend/app/projects/project_routes.py index b05c9a4b..eddc5c22 100644 --- a/src/backend/app/projects/project_routes.py +++ b/src/backend/app/projects/project_routes.py @@ -313,20 +313,17 @@ async def generate_presigned_url( # Process each image in the request for image in data.image_name: - # Construct the image path - image_path = ( - f"projects/{data.project_id}/{data.task_id}/images/" - if replace_existing - else f"projects/{data.project_id}/{data.task_id}/images/{image}" - ) + image_path = f"projects/{data.project_id}/{data.task_id}/images/{image}" + # If replace_existing is True, delete the image first if replace_existing: + image_dir = f"projects/{data.project_id}/{data.task_id}/images/" try: # Prepare the list of objects to delete (recursively if necessary) delete_object_list = map( lambda x: DeleteObject(x.object_name), client.list_objects( - settings.S3_BUCKET_NAME, image_path, recursive=True + settings.S3_BUCKET_NAME, image_dir, recursive=True ), ) @@ -343,22 +340,6 @@ async def generate_presigned_url( detail=f"Failed to delete existing image: {error}", ) - # # Update task as images uploaded - # pool = await database.get_db_connection_pool() - # current_task_state = await task_logic.get_task_state( - # conn, data.project_id, data.task_id - # ) - # async with pool.connection() as conn: - # await task_logic.update_task_state( - # conn, - # data.project_id, - # data.task_id, - # data.user_id, - # "Image re-upload", - # current_task_state, - # final_state=State.IMAGE_UPLOADED, - # updated_at=timestamp(), - # ) except Exception as e: raise HTTPException( status_code=HTTPStatus.BAD_REQUEST, From 3e7b94057ea05062aa9b48cbf4809ee7d0513418 Mon Sep 17 00:00:00 2001 From: Niraj Adhikari Date: Tue, 29 Oct 2024 11:30:42 +0545 Subject: [PATCH 084/390] fix: options passed in odm task --- src/backend/app/projects/image_processing.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/backend/app/projects/image_processing.py b/src/backend/app/projects/image_processing.py index 57725ae2..aa2997fa 100644 --- a/src/backend/app/projects/image_processing.py +++ b/src/backend/app/projects/image_processing.py @@ -102,9 +102,6 @@ def process_new_task( """ opts = self.options_list_to_dict(options) - # FIXME: take this from the function above - opts = {"dsm": True} - task = self.node.create_task( images, opts, name, progress_callback, webhook=webhook ) From 1ae47020d763a37c6c9b32e65c46b1caf942c2b2 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Tue, 29 Oct 2024 11:57:36 +0545 Subject: [PATCH 085/390] fix: added options for image processing for orthophooto formats --- src/backend/app/projects/image_processing.py | 3 --- src/backend/app/projects/project_routes.py | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/backend/app/projects/image_processing.py b/src/backend/app/projects/image_processing.py index 57725ae2..aa2997fa 100644 --- a/src/backend/app/projects/image_processing.py +++ b/src/backend/app/projects/image_processing.py @@ -102,9 +102,6 @@ def process_new_task( """ opts = self.options_list_to_dict(options) - # FIXME: take this from the function above - opts = {"dsm": True} - task = self.node.create_task( images, opts, name, progress_callback, webhook=webhook ) diff --git a/src/backend/app/projects/project_routes.py b/src/backend/app/projects/project_routes.py index c670ee7b..0921b3fd 100644 --- a/src/backend/app/projects/project_routes.py +++ b/src/backend/app/projects/project_routes.py @@ -560,7 +560,7 @@ async def get_orthophoto_tile( except TileOutsideBounds: raise HTTPException( - status_code=400, detail="Tile is outside the bounds of the image." + status_code=200, detail="Tile is outside the bounds of the image." ) except Exception as e: From cfc1a6c98d56f5321c306db57957a60fca9e028a Mon Sep 17 00:00:00 2001 From: Sujit Date: Wed, 30 Oct 2024 09:55:07 +0545 Subject: [PATCH 086/390] feat(task-description): update status on rerun processing --- .../DescriptionSection/DescriptionBox/index.tsx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx b/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx index f2dc2eba..1fa42b0f 100644 --- a/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx +++ b/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx @@ -7,7 +7,7 @@ import { useGetTaskAssetsInfo, useGetTaskWaypointQuery, } from '@Api/tasks'; -import { useMutation } from '@tanstack/react-query'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; import { postProcessImagery } from '@Services/tasks'; import { formatString } from '@Utils/index'; import { Button } from '@Components/RadixComponents/Button'; @@ -15,6 +15,7 @@ import { Label } from '@Components/common/FormUI'; import SwitchTab from '@Components/common/SwitchTab'; import { setUploadedImagesType } from '@Store/actions/droneOperatorTask'; import { useTypedSelector } from '@Store/hooks'; +import { postTaskStatus } from '@Services/project'; import DescriptionBoxComponent from './DescriptionComponent'; import QuestionBox from '../QuestionBox'; import UploadsInformation from '../UploadsInformation'; @@ -22,6 +23,7 @@ import UploadsBox from '../UploadsBox'; const DescriptionBox = () => { const dispatch = useDispatch(); + const queryClient = useQueryClient(); const [flyable, setFlyable] = useState('yes'); const { taskId, projectId } = useParams(); const uploadedImageType = useTypedSelector( @@ -40,9 +42,22 @@ const DescriptionBox = () => { const { data: taskAssetsInformation }: Record = useGetTaskAssetsInfo(projectId as string, taskId as string); + const { mutate: updateStatus } = useMutation({ + mutationFn: postTaskStatus, + onError: (err: any) => { + toast.error(err.message); + }, + }); + const { mutate: reStartImageryProcess } = useMutation({ mutationFn: () => postProcessImagery(projectId as string, taskId as string), onSuccess: () => { + updateStatus({ + projectId, + taskId, + data: { event: 'image_upload', updated_at: new Date().toISOString() }, + }); + queryClient.invalidateQueries(['task-assets-info']); toast.success('Image processing re-started'); }, }); From 85d4773cadeec18f4ea486038ae0cb5c12050946 Mon Sep 17 00:00:00 2001 From: Sujit Date: Wed, 30 Oct 2024 10:55:33 +0545 Subject: [PATCH 087/390] feat: create orhtophoto preview modal --- .../DescriptionSection/DescriptionBox/index.tsx | 14 +++++++++++++- .../ModalContent/TaskOrthophotoPreview.tsx | 7 +++++++ src/frontend/src/constants/modalContents.tsx | 9 +++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/frontend/src/components/DroneOperatorTask/ModalContent/TaskOrthophotoPreview.tsx diff --git a/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx b/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx index f2dc2eba..b4668e71 100644 --- a/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx +++ b/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx @@ -15,6 +15,7 @@ import { Label } from '@Components/common/FormUI'; import SwitchTab from '@Components/common/SwitchTab'; import { setUploadedImagesType } from '@Store/actions/droneOperatorTask'; import { useTypedSelector } from '@Store/hooks'; +import { toggleModal } from '@Store/actions/common'; import DescriptionBoxComponent from './DescriptionComponent'; import QuestionBox from '../QuestionBox'; import UploadsInformation from '../UploadsInformation'; @@ -198,7 +199,18 @@ const DescriptionBox = () => { /> {taskAssetsInformation?.assets_url && ( -
+
+
); diff --git a/src/frontend/src/components/common/MapLibreComponents/COGOrthophotoViewer/index.tsx b/src/frontend/src/components/common/MapLibreComponents/COGOrthophotoViewer/index.tsx new file mode 100644 index 00000000..3a465717 --- /dev/null +++ b/src/frontend/src/components/common/MapLibreComponents/COGOrthophotoViewer/index.tsx @@ -0,0 +1,49 @@ +import { useEffect } from 'react'; +import mapLibre, { RasterSourceSpecification } from 'maplibre-gl'; +import { cogProtocol } from '@geomatico/maplibre-cog-protocol'; +import { MapInstanceType } from '../types'; + +interface IViewOrthophotoProps { + map?: MapInstanceType; + isMapLoaded?: Boolean; + id: string; + source: RasterSourceSpecification; + visibleOnMap?: Boolean; +} + +const COGOrthophotoViewer = ({ + map, + isMapLoaded, + id, + source, + visibleOnMap, +}: IViewOrthophotoProps) => { + useEffect(() => { + if (!map || !isMapLoaded || !source || !visibleOnMap) return; + + // Registers the 'cog' protocol with the mapLibre instance, enabling support for Cloud Optimized GeoTIFF (COG) files + mapLibre?.addProtocol('cog', cogProtocol); + + if (!map.getSource(id)) { + map.addSource(id, source); + map.addLayer({ + id, + source: id, + layout: {}, + ...source, + }); + } + + // eslint-disable-next-line consistent-return + return () => { + if (map?.getSource(id)) { + map?.removeSource(id); + if (map?.getLayer(id)) map?.removeLayer(id); + } + }; + }, [map, isMapLoaded, id, source, visibleOnMap]); + + return null; +}; + +export default COGOrthophotoViewer; diff --git a/src/frontend/vite.config.ts b/src/frontend/vite.config.ts index 3c16a6c9..6e3900ca 100644 --- a/src/frontend/vite.config.ts +++ b/src/frontend/vite.config.ts @@ -46,6 +46,7 @@ export default defineConfig({ API_URL_V1: process.env.API_URL_V1, SITE_NAME: process.env.SITE_NAME, STATIC_BASE_URL: process.env.STATIC_BASE_URL, + S3_ENDPOINT: process.env.S3_ENDPOINT, }, }, server: { From a9f8e28d2054ff02a2898eec798e2fe5429a1f51 Mon Sep 17 00:00:00 2001 From: Sujit Date: Fri, 15 Nov 2024 15:00:14 +0545 Subject: [PATCH 132/390] feat: make required changes for `loadImage` on map libre version updation to 4 --- .../MapLibreComponents/Layers/VectorLayer.ts | 16 ++++++++++++---- .../MapLibreComponents/useDrawTool/index.ts | 9 +++++---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/frontend/src/components/common/MapLibreComponents/Layers/VectorLayer.ts b/src/frontend/src/components/common/MapLibreComponents/Layers/VectorLayer.ts index f0e8f239..f50170eb 100644 --- a/src/frontend/src/components/common/MapLibreComponents/Layers/VectorLayer.ts +++ b/src/frontend/src/components/common/MapLibreComponents/Layers/VectorLayer.ts @@ -56,11 +56,19 @@ export default function VectorLayer({ }); if (hasImage) { - map.loadImage(image, (error, img: any) => { - if (error) throw error; - // Add the loaded image to the style's sprite with the ID 'kitten'. - map.addImage(imageId, img); + // map.loadImage(image, (error, img: any) => { + // if (error) throw error; + // // Add the loaded image to the style's sprite with the ID 'kitten'. + // map.addImage(imageId, img); + // }); + + // changes on map libre 4 + map.loadImage(image).then(({ data }) => { + if (!map.hasImage(imageId)) { + map.addImage(imageId, data); + } }); + map.addLayer({ id: imageId, type: 'symbol', diff --git a/src/frontend/src/components/common/MapLibreComponents/useDrawTool/index.ts b/src/frontend/src/components/common/MapLibreComponents/useDrawTool/index.ts index 77bda231..d875e112 100644 --- a/src/frontend/src/components/common/MapLibreComponents/useDrawTool/index.ts +++ b/src/frontend/src/components/common/MapLibreComponents/useDrawTool/index.ts @@ -126,6 +126,7 @@ export default function useDrawTool({ const lastCoords = coordinates[coordinates.length - 1]; map.addSource('line-start-point', { type: 'geojson', + // @ts-ignore data: { type: 'Feature', geometry: { @@ -136,6 +137,7 @@ export default function useDrawTool({ }); map.addSource('line-end-point', { type: 'geojson', + // @ts-ignore data: { type: 'Feature', geometry: { @@ -177,11 +179,10 @@ export default function useDrawTool({ const featureCollection = draw.getAll(); const { geometry } = featureCollection.features[0]; if (!lineStringTypes.includes(geometry.type)) return () => {}; - map.loadImage(DirectionArrow, (err, image) => { - if (err) return; + map.loadImage(DirectionArrow).then(({ data }) => { if (map.getLayer('arrowId')) return; // @ts-ignore - map.addImage('arrow', image); + map.addImage('arrow', data); map.addLayer({ id: 'arrowId', type: 'symbol', @@ -209,7 +210,7 @@ export default function useDrawTool({ useEffect(() => { if (!map || !drawMode?.includes('draw') || isDrawLayerAdded) return () => {}; - const handleMouseMove = (e: any) => { + const handleMouseMove = () => { // map.getCanvas().style.cursor = 'crosshair'; map.getCanvas().style.cursor = ''; // const description = 'Click to start drawing shape'; From 4002d79e5198d87c9820da71f24f5ff0ab1af6c0 Mon Sep 17 00:00:00 2001 From: Sujit Date: Fri, 15 Nov 2024 15:38:04 +0545 Subject: [PATCH 133/390] feat: make required changes for cluster on map libre version updation to 4 --- .../MapSection/VectorLayerWithCluster.tsx | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/frontend/src/components/Projects/MapSection/VectorLayerWithCluster.tsx b/src/frontend/src/components/Projects/MapSection/VectorLayerWithCluster.tsx index 2295a2b2..59e5f04e 100644 --- a/src/frontend/src/components/Projects/MapSection/VectorLayerWithCluster.tsx +++ b/src/frontend/src/components/Projects/MapSection/VectorLayerWithCluster.tsx @@ -68,20 +68,18 @@ export default function VectorLayerWithCluster({ }); // inspect a cluster on click - map.on('click', 'clusters', (e: any) => { + map.on('click', 'clusters', async (e: any) => { const features = map.queryRenderedFeatures(e.point, { layers: ['clusters'], }); const clusterId = features[0].properties.cluster_id; - map + const zoom = await map .getSource(sourceId) - .getClusterExpansionZoom(clusterId, (err: any, zoom: any) => { - if (err) return; - map.easeTo({ - center: features[0].geometry.coordinates, - zoom, - }); - }); + .getClusterExpansionZoom(clusterId); + map.easeTo({ + center: features[0].geometry.coordinates, + zoom, + }); }); map.on('mouseenter', 'clusters', () => { From c5e9ae42c8ac889b16bb72bb079d0b0080f03303 Mon Sep 17 00:00:00 2001 From: Sujit Date: Fri, 15 Nov 2024 16:12:13 +0545 Subject: [PATCH 134/390] feat: add `COG_URL` --- .env.example | 1 + .../DroneOperatorTask/ModalContent/TaskOrthophotoPreview.tsx | 4 ++-- src/frontend/vite.config.ts | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.env.example b/.env.example index 0ded43ef..815265be 100644 --- a/.env.example +++ b/.env.example @@ -47,6 +47,7 @@ SITE_NAME=${SITE_NAME:-"DTM-Drone Tasking Manager"} BASE_URL=${BASE_URL:-http://localhost:8000/api} API_URL_V1=${API_URL_V1:-http://localhost:8000/api} NODE_ODM_URL=${NODE_ODM_URL:-http://odm-api:3000} +COG_URL=${COG_URL} ### ODM ### diff --git a/src/frontend/src/components/DroneOperatorTask/ModalContent/TaskOrthophotoPreview.tsx b/src/frontend/src/components/DroneOperatorTask/ModalContent/TaskOrthophotoPreview.tsx index ab48fe26..902068be 100644 --- a/src/frontend/src/components/DroneOperatorTask/ModalContent/TaskOrthophotoPreview.tsx +++ b/src/frontend/src/components/DroneOperatorTask/ModalContent/TaskOrthophotoPreview.tsx @@ -8,7 +8,7 @@ import { LngLatBoundsLike, RasterSourceSpecification } from 'maplibre-gl'; import { useEffect, useMemo } from 'react'; import { useDispatch } from 'react-redux'; -const { S3_ENDPOINT } = process.env; +const { COG_URL } = process.env; const TaskOrthophotoPreview = () => { const dispatch = useDispatch(); @@ -35,7 +35,7 @@ const TaskOrthophotoPreview = () => { const orthophotoSource: RasterSourceSpecification = useMemo( () => ({ type: 'raster', - url: `cog://${S3_ENDPOINT}/dtm-data/projects/${projectId}/${taskId}/orthophoto/odm_orthophoto.tif`, + url: `cog://${COG_URL}/dtm-data/projects/${projectId}/${taskId}/orthophoto/odm_orthophoto.tif`, tileSize: 256, }), diff --git a/src/frontend/vite.config.ts b/src/frontend/vite.config.ts index 6e3900ca..b96e6fc8 100644 --- a/src/frontend/vite.config.ts +++ b/src/frontend/vite.config.ts @@ -46,7 +46,7 @@ export default defineConfig({ API_URL_V1: process.env.API_URL_V1, SITE_NAME: process.env.SITE_NAME, STATIC_BASE_URL: process.env.STATIC_BASE_URL, - S3_ENDPOINT: process.env.S3_ENDPOINT, + COG_URL: process.env.COG_URL, }, }, server: { From be69566ca5d470de189faa7c62874bc5bea54546 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Mon, 18 Nov 2024 10:10:39 +0545 Subject: [PATCH 135/390] feat: remove rio tiler package & update authord_id in project details endpoint --- src/backend/app/projects/project_routes.py | 34 +- src/backend/app/projects/project_schemas.py | 2 + src/backend/pdm.lock | 625 +++++++------------- src/backend/pyproject.toml | 1 - 4 files changed, 215 insertions(+), 447 deletions(-) diff --git a/src/backend/app/projects/project_routes.py b/src/backend/app/projects/project_routes.py index 32c25657..a9ab36d5 100644 --- a/src/backend/app/projects/project_routes.py +++ b/src/backend/app/projects/project_routes.py @@ -27,16 +27,14 @@ from app.projects import project_schemas, project_deps, project_logic, image_processing from app.db import database from app.models.enums import HTTPStatus, State -from app.s3 import get_cog_path, s3_client +from app.s3 import s3_client from app.config import settings from app.users.user_deps import login_required from app.users.user_schemas import AuthUser from app.tasks import task_schemas from app.utils import geojson_to_kml, timestamp from app.users import user_schemas -from rio_tiler.errors import TileOutsideBounds from minio.deleteobjects import DeleteObject -import asyncio router = APIRouter( @@ -584,33 +582,3 @@ async def odm_webhook( log.info(f"Task ID: {task_id}, Status: Webhook received") return {"message": "Webhook received", "task_id": task_id} - - -@router.get( - "/orthophoto/{z}/{x}/{y}.png", - tags=["Image Processing"], -) -async def get_orthophoto_tile( - project_id: str, - task_id: str, - z: int, - x: int, - y: int, -): - """ - Endpoint to serve COG tiles as PNG images with safer and more efficient handling. - """ - cog_path = get_cog_path(settings.S3_BUCKET_NAME, project_id, task_id) - - try: - # Use asyncio.to_thread to move blocking raster file I/O to a separate thread - tile = await asyncio.to_thread( - project_logic.read_tile_from_cog, cog_path, x, y, z - ) - return Response(content=tile, media_type="image/png") - - except TileOutsideBounds: - # Return a 204 No Content if tile is outside the bounds - return Response(status_code=204, content="") - except Exception as e: - raise HTTPException(status_code=500, detail=f"Unexpected error: {str(e)}") diff --git a/src/backend/app/projects/project_schemas.py b/src/backend/app/projects/project_schemas.py index ad183a45..caed48bb 100644 --- a/src/backend/app/projects/project_schemas.py +++ b/src/backend/app/projects/project_schemas.py @@ -199,6 +199,7 @@ class DbProject(BaseModel): is_terrain_follow: bool = False image_url: Optional[str] = None created_at: datetime + author_id: str async def one(db: Connection, project_id: uuid.UUID): """Get a single project & all associated tasks by ID.""" @@ -536,6 +537,7 @@ class ProjectInfo(BaseModel): completed_task_count: Optional[int] = 0 status: Optional[str] = "not-started" created_at: datetime + author_id: str @model_validator(mode="after") def set_image_url(cls, values): diff --git a/src/backend/pdm.lock b/src/backend/pdm.lock index d780989f..34c0aeda 100644 --- a/src/backend/pdm.lock +++ b/src/backend/pdm.lock @@ -5,21 +5,11 @@ groups = ["default", "debug", "dev", "docs", "monitoring", "test"] strategy = ["cross_platform"] lock_version = "4.5.0" -content_hash = "sha256:8888b73b062f86c4e1d3ef1525c6cb7c606849e6471a601c6f8a70893e38a0c9" +content_hash = "sha256:e524477903e8b42669f32cc8281c4d9bae68f5f8b21c21d9f2bf5a406bde42dd" [[metadata.targets]] requires_python = ">=3.11" -[[package]] -name = "affine" -version = "2.4.0" -requires_python = ">=3.7" -summary = "Matrices describing affine transformation of the plane" -files = [ - {file = "affine-2.4.0-py3-none-any.whl", hash = "sha256:8a3df80e2b2378aef598a83c1392efd47967afec4242021a0b06b4c7cbc61a92"}, - {file = "affine-2.4.0.tar.gz", hash = "sha256:a24d818d6a836c131976d22f8c27b8d3ca32d0af64c1d8d29deb7bafa4da1eea"}, -] - [[package]] name = "aiosmtplib" version = "3.0.2" @@ -32,7 +22,7 @@ files = [ [[package]] name = "alembic" -version = "1.13.3" +version = "1.14.0" requires_python = ">=3.8" summary = "A database migration tool for SQLAlchemy." dependencies = [ @@ -43,8 +33,8 @@ dependencies = [ "typing-extensions>=4", ] files = [ - {file = "alembic-1.13.3-py3-none-any.whl", hash = "sha256:908e905976d15235fae59c9ac42c4c5b75cfcefe3d27c0fbf7ae15a37715d80e"}, - {file = "alembic-1.13.3.tar.gz", hash = "sha256:203503117415561e203aa14541740643a611f641517f0209fcae63e9fa09f1a2"}, + {file = "alembic-1.14.0-py3-none-any.whl", hash = "sha256:99bd884ca390466db5e27ffccff1d179ec5c05c965cfefc0607e69f9e411cb25"}, + {file = "alembic-1.14.0.tar.gz", hash = "sha256:b00892b53b3642d0b8dbedba234dbf1924b69be83a9a769d5a624b01094e304b"}, ] [[package]] @@ -135,19 +125,6 @@ files = [ {file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"}, ] -[[package]] -name = "attrs" -version = "24.2.0" -requires_python = ">=3.7" -summary = "Classes Without Boilerplate" -dependencies = [ - "importlib-metadata; python_version < \"3.8\"", -] -files = [ - {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, - {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, -] - [[package]] name = "babel" version = "2.16.0" @@ -192,16 +169,6 @@ files = [ {file = "bcrypt-4.2.0.tar.gz", hash = "sha256:cf69eaf5185fd58f268f805b505ce31f9b9fc2d64b376642164e9244540c1221"}, ] -[[package]] -name = "cachetools" -version = "5.5.0" -requires_python = ">=3.7" -summary = "Extensible memoizing collections and decorators" -files = [ - {file = "cachetools-5.5.0-py3-none-any.whl", hash = "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292"}, - {file = "cachetools-5.5.0.tar.gz", hash = "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a"}, -] - [[package]] name = "certifi" version = "2024.8.30" @@ -337,55 +304,6 @@ files = [ {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, ] -[[package]] -name = "click-plugins" -version = "1.1.1" -summary = "An extension module for click to enable registering CLI commands via setuptools entry-points." -dependencies = [ - "click>=4.0", -] -files = [ - {file = "click-plugins-1.1.1.tar.gz", hash = "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b"}, - {file = "click_plugins-1.1.1-py2.py3-none-any.whl", hash = "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8"}, -] - -[[package]] -name = "cligj" -version = "0.7.2" -requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, <4" -summary = "Click params for commmand line interfaces to GeoJSON" -dependencies = [ - "click>=4.0", -] -files = [ - {file = "cligj-0.7.2-py3-none-any.whl", hash = "sha256:c1ca117dbce1fe20a5809dc96f01e1c2840f6dcc939b3ddbb1111bf330ba82df"}, - {file = "cligj-0.7.2.tar.gz", hash = "sha256:a4bc13d623356b373c2c27c53dbd9c68cae5d526270bfa71f6c6fa69669c6b27"}, -] - -[[package]] -name = "color-operations" -version = "0.1.6" -requires_python = ">=3.8" -summary = "Apply basic color-oriented image operations." -dependencies = [ - "numpy", -] -files = [ - {file = "color_operations-0.1.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:65662664bb1d39e4d48a16ccd010e4fd2281a5abb7102ebf1d65245319ee1268"}, - {file = "color_operations-0.1.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6faaa11e03fa88cdf3564a6abaadd02068c7f88df968cefa3bd33d1a1e30d6c2"}, - {file = "color_operations-0.1.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fbe49f8b91ed0c93dd1c5ec4baa144fcfe6a70ecaa81d9ca8c8ae2ad84dc560e"}, - {file = "color_operations-0.1.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3770e4e7bd0a972a65c5df313d5e32532db42b2f10898c417f769de93a7ba167"}, - {file = "color_operations-0.1.6-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6d499de4d820183e9a0599b6e9ad445b7bc84c50c9162e7c3ba05660c34a668"}, - {file = "color_operations-0.1.6-cp311-cp311-win_amd64.whl", hash = "sha256:5c6d35dc7c194595b1391e0ccc2e38cbd7cb87be37dd27ed49a058bb7c1a5442"}, - {file = "color_operations-0.1.6-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:906316d4e67d057496d4547a8050f1c555c49d712e0f4f79908ee5da8ca7aef3"}, - {file = "color_operations-0.1.6-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e6fce57bcda78a871b58b30df05b478c4b2da9736ef500554bb1c9c41e02aca2"}, - {file = "color_operations-0.1.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c0d3fb1085d83f0082a223901a91325a68b8d03b10ed9d40881d4489dcc641f0"}, - {file = "color_operations-0.1.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:715672ee6d827d4b068f7558f9e473de54eafced3c9a195641b0cf39d9aea700"}, - {file = "color_operations-0.1.6-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59b6fea23da0d19afc15bb56c4707275d5ac6c7fd27936c5c64fcdf628c82a53"}, - {file = "color_operations-0.1.6-cp312-cp312-win_amd64.whl", hash = "sha256:375226cdc52b8b3fe576efb47e0fb4b3dc2c9a8ecbb82c208e86df7153a76882"}, - {file = "color_operations-0.1.6.tar.gz", hash = "sha256:9b5ff7409d189b8254a3524fc78202e2db4021be973592875d61722abe027ec6"}, -] - [[package]] name = "colorama" version = "0.4.6" @@ -398,7 +316,7 @@ files = [ [[package]] name = "commitizen" -version = "3.30.0" +version = "3.31.0" requires_python = ">=3.8" summary = "Python commitizen client tool" dependencies = [ @@ -416,57 +334,57 @@ dependencies = [ "typing-extensions<5.0.0,>=4.0.1; python_version < \"3.8\"", ] files = [ - {file = "commitizen-3.30.0-py3-none-any.whl", hash = "sha256:8dc226a136aee61207e396101fcd89e73de67a57c06e066db982310863caaf65"}, - {file = "commitizen-3.30.0.tar.gz", hash = "sha256:ae67a47c1a700b4f35ac12de0c35c7ba96f152b9377d22b6226bb87372c527b0"}, + {file = "commitizen-3.31.0-py3-none-any.whl", hash = "sha256:a28df7ab5b8665d48796c422a97dcfae0d0fce7e2d28404c0e386cf1ebd42c8f"}, + {file = "commitizen-3.31.0.tar.gz", hash = "sha256:6ab973e91d07c1e745c6c0efe6dd0708b1f6d8fd7e4ab5e7c773b5ceb3df4ff0"}, ] [[package]] name = "coverage" -version = "7.6.4" +version = "7.6.7" requires_python = ">=3.9" summary = "Code coverage measurement for Python" files = [ - {file = "coverage-7.6.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:73d2b73584446e66ee633eaad1a56aad577c077f46c35ca3283cd687b7715b0b"}, - {file = "coverage-7.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51b44306032045b383a7a8a2c13878de375117946d68dcb54308111f39775a25"}, - {file = "coverage-7.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b3fb02fe73bed561fa12d279a417b432e5b50fe03e8d663d61b3d5990f29546"}, - {file = "coverage-7.6.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed8fe9189d2beb6edc14d3ad19800626e1d9f2d975e436f84e19efb7fa19469b"}, - {file = "coverage-7.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b369ead6527d025a0fe7bd3864e46dbee3aa8f652d48df6174f8d0bac9e26e0e"}, - {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ade3ca1e5f0ff46b678b66201f7ff477e8fa11fb537f3b55c3f0568fbfe6e718"}, - {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:27fb4a050aaf18772db513091c9c13f6cb94ed40eacdef8dad8411d92d9992db"}, - {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4f704f0998911abf728a7783799444fcbbe8261c4a6c166f667937ae6a8aa522"}, - {file = "coverage-7.6.4-cp311-cp311-win32.whl", hash = "sha256:29155cd511ee058e260db648b6182c419422a0d2e9a4fa44501898cf918866cf"}, - {file = "coverage-7.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:8902dd6a30173d4ef09954bfcb24b5d7b5190cf14a43170e386979651e09ba19"}, - {file = "coverage-7.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12394842a3a8affa3ba62b0d4ab7e9e210c5e366fbac3e8b2a68636fb19892c2"}, - {file = "coverage-7.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b6b4c83d8e8ea79f27ab80778c19bc037759aea298da4b56621f4474ffeb117"}, - {file = "coverage-7.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d5b8007f81b88696d06f7df0cb9af0d3b835fe0c8dbf489bad70b45f0e45613"}, - {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b57b768feb866f44eeed9f46975f3d6406380275c5ddfe22f531a2bf187eda27"}, - {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5915fcdec0e54ee229926868e9b08586376cae1f5faa9bbaf8faf3561b393d52"}, - {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b58c672d14f16ed92a48db984612f5ce3836ae7d72cdd161001cc54512571f2"}, - {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2fdef0d83a2d08d69b1f2210a93c416d54e14d9eb398f6ab2f0a209433db19e1"}, - {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cf717ee42012be8c0cb205dbbf18ffa9003c4cbf4ad078db47b95e10748eec5"}, - {file = "coverage-7.6.4-cp312-cp312-win32.whl", hash = "sha256:7bb92c539a624cf86296dd0c68cd5cc286c9eef2d0c3b8b192b604ce9de20a17"}, - {file = "coverage-7.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:1032e178b76a4e2b5b32e19d0fd0abbce4b58e77a1ca695820d10e491fa32b08"}, - {file = "coverage-7.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:023bf8ee3ec6d35af9c1c6ccc1d18fa69afa1cb29eaac57cb064dbb262a517f9"}, - {file = "coverage-7.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0ac3d42cb51c4b12df9c5f0dd2f13a4f24f01943627120ec4d293c9181219ba"}, - {file = "coverage-7.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8fe4984b431f8621ca53d9380901f62bfb54ff759a1348cd140490ada7b693c"}, - {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5fbd612f8a091954a0c8dd4c0b571b973487277d26476f8480bfa4b2a65b5d06"}, - {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dacbc52de979f2823a819571f2e3a350a7e36b8cb7484cdb1e289bceaf35305f"}, - {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dab4d16dfef34b185032580e2f2f89253d302facba093d5fa9dbe04f569c4f4b"}, - {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:862264b12ebb65ad8d863d51f17758b1684560b66ab02770d4f0baf2ff75da21"}, - {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5beb1ee382ad32afe424097de57134175fea3faf847b9af002cc7895be4e2a5a"}, - {file = "coverage-7.6.4-cp313-cp313-win32.whl", hash = "sha256:bf20494da9653f6410213424f5f8ad0ed885e01f7e8e59811f572bdb20b8972e"}, - {file = "coverage-7.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:182e6cd5c040cec0a1c8d415a87b67ed01193ed9ad458ee427741c7d8513d963"}, - {file = "coverage-7.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a181e99301a0ae128493a24cfe5cfb5b488c4e0bf2f8702091473d033494d04f"}, - {file = "coverage-7.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:df57bdbeffe694e7842092c5e2e0bc80fff7f43379d465f932ef36f027179806"}, - {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bcd1069e710600e8e4cf27f65c90c7843fa8edfb4520fb0ccb88894cad08b11"}, - {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99b41d18e6b2a48ba949418db48159d7a2e81c5cc290fc934b7d2380515bd0e3"}, - {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1e54712ba3474f34b7ef7a41e65bd9037ad47916ccb1cc78769bae324c01a"}, - {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53d202fd109416ce011578f321460795abfe10bb901b883cafd9b3ef851bacfc"}, - {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:c48167910a8f644671de9f2083a23630fbf7a1cb70ce939440cd3328e0919f70"}, - {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc8ff50b50ce532de2fa7a7daae9dd12f0a699bfcd47f20945364e5c31799fef"}, - {file = "coverage-7.6.4-cp313-cp313t-win32.whl", hash = "sha256:b8d3a03d9bfcaf5b0141d07a88456bb6a4c3ce55c080712fec8418ef3610230e"}, - {file = "coverage-7.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:f3ddf056d3ebcf6ce47bdaf56142af51bb7fad09e4af310241e9db7a3a8022e1"}, - {file = "coverage-7.6.4.tar.gz", hash = "sha256:29fc0f17b1d3fea332f8001d4558f8214af7f1d87a345f3a133c901d60347c73"}, + {file = "coverage-7.6.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7e61b0e77ff4dddebb35a0e8bb5a68bf0f8b872407d8d9f0c726b65dfabe2469"}, + {file = "coverage-7.6.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1a5407a75ca4abc20d6252efeb238377a71ce7bda849c26c7a9bece8680a5d99"}, + {file = "coverage-7.6.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df002e59f2d29e889c37abd0b9ee0d0e6e38c24f5f55d71ff0e09e3412a340ec"}, + {file = "coverage-7.6.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:673184b3156cba06154825f25af33baa2671ddae6343f23175764e65a8c4c30b"}, + {file = "coverage-7.6.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e69ad502f1a2243f739f5bd60565d14a278be58be4c137d90799f2c263e7049a"}, + {file = "coverage-7.6.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60dcf7605c50ea72a14490d0756daffef77a5be15ed1b9fea468b1c7bda1bc3b"}, + {file = "coverage-7.6.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9c2eb378bebb2c8f65befcb5147877fc1c9fbc640fc0aad3add759b5df79d55d"}, + {file = "coverage-7.6.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3c0317288f032221d35fa4cbc35d9f4923ff0dfd176c79c9b356e8ef8ef2dff4"}, + {file = "coverage-7.6.7-cp311-cp311-win32.whl", hash = "sha256:951aade8297358f3618a6e0660dc74f6b52233c42089d28525749fc8267dccd2"}, + {file = "coverage-7.6.7-cp311-cp311-win_amd64.whl", hash = "sha256:5e444b8e88339a2a67ce07d41faabb1d60d1004820cee5a2c2b54e2d8e429a0f"}, + {file = "coverage-7.6.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f07ff574986bc3edb80e2c36391678a271d555f91fd1d332a1e0f4b5ea4b6ea9"}, + {file = "coverage-7.6.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:49ed5ee4109258973630c1f9d099c7e72c5c36605029f3a91fe9982c6076c82b"}, + {file = "coverage-7.6.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3e8796434a8106b3ac025fd15417315d7a58ee3e600ad4dbcfddc3f4b14342c"}, + {file = "coverage-7.6.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3b925300484a3294d1c70f6b2b810d6526f2929de954e5b6be2bf8caa1f12c1"}, + {file = "coverage-7.6.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c42ec2c522e3ddd683dec5cdce8e62817afb648caedad9da725001fa530d354"}, + {file = "coverage-7.6.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0266b62cbea568bd5e93a4da364d05de422110cbed5056d69339bd5af5685433"}, + {file = "coverage-7.6.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e5f2a0f161d126ccc7038f1f3029184dbdf8f018230af17ef6fd6a707a5b881f"}, + {file = "coverage-7.6.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c132b5a22821f9b143f87446805e13580b67c670a548b96da945a8f6b4f2efbb"}, + {file = "coverage-7.6.7-cp312-cp312-win32.whl", hash = "sha256:7c07de0d2a110f02af30883cd7dddbe704887617d5c27cf373362667445a4c76"}, + {file = "coverage-7.6.7-cp312-cp312-win_amd64.whl", hash = "sha256:fd49c01e5057a451c30c9b892948976f5d38f2cbd04dc556a82743ba8e27ed8c"}, + {file = "coverage-7.6.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:46f21663e358beae6b368429ffadf14ed0a329996248a847a4322fb2e35d64d3"}, + {file = "coverage-7.6.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:40cca284c7c310d622a1677f105e8507441d1bb7c226f41978ba7c86979609ab"}, + {file = "coverage-7.6.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77256ad2345c29fe59ae861aa11cfc74579c88d4e8dbf121cbe46b8e32aec808"}, + {file = "coverage-7.6.7-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87ea64b9fa52bf395272e54020537990a28078478167ade6c61da7ac04dc14bc"}, + {file = "coverage-7.6.7-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d608a7808793e3615e54e9267519351c3ae204a6d85764d8337bd95993581a8"}, + {file = "coverage-7.6.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdd94501d65adc5c24f8a1a0eda110452ba62b3f4aeaba01e021c1ed9cb8f34a"}, + {file = "coverage-7.6.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:82c809a62e953867cf57e0548c2b8464207f5f3a6ff0e1e961683e79b89f2c55"}, + {file = "coverage-7.6.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bb684694e99d0b791a43e9fc0fa58efc15ec357ac48d25b619f207c41f2fd384"}, + {file = "coverage-7.6.7-cp313-cp313-win32.whl", hash = "sha256:963e4a08cbb0af6623e61492c0ec4c0ec5c5cf74db5f6564f98248d27ee57d30"}, + {file = "coverage-7.6.7-cp313-cp313-win_amd64.whl", hash = "sha256:14045b8bfd5909196a90da145a37f9d335a5d988a83db34e80f41e965fb7cb42"}, + {file = "coverage-7.6.7-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f2c7a045eef561e9544359a0bf5784b44e55cefc7261a20e730baa9220c83413"}, + {file = "coverage-7.6.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5dd4e4a49d9c72a38d18d641135d2fb0bdf7b726ca60a103836b3d00a1182acd"}, + {file = "coverage-7.6.7-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c95e0fa3d1547cb6f021ab72f5c23402da2358beec0a8e6d19a368bd7b0fb37"}, + {file = "coverage-7.6.7-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f63e21ed474edd23f7501f89b53280014436e383a14b9bd77a648366c81dce7b"}, + {file = "coverage-7.6.7-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ead9b9605c54d15be228687552916c89c9683c215370c4a44f1f217d2adcc34d"}, + {file = "coverage-7.6.7-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:0573f5cbf39114270842d01872952d301027d2d6e2d84013f30966313cadb529"}, + {file = "coverage-7.6.7-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:e2c8e3384c12dfa19fa9a52f23eb091a8fad93b5b81a41b14c17c78e23dd1d8b"}, + {file = "coverage-7.6.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:70a56a2ec1869e6e9fa69ef6b76b1a8a7ef709972b9cc473f9ce9d26b5997ce3"}, + {file = "coverage-7.6.7-cp313-cp313t-win32.whl", hash = "sha256:dbba8210f5067398b2c4d96b4e64d8fb943644d5eb70be0d989067c8ca40c0f8"}, + {file = "coverage-7.6.7-cp313-cp313t-win_amd64.whl", hash = "sha256:dfd14bcae0c94004baba5184d1c935ae0d1231b8409eb6c103a5fd75e8ecdc56"}, + {file = "coverage-7.6.7.tar.gz", hash = "sha256:d79d4826e41441c9a118ff045e4bccb9fdbdcb1d02413e7ea6eb5c87b5439d24"}, ] [[package]] @@ -484,24 +402,24 @@ files = [ [[package]] name = "debugpy" -version = "1.8.7" +version = "1.8.8" requires_python = ">=3.8" summary = "An implementation of the Debug Adapter Protocol for Python" files = [ - {file = "debugpy-1.8.7-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:caf528ff9e7308b74a1749c183d6808ffbedbb9fb6af78b033c28974d9b8831f"}, - {file = "debugpy-1.8.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cba1d078cf2e1e0b8402e6bda528bf8fda7ccd158c3dba6c012b7897747c41a0"}, - {file = "debugpy-1.8.7-cp311-cp311-win32.whl", hash = "sha256:171899588bcd412151e593bd40d9907133a7622cd6ecdbdb75f89d1551df13c2"}, - {file = "debugpy-1.8.7-cp311-cp311-win_amd64.whl", hash = "sha256:6e1c4ffb0c79f66e89dfd97944f335880f0d50ad29525dc792785384923e2211"}, - {file = "debugpy-1.8.7-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:4d27d842311353ede0ad572600c62e4bcd74f458ee01ab0dd3a1a4457e7e3706"}, - {file = "debugpy-1.8.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:703c1fd62ae0356e194f3e7b7a92acd931f71fe81c4b3be2c17a7b8a4b546ec2"}, - {file = "debugpy-1.8.7-cp312-cp312-win32.whl", hash = "sha256:2f729228430ef191c1e4df72a75ac94e9bf77413ce5f3f900018712c9da0aaca"}, - {file = "debugpy-1.8.7-cp312-cp312-win_amd64.whl", hash = "sha256:45c30aaefb3e1975e8a0258f5bbd26cd40cde9bfe71e9e5a7ac82e79bad64e39"}, - {file = "debugpy-1.8.7-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:d050a1ec7e925f514f0f6594a1e522580317da31fbda1af71d1530d6ea1f2b40"}, - {file = "debugpy-1.8.7-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2f4349a28e3228a42958f8ddaa6333d6f8282d5edaea456070e48609c5983b7"}, - {file = "debugpy-1.8.7-cp313-cp313-win32.whl", hash = "sha256:11ad72eb9ddb436afb8337891a986302e14944f0f755fd94e90d0d71e9100bba"}, - {file = "debugpy-1.8.7-cp313-cp313-win_amd64.whl", hash = "sha256:2efb84d6789352d7950b03d7f866e6d180284bc02c7e12cb37b489b7083d81aa"}, - {file = "debugpy-1.8.7-py2.py3-none-any.whl", hash = "sha256:57b00de1c8d2c84a61b90880f7e5b6deaf4c312ecbde3a0e8912f2a56c4ac9ae"}, - {file = "debugpy-1.8.7.zip", hash = "sha256:18b8f731ed3e2e1df8e9cdaa23fb1fc9c24e570cd0081625308ec51c82efe42e"}, + {file = "debugpy-1.8.8-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:c399023146e40ae373753a58d1be0a98bf6397fadc737b97ad612886b53df318"}, + {file = "debugpy-1.8.8-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09cc7b162586ea2171eea055985da2702b0723f6f907a423c9b2da5996ad67ba"}, + {file = "debugpy-1.8.8-cp311-cp311-win32.whl", hash = "sha256:eea8821d998ebeb02f0625dd0d76839ddde8cbf8152ebbe289dd7acf2cdc6b98"}, + {file = "debugpy-1.8.8-cp311-cp311-win_amd64.whl", hash = "sha256:d4483836da2a533f4b1454dffc9f668096ac0433de855f0c22cdce8c9f7e10c4"}, + {file = "debugpy-1.8.8-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:0cc94186340be87b9ac5a707184ec8f36547fb66636d1029ff4f1cc020e53996"}, + {file = "debugpy-1.8.8-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64674e95916e53c2e9540a056e5f489e0ad4872645399d778f7c598eacb7b7f9"}, + {file = "debugpy-1.8.8-cp312-cp312-win32.whl", hash = "sha256:5c6e885dbf12015aed73770f29dec7023cb310d0dc2ba8bfbeb5c8e43f80edc9"}, + {file = "debugpy-1.8.8-cp312-cp312-win_amd64.whl", hash = "sha256:19ffbd84e757a6ca0113574d1bf5a2298b3947320a3e9d7d8dc3377f02d9f864"}, + {file = "debugpy-1.8.8-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:705cd123a773d184860ed8dae99becd879dfec361098edbefb5fc0d3683eb804"}, + {file = "debugpy-1.8.8-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:890fd16803f50aa9cb1a9b9b25b5ec321656dd6b78157c74283de241993d086f"}, + {file = "debugpy-1.8.8-cp313-cp313-win32.whl", hash = "sha256:90244598214bbe704aa47556ec591d2f9869ff9e042e301a2859c57106649add"}, + {file = "debugpy-1.8.8-cp313-cp313-win_amd64.whl", hash = "sha256:4b93e4832fd4a759a0c465c967214ed0c8a6e8914bced63a28ddb0dd8c5f078b"}, + {file = "debugpy-1.8.8-py2.py3-none-any.whl", hash = "sha256:ec684553aba5b4066d4de510859922419febc710df7bba04fe9e7ef3de15d34f"}, + {file = "debugpy-1.8.8.zip", hash = "sha256:e6355385db85cbd666be703a96ab7351bc9e6c61d694893206f8001e22aee091"}, ] [[package]] @@ -516,15 +434,15 @@ files = [ [[package]] name = "deprecated" -version = "1.2.14" -requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.2.15" +requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" summary = "Python @deprecated decorator to deprecate old python classes, functions or methods." dependencies = [ "wrapt<2,>=1.10", ] files = [ - {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, - {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, + {file = "Deprecated-1.2.15-py2.py3-none-any.whl", hash = "sha256:353bc4a8ac4bfc96800ddab349d89c25dec1079f65fd53acdcc1e0b975b21320"}, + {file = "deprecated-1.2.15.tar.gz", hash = "sha256:683e561a90de76239796e6b6feac66b99030d2dd3fcf61ef996330f14bbb9b0d"}, ] [[package]] @@ -757,7 +675,7 @@ files = [ [[package]] name = "httpcore" -version = "1.0.6" +version = "1.0.7" requires_python = ">=3.8" summary = "A minimal low-level HTTP client." dependencies = [ @@ -765,8 +683,8 @@ dependencies = [ "h11<0.15,>=0.13", ] files = [ - {file = "httpcore-1.0.6-py3-none-any.whl", hash = "sha256:27b59625743b85577a8c0e10e55b50b5368a4f2cfe8cc7bcfa9cf00829c2682f"}, - {file = "httpcore-1.0.6.tar.gz", hash = "sha256:73f6dbd6eb8c21bbf7ef8efad555481853f5f6acdeaff1edb0694289269ee17f"}, + {file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"}, + {file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"}, ] [[package]] @@ -788,12 +706,12 @@ files = [ [[package]] name = "identify" -version = "2.6.1" -requires_python = ">=3.8" +version = "2.6.2" +requires_python = ">=3.9" summary = "File identification library for Python" files = [ - {file = "identify-2.6.1-py2.py3-none-any.whl", hash = "sha256:53863bcac7caf8d2ed85bd20312ea5dcfc22226800f6d6881f232d861db5a8f0"}, - {file = "identify-2.6.1.tar.gz", hash = "sha256:91478c5fb7c3aac5ff7bf9b4344f803843dc586832d5f110d672b19aa1984c98"}, + {file = "identify-2.6.2-py2.py3-none-any.whl", hash = "sha256:c097384259f49e372f4ea00a19719d95ae27dd5ff0fd77ad630aa891306b82f3"}, + {file = "identify-2.6.2.tar.gz", hash = "sha256:fab5c716c24d7a789775228823797296a2994b075fb6080ac83a102772a98cbd"}, ] [[package]] @@ -808,16 +726,16 @@ files = [ [[package]] name = "importlib-metadata" -version = "8.4.0" +version = "8.5.0" requires_python = ">=3.8" summary = "Read metadata from Python packages" dependencies = [ "typing-extensions>=3.6.4; python_version < \"3.8\"", - "zipp>=0.5", + "zipp>=3.20", ] files = [ - {file = "importlib_metadata-8.4.0-py3-none-any.whl", hash = "sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1"}, - {file = "importlib_metadata-8.4.0.tar.gz", hash = "sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5"}, + {file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"}, + {file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"}, ] [[package]] @@ -1101,7 +1019,7 @@ files = [ [[package]] name = "mkdocstrings" -version = "0.26.2" +version = "0.27.0" requires_python = ">=3.9" summary = "Automatic documentation from sources, for MkDocs." dependencies = [ @@ -1117,8 +1035,8 @@ dependencies = [ "typing-extensions>=4.1; python_version < \"3.10\"", ] files = [ - {file = "mkdocstrings-0.26.2-py3-none-any.whl", hash = "sha256:1248f3228464f3b8d1a15bd91249ce1701fe3104ac517a5f167a0e01ca850ba5"}, - {file = "mkdocstrings-0.26.2.tar.gz", hash = "sha256:34a8b50f1e6cfd29546c6c09fbe02154adfb0b361bb758834bf56aa284ba876e"}, + {file = "mkdocstrings-0.27.0-py3-none-any.whl", hash = "sha256:6ceaa7ea830770959b55a16203ac63da24badd71325b96af950e59fd37366332"}, + {file = "mkdocstrings-0.27.0.tar.gz", hash = "sha256:16adca6d6b0a1f9e0c07ff0b02ced8e16f228a9d65a37c063ec4c14d7b76a657"}, ] [[package]] @@ -1136,21 +1054,6 @@ files = [ {file = "mkdocstrings_python-1.12.2.tar.gz", hash = "sha256:7a1760941c0b52a2cd87b960a9e21112ffe52e7df9d0b9583d04d47ed2e186f3"}, ] -[[package]] -name = "morecantile" -version = "6.1.0" -requires_python = ">=3.8" -summary = "Construct and use map tile grids (a.k.a TileMatrixSet / TMS)." -dependencies = [ - "attrs", - "pydantic~=2.0", - "pyproj~=3.1", -] -files = [ - {file = "morecantile-6.1.0-py3-none-any.whl", hash = "sha256:2c8bfb79298b3b27efba8c734f01ea32b7af859153f553b3e3f6a67258b3b001"}, - {file = "morecantile-6.1.0.tar.gz", hash = "sha256:4445c6fbf741f3ee5d0130d18ec65c917e6d9f98e98a8f9d4a8a60d39c0c3b0a"}, -] - [[package]] name = "nodeenv" version = "1.9.1" @@ -1161,32 +1064,6 @@ files = [ {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, ] -[[package]] -name = "numexpr" -version = "2.10.1" -requires_python = ">=3.9" -summary = "Fast numerical expression evaluator for NumPy" -dependencies = [ - "numpy>=1.23.0", -] -files = [ - {file = "numexpr-2.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a3c0b0bf165b2d886eb981afa4e77873ca076f5d51c491c4d7b8fc10f17c876f"}, - {file = "numexpr-2.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56648a04679063175681195670ad53e5c8ca19668166ed13875199b5600089c7"}, - {file = "numexpr-2.10.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce04ae6efe2a9d0be1a0e114115c3ae70c68b8b8fbc615c5c55c15704b01e6a4"}, - {file = "numexpr-2.10.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:45f598182b4f5c153222e47d5163c3bee8d5ebcaee7e56dd2a5898d4d97e4473"}, - {file = "numexpr-2.10.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6a50370bea77ba94c3734a44781c716751354c6bfda2d369af3aed3d67d42871"}, - {file = "numexpr-2.10.1-cp311-cp311-win32.whl", hash = "sha256:fa4009d84a8e6e21790e718a80a22d57fe7f215283576ef2adc4183f7247f3c7"}, - {file = "numexpr-2.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:fcbf013bb8494e8ef1d11fa3457827c1571c6a3153982d709e5d17594999d4dd"}, - {file = "numexpr-2.10.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:82fc95c301b15ff4823f98989ee363a2d5555d16a7cfd3710e98ddee726eaaaa"}, - {file = "numexpr-2.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cbf79fef834f88607f977ab9867061dcd9b40ccb08bb28547c6dc6c73e560895"}, - {file = "numexpr-2.10.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:552c8d4b2e3b87cdb2abb40a781b9a61a9090a9f66ac7357fc5a0b93aff76be3"}, - {file = "numexpr-2.10.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22cc65e9121aeb3187a2b50827715b2b087ea70e8ab21416ea52662322087b43"}, - {file = "numexpr-2.10.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:00204e5853713b5eba5f3d0bc586a5d8d07f76011b597c8b4087592cc2ec2928"}, - {file = "numexpr-2.10.1-cp312-cp312-win32.whl", hash = "sha256:82bf04a1495ac475de4ab49fbe0a3a2710ed3fd1a00bc03847316b5d7602402d"}, - {file = "numexpr-2.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:300e577b3c006dd7a8270f1bb2e8a00ee15bf235b1650fe2a6febec2954bc2c3"}, - {file = "numexpr-2.10.1.tar.gz", hash = "sha256:9bba99d354a65f1a008ab8b87f07d84404c668e66bab624df5b6b5373403cf81"}, -] - [[package]] name = "numpy" version = "1.26.4" @@ -1224,190 +1101,191 @@ files = [ [[package]] name = "opentelemetry-api" -version = "1.27.0" +version = "1.28.1" requires_python = ">=3.8" summary = "OpenTelemetry Python API" dependencies = [ "deprecated>=1.2.6", - "importlib-metadata<=8.4.0,>=6.0", + "importlib-metadata<=8.5.0,>=6.0", ] files = [ - {file = "opentelemetry_api-1.27.0-py3-none-any.whl", hash = "sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7"}, - {file = "opentelemetry_api-1.27.0.tar.gz", hash = "sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342"}, + {file = "opentelemetry_api-1.28.1-py3-none-any.whl", hash = "sha256:bfe86c95576cf19a914497f439fd79c9553a38de0adbdc26f7cfc46b0c00b16c"}, + {file = "opentelemetry_api-1.28.1.tar.gz", hash = "sha256:6fa7295a12c707f5aebef82da3d9ec5afe6992f3e42bfe7bec0339a44b3518e7"}, ] [[package]] name = "opentelemetry-distro" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "OpenTelemetry Python Distro" dependencies = [ "opentelemetry-api~=1.12", - "opentelemetry-instrumentation==0.48b0", + "opentelemetry-instrumentation==0.49b1", "opentelemetry-sdk~=1.13", ] files = [ - {file = "opentelemetry_distro-0.48b0-py3-none-any.whl", hash = "sha256:b2f8fce114325b020769af3b9bf503efb8af07efc190bd1b9deac7843171664a"}, - {file = "opentelemetry_distro-0.48b0.tar.gz", hash = "sha256:5cb15915780ac4972583286a56683d43bd4ca95371d72f5f3f179c8b0b2ddc91"}, + {file = "opentelemetry_distro-0.49b1-py3-none-any.whl", hash = "sha256:c3a87a4a284c3d7cb680b0f320cb8dba8358b5958f0df837e00db2fbd700a71f"}, + {file = "opentelemetry_distro-0.49b1.tar.gz", hash = "sha256:3eb644547170122ade8a24da8cc02d795f4ccec69a19ae9fe3a0e5b930e56917"}, ] [[package]] name = "opentelemetry-instrumentation" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python" dependencies = [ "opentelemetry-api~=1.4", - "setuptools>=16.0", + "opentelemetry-semantic-conventions==0.49b1", + "packaging>=18.0", "wrapt<2.0.0,>=1.0.0", ] files = [ - {file = "opentelemetry_instrumentation-0.48b0-py3-none-any.whl", hash = "sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44"}, - {file = "opentelemetry_instrumentation-0.48b0.tar.gz", hash = "sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35"}, + {file = "opentelemetry_instrumentation-0.49b1-py3-none-any.whl", hash = "sha256:0a9d3821736104013693ef3b8a9d29b41f2f3a81ee2d8c9288b52d62bae5747c"}, + {file = "opentelemetry_instrumentation-0.49b1.tar.gz", hash = "sha256:2d0e41181b7957ba061bb436b969ad90545ac3eba65f290830009b4264d2824e"}, ] [[package]] name = "opentelemetry-instrumentation-asgi" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "ASGI instrumentation for OpenTelemetry" dependencies = [ "asgiref~=3.0", "opentelemetry-api~=1.12", - "opentelemetry-instrumentation==0.48b0", - "opentelemetry-semantic-conventions==0.48b0", - "opentelemetry-util-http==0.48b0", + "opentelemetry-instrumentation==0.49b1", + "opentelemetry-semantic-conventions==0.49b1", + "opentelemetry-util-http==0.49b1", ] files = [ - {file = "opentelemetry_instrumentation_asgi-0.48b0-py3-none-any.whl", hash = "sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d"}, - {file = "opentelemetry_instrumentation_asgi-0.48b0.tar.gz", hash = "sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785"}, + {file = "opentelemetry_instrumentation_asgi-0.49b1-py3-none-any.whl", hash = "sha256:8dcbc438cb138789fcb20ae38b6e7f23088e066d77b54bae205c5744856603c6"}, + {file = "opentelemetry_instrumentation_asgi-0.49b1.tar.gz", hash = "sha256:d1a2b4cb76490be28bcad3c0f562c4b3c84157148c922ca298bb04ed9e36c005"}, ] [[package]] name = "opentelemetry-instrumentation-dbapi" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "OpenTelemetry Database API instrumentation" dependencies = [ "opentelemetry-api~=1.12", - "opentelemetry-instrumentation==0.48b0", - "opentelemetry-semantic-conventions==0.48b0", + "opentelemetry-instrumentation==0.49b1", + "opentelemetry-semantic-conventions==0.49b1", "wrapt<2.0.0,>=1.0.0", ] files = [ - {file = "opentelemetry_instrumentation_dbapi-0.48b0-py3-none-any.whl", hash = "sha256:0d11a73ecbf55b11e8fbc93e9e97366958b98ccb4b691c776b32e4b20b3ce8bb"}, - {file = "opentelemetry_instrumentation_dbapi-0.48b0.tar.gz", hash = "sha256:89821288199f4f5225e74543bf14addf9b1824b8b5f1e83ad0d9dafa844f33b0"}, + {file = "opentelemetry_instrumentation_dbapi-0.49b1-py3-none-any.whl", hash = "sha256:ff4fc87f6b6a8fd40bb383efabcdb94078ff6fc7e8f8bf1c501256fb4e8064ed"}, + {file = "opentelemetry_instrumentation_dbapi-0.49b1.tar.gz", hash = "sha256:aa19a0dc96a127b155778b7c3aa58d1db100e3c1b4be2b61cd7aa318af9079cd"}, ] [[package]] name = "opentelemetry-instrumentation-fastapi" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "OpenTelemetry FastAPI Instrumentation" dependencies = [ "opentelemetry-api~=1.12", - "opentelemetry-instrumentation-asgi==0.48b0", - "opentelemetry-instrumentation==0.48b0", - "opentelemetry-semantic-conventions==0.48b0", - "opentelemetry-util-http==0.48b0", + "opentelemetry-instrumentation-asgi==0.49b1", + "opentelemetry-instrumentation==0.49b1", + "opentelemetry-semantic-conventions==0.49b1", + "opentelemetry-util-http==0.49b1", ] files = [ - {file = "opentelemetry_instrumentation_fastapi-0.48b0-py3-none-any.whl", hash = "sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2"}, - {file = "opentelemetry_instrumentation_fastapi-0.48b0.tar.gz", hash = "sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2"}, + {file = "opentelemetry_instrumentation_fastapi-0.49b1-py3-none-any.whl", hash = "sha256:3398940102c8ef613b9c55fc4f179cc92413de456f6bec6eeb1995270de2b087"}, + {file = "opentelemetry_instrumentation_fastapi-0.49b1.tar.gz", hash = "sha256:13d9d4d70b4bb831468b8e40807353731cad7fbfaeedde0070d93bcb2c417b07"}, ] [[package]] name = "opentelemetry-instrumentation-logging" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "OpenTelemetry Logging instrumentation" dependencies = [ "opentelemetry-api~=1.12", - "opentelemetry-instrumentation==0.48b0", + "opentelemetry-instrumentation==0.49b1", ] files = [ - {file = "opentelemetry_instrumentation_logging-0.48b0-py3-none-any.whl", hash = "sha256:75e5357d9b8c12071a19e1fef664dc1f430ef45874445c324ba4439a00972dc0"}, - {file = "opentelemetry_instrumentation_logging-0.48b0.tar.gz", hash = "sha256:529eb13eedf57d6b2f94e20e996271db2957b817b9457fe4796365d6d4238dec"}, + {file = "opentelemetry_instrumentation_logging-0.49b1-py3-none-any.whl", hash = "sha256:65f632ea0b450b4a8517b31ccf48b011a36e6335d00c1cb0674204db33a35834"}, + {file = "opentelemetry_instrumentation_logging-0.49b1.tar.gz", hash = "sha256:65c2eabe9d7d29d153c3b80e445f8649693c7f6c8ce5add12dd0328e47f593c7"}, ] [[package]] name = "opentelemetry-instrumentation-psycopg2" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "OpenTelemetry psycopg2 instrumentation" dependencies = [ "opentelemetry-api~=1.12", - "opentelemetry-instrumentation-dbapi==0.48b0", - "opentelemetry-instrumentation==0.48b0", + "opentelemetry-instrumentation-dbapi==0.49b1", + "opentelemetry-instrumentation==0.49b1", ] files = [ - {file = "opentelemetry_instrumentation_psycopg2-0.48b0-py3-none-any.whl", hash = "sha256:6a935f33b3d8908bee29b6b178bf84e56d93902c31282714113ffec922056aa4"}, - {file = "opentelemetry_instrumentation_psycopg2-0.48b0.tar.gz", hash = "sha256:f86c8d15deefe80475d9778ddc425e1ae56b325ecb32653e2ad0f78abef1717d"}, + {file = "opentelemetry_instrumentation_psycopg2-0.49b1-py3-none-any.whl", hash = "sha256:6472cd8cea96f14c979a3a7b799f8d3cc7ebb615bcd2a725a6f82eeda0b71d55"}, + {file = "opentelemetry_instrumentation_psycopg2-0.49b1.tar.gz", hash = "sha256:de986a39f98d86a4193ed1b69f744333daae28d9706eeb7408fddebebad836d7"}, ] [[package]] name = "opentelemetry-instrumentation-requests" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "OpenTelemetry requests instrumentation" dependencies = [ "opentelemetry-api~=1.12", - "opentelemetry-instrumentation==0.48b0", - "opentelemetry-semantic-conventions==0.48b0", - "opentelemetry-util-http==0.48b0", + "opentelemetry-instrumentation==0.49b1", + "opentelemetry-semantic-conventions==0.49b1", + "opentelemetry-util-http==0.49b1", ] files = [ - {file = "opentelemetry_instrumentation_requests-0.48b0-py3-none-any.whl", hash = "sha256:d4f01852121d0bd4c22f14f429654a735611d4f7bf3cf93f244bdf1489b2233d"}, - {file = "opentelemetry_instrumentation_requests-0.48b0.tar.gz", hash = "sha256:67ab9bd877a0352ee0db4616c8b4ae59736ddd700c598ed907482d44f4c9a2b3"}, + {file = "opentelemetry_instrumentation_requests-0.49b1-py3-none-any.whl", hash = "sha256:4a7f8321f9cca5b4da3a96b63dde0c7a41775302f4e9e0267a775f9800efac59"}, + {file = "opentelemetry_instrumentation_requests-0.49b1.tar.gz", hash = "sha256:329726afd607e1078e80bc2fb43741bd73e77c2d36804d9250d965858df8bd36"}, ] [[package]] name = "opentelemetry-sdk" -version = "1.27.0" +version = "1.28.1" requires_python = ">=3.8" summary = "OpenTelemetry Python SDK" dependencies = [ - "opentelemetry-api==1.27.0", - "opentelemetry-semantic-conventions==0.48b0", + "opentelemetry-api==1.28.1", + "opentelemetry-semantic-conventions==0.49b1", "typing-extensions>=3.7.4", ] files = [ - {file = "opentelemetry_sdk-1.27.0-py3-none-any.whl", hash = "sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d"}, - {file = "opentelemetry_sdk-1.27.0.tar.gz", hash = "sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f"}, + {file = "opentelemetry_sdk-1.28.1-py3-none-any.whl", hash = "sha256:72aad7f5fcbe37113c4ab4899f6cdeb6ac77ed3e62f25a85e3627b12583dad0f"}, + {file = "opentelemetry_sdk-1.28.1.tar.gz", hash = "sha256:100fa371b2046ffba6a340c18f0b2a0463acad7461e5177e126693b613a6ca57"}, ] [[package]] name = "opentelemetry-semantic-conventions" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "OpenTelemetry Semantic Conventions" dependencies = [ "deprecated>=1.2.6", - "opentelemetry-api==1.27.0", + "opentelemetry-api==1.28.1", ] files = [ - {file = "opentelemetry_semantic_conventions-0.48b0-py3-none-any.whl", hash = "sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f"}, - {file = "opentelemetry_semantic_conventions-0.48b0.tar.gz", hash = "sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a"}, + {file = "opentelemetry_semantic_conventions-0.49b1-py3-none-any.whl", hash = "sha256:dd6f3ac8169d2198c752e1a63f827e5f5e110ae9b0ce33f2aad9a3baf0739743"}, + {file = "opentelemetry_semantic_conventions-0.49b1.tar.gz", hash = "sha256:91817883b159ffb94c2ca9548509c4fe0aafce7c24f437aa6ac3fc613aa9a758"}, ] [[package]] name = "opentelemetry-util-http" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "Web util for OpenTelemetry" files = [ - {file = "opentelemetry_util_http-0.48b0-py3-none-any.whl", hash = "sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb"}, - {file = "opentelemetry_util_http-0.48b0.tar.gz", hash = "sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c"}, + {file = "opentelemetry_util_http-0.49b1-py3-none-any.whl", hash = "sha256:0290b942f7888b6310df6803e52e12f4043b8f224db0659f62dc7b70059eb94f"}, + {file = "opentelemetry_util_http-0.49b1.tar.gz", hash = "sha256:6c2bc6f7e20e286dbdfcccb9d895fa290ec9d7c596cdf2e06bf1d8e434b2edd0"}, ] [[package]] name = "packaging" -version = "24.1" +version = "24.2" requires_python = ">=3.8" summary = "Core utilities for Python packages" files = [ - {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, - {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, + {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, + {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, ] [[package]] @@ -1519,15 +1397,15 @@ files = [ [[package]] name = "psycopg-pool" -version = "3.2.3" +version = "3.2.4" requires_python = ">=3.8" summary = "Connection Pool for Psycopg" dependencies = [ "typing-extensions>=4.6", ] files = [ - {file = "psycopg_pool-3.2.3-py3-none-any.whl", hash = "sha256:53bd8e640625e01b2927b2ad96df8ed8e8f91caea4597d45e7673fc7bbb85eb1"}, - {file = "psycopg_pool-3.2.3.tar.gz", hash = "sha256:bb942f123bef4b7fbe4d55421bd3fb01829903c95c0f33fd42b7e94e5ac9b52a"}, + {file = "psycopg_pool-3.2.4-py3-none-any.whl", hash = "sha256:f6a22cff0f21f06d72fb2f5cb48c618946777c49385358e0c88d062c59cbd224"}, + {file = "psycopg_pool-3.2.4.tar.gz", hash = "sha256:61774b5bbf23e8d22bedc7504707135aaf744679f8ef9b3fe29942920746a6ed"}, ] [[package]] @@ -1731,12 +1609,12 @@ files = [ [[package]] name = "pyjwt" -version = "2.9.0" -requires_python = ">=3.8" +version = "2.10.0" +requires_python = ">=3.9" summary = "JSON Web Token implementation in Python" files = [ - {file = "PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850"}, - {file = "pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c"}, + {file = "PyJWT-2.10.0-py3-none-any.whl", hash = "sha256:543b77207db656de204372350926bed5a86201c4cbff159f623f79c7bb487a15"}, + {file = "pyjwt-2.10.0.tar.gz", hash = "sha256:7628a7eb7938959ac1b26e819a1df0fd3259505627b575e4bad6d08f76db695c"}, ] [[package]] @@ -1767,16 +1645,6 @@ files = [ {file = "pyodm-1.5.12.tar.gz", hash = "sha256:d0433182ac6d5587786391c91d0eeafe0d78c71d618336af78964620dafe87c4"}, ] -[[package]] -name = "pyparsing" -version = "3.2.0" -requires_python = ">=3.9" -summary = "pyparsing module - Classes and methods to define and execute parsing grammars" -files = [ - {file = "pyparsing-3.2.0-py3-none-any.whl", hash = "sha256:93d9577b88da0bbea8cc8334ee8b918ed014968fd2ec383e868fb8afb1ccef84"}, - {file = "pyparsing-3.2.0.tar.gz", hash = "sha256:cbf74e27246d595d9a74b186b810f6fbb86726dbf3b9532efb343f6d7294fe9c"}, -] - [[package]] name = "pyproj" version = "3.7.0" @@ -1807,19 +1675,6 @@ files = [ {file = "pyproj-3.7.0.tar.gz", hash = "sha256:bf658f4aaf815d9d03c8121650b6f0b8067265c36e31bc6660b98ef144d81813"}, ] -[[package]] -name = "pystac" -version = "1.11.0" -requires_python = ">=3.10" -summary = "Python library for working with the SpatioTemporal Asset Catalog (STAC) specification" -dependencies = [ - "python-dateutil>=2.7.0", -] -files = [ - {file = "pystac-1.11.0-py3-none-any.whl", hash = "sha256:10ac7c7b4ea6c5ec8333829a09ec1a33b596f02d1a97ffbbd72cd1b6c10598c1"}, - {file = "pystac-1.11.0.tar.gz", hash = "sha256:acb1e04be398a0cda2d8870ab5e90457783a8014a206590233171d8b2ae0d9e7"}, -] - [[package]] name = "pytest" version = "8.3.3" @@ -1968,90 +1823,58 @@ files = [ {file = "questionary-2.0.1.tar.gz", hash = "sha256:bcce898bf3dbb446ff62830c86c5c6fb9a22a54146f0f5597d3da43b10d8fc8b"}, ] -[[package]] -name = "rasterio" -version = "1.4.2" -requires_python = ">=3.9" -summary = "Fast and direct raster I/O for use with Numpy and SciPy" -dependencies = [ - "affine", - "attrs", - "certifi", - "click-plugins", - "click>=4.0", - "cligj>=0.5", - "importlib-metadata; python_version < \"3.10\"", - "numpy>=1.24", - "pyparsing", -] -files = [ - {file = "rasterio-1.4.2-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:019e6fbfea250fea91987a38abc7a02c752b50beadb3178d82a5d47e8e265313"}, - {file = "rasterio-1.4.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:a9830e0c9d09d2680079b8a31085cc2a2b885b1ed6c4d95d2a91e2813efc22aa"}, - {file = "rasterio-1.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea3f38da794e7a4df409f2c57799a26a777a2560025ad401fe33a0b8efe90a5a"}, - {file = "rasterio-1.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:0c74d6a2e64fae6c2293bf520fa4048e12598379736953c34ca3dfb058cedfc5"}, - {file = "rasterio-1.4.2-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:84ce104a3017c04bfb809f268faaef4287458916f7af4f25a39b93f420fa8ef4"}, - {file = "rasterio-1.4.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:856c740e621211a19f0efddc2f0a61cc3d37c89c50699ea6cb249da3930d601b"}, - {file = "rasterio-1.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43a21306c8dc265f50d3cb8a13a58d50e055477ace1003bb8a507658a4124c37"}, - {file = "rasterio-1.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:83bf03b39dc7e1d932907d1b05d99a53b7fc184c215a27b938f4697db7295f53"}, - {file = "rasterio-1.4.2-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:e405e92ab03f5606a959d4a7d9ae1589e2212f9720c2db55853bfa8c91f6d736"}, - {file = "rasterio-1.4.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:7dbf3d084e1f72f322d378eb2b9e155fbe0ead97f0a1b0065a389e9435a5a3db"}, - {file = "rasterio-1.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6f2952e1b4ad01f0dcf97f477050d8122ca781abbb3ef8b5a5751835a222317"}, - {file = "rasterio-1.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:25ec2a35548c1c45ea1dd5341e777e5aeea8f79310bbae6aaed4d5f6a4c53f26"}, - {file = "rasterio-1.4.2.tar.gz", hash = "sha256:1be35ccb4d998a4c48fa51bbee9e37927ecd9b9e954a2b2581b8f3e9bb165332"}, -] - [[package]] name = "regex" -version = "2024.9.11" +version = "2024.11.6" requires_python = ">=3.8" summary = "Alternative regular expression module, to replace re." files = [ - {file = "regex-2024.9.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2cce2449e5927a0bf084d346da6cd5eb016b2beca10d0013ab50e3c226ffc0df"}, - {file = "regex-2024.9.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3b37fa423beefa44919e009745ccbf353d8c981516e807995b2bd11c2c77d268"}, - {file = "regex-2024.9.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:64ce2799bd75039b480cc0360907c4fb2f50022f030bf9e7a8705b636e408fad"}, - {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4cc92bb6db56ab0c1cbd17294e14f5e9224f0cc6521167ef388332604e92679"}, - {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d05ac6fa06959c4172eccd99a222e1fbf17b5670c4d596cb1e5cde99600674c4"}, - {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:040562757795eeea356394a7fb13076ad4f99d3c62ab0f8bdfb21f99a1f85664"}, - {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6113c008a7780792efc80f9dfe10ba0cd043cbf8dc9a76ef757850f51b4edc50"}, - {file = "regex-2024.9.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e5fb5f77c8745a60105403a774fe2c1759b71d3e7b4ca237a5e67ad066c7199"}, - {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:54d9ff35d4515debf14bc27f1e3b38bfc453eff3220f5bce159642fa762fe5d4"}, - {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:df5cbb1fbc74a8305b6065d4ade43b993be03dbe0f8b30032cced0d7740994bd"}, - {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7fb89ee5d106e4a7a51bce305ac4efb981536301895f7bdcf93ec92ae0d91c7f"}, - {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a738b937d512b30bf75995c0159c0ddf9eec0775c9d72ac0202076c72f24aa96"}, - {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e28f9faeb14b6f23ac55bfbbfd3643f5c7c18ede093977f1df249f73fd22c7b1"}, - {file = "regex-2024.9.11-cp311-cp311-win32.whl", hash = "sha256:18e707ce6c92d7282dfce370cd205098384b8ee21544e7cb29b8aab955b66fa9"}, - {file = "regex-2024.9.11-cp311-cp311-win_amd64.whl", hash = "sha256:313ea15e5ff2a8cbbad96ccef6be638393041b0a7863183c2d31e0c6116688cf"}, - {file = "regex-2024.9.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b0d0a6c64fcc4ef9c69bd5b3b3626cc3776520a1637d8abaa62b9edc147a58f7"}, - {file = "regex-2024.9.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:49b0e06786ea663f933f3710a51e9385ce0cba0ea56b67107fd841a55d56a231"}, - {file = "regex-2024.9.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5b513b6997a0b2f10e4fd3a1313568e373926e8c252bd76c960f96fd039cd28d"}, - {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee439691d8c23e76f9802c42a95cfeebf9d47cf4ffd06f18489122dbb0a7ad64"}, - {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8f877c89719d759e52783f7fe6e1c67121076b87b40542966c02de5503ace42"}, - {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23b30c62d0f16827f2ae9f2bb87619bc4fba2044911e2e6c2eb1af0161cdb766"}, - {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85ab7824093d8f10d44330fe1e6493f756f252d145323dd17ab6b48733ff6c0a"}, - {file = "regex-2024.9.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8dee5b4810a89447151999428fe096977346cf2f29f4d5e29609d2e19e0199c9"}, - {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98eeee2f2e63edae2181c886d7911ce502e1292794f4c5ee71e60e23e8d26b5d"}, - {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:57fdd2e0b2694ce6fc2e5ccf189789c3e2962916fb38779d3e3521ff8fe7a822"}, - {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d552c78411f60b1fdaafd117a1fca2f02e562e309223b9d44b7de8be451ec5e0"}, - {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a0b2b80321c2ed3fcf0385ec9e51a12253c50f146fddb2abbb10f033fe3d049a"}, - {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:18406efb2f5a0e57e3a5881cd9354c1512d3bb4f5c45d96d110a66114d84d23a"}, - {file = "regex-2024.9.11-cp312-cp312-win32.whl", hash = "sha256:e464b467f1588e2c42d26814231edecbcfe77f5ac414d92cbf4e7b55b2c2a776"}, - {file = "regex-2024.9.11-cp312-cp312-win_amd64.whl", hash = "sha256:9e8719792ca63c6b8340380352c24dcb8cd7ec49dae36e963742a275dfae6009"}, - {file = "regex-2024.9.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c157bb447303070f256e084668b702073db99bbb61d44f85d811025fcf38f784"}, - {file = "regex-2024.9.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4db21ece84dfeefc5d8a3863f101995de646c6cb0536952c321a2650aa202c36"}, - {file = "regex-2024.9.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:220e92a30b426daf23bb67a7962900ed4613589bab80382be09b48896d211e92"}, - {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb1ae19e64c14c7ec1995f40bd932448713d3c73509e82d8cd7744dc00e29e86"}, - {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f47cd43a5bfa48f86925fe26fbdd0a488ff15b62468abb5d2a1e092a4fb10e85"}, - {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9d4a76b96f398697fe01117093613166e6aa8195d63f1b4ec3f21ab637632963"}, - {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ea51dcc0835eea2ea31d66456210a4e01a076d820e9039b04ae8d17ac11dee6"}, - {file = "regex-2024.9.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7aaa315101c6567a9a45d2839322c51c8d6e81f67683d529512f5bcfb99c802"}, - {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c57d08ad67aba97af57a7263c2d9006d5c404d721c5f7542f077f109ec2a4a29"}, - {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f8404bf61298bb6f8224bb9176c1424548ee1181130818fcd2cbffddc768bed8"}, - {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dd4490a33eb909ef5078ab20f5f000087afa2a4daa27b4c072ccb3cb3050ad84"}, - {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:eee9130eaad130649fd73e5cd92f60e55708952260ede70da64de420cdcad554"}, - {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6a2644a93da36c784e546de579ec1806bfd2763ef47babc1b03d765fe560c9f8"}, - {file = "regex-2024.9.11-cp313-cp313-win32.whl", hash = "sha256:e997fd30430c57138adc06bba4c7c2968fb13d101e57dd5bb9355bf8ce3fa7e8"}, - {file = "regex-2024.9.11-cp313-cp313-win_amd64.whl", hash = "sha256:042c55879cfeb21a8adacc84ea347721d3d83a159da6acdf1116859e2427c43f"}, - {file = "regex-2024.9.11.tar.gz", hash = "sha256:6c188c307e8433bcb63dc1915022deb553b4203a70722fc542c363bf120a01fd"}, + {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638"}, + {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7"}, + {file = "regex-2024.11.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45"}, + {file = "regex-2024.11.6-cp311-cp311-win32.whl", hash = "sha256:c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9"}, + {file = "regex-2024.11.6-cp311-cp311-win_amd64.whl", hash = "sha256:02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60"}, + {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a"}, + {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9"}, + {file = "regex-2024.11.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad"}, + {file = "regex-2024.11.6-cp312-cp312-win32.whl", hash = "sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54"}, + {file = "regex-2024.11.6-cp312-cp312-win_amd64.whl", hash = "sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b"}, + {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84"}, + {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4"}, + {file = "regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d"}, + {file = "regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff"}, + {file = "regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a"}, + {file = "regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519"}, ] [[package]] @@ -2097,33 +1920,9 @@ files = [ {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, ] -[[package]] -name = "rio-tiler" -version = "7.1.0" -requires_python = ">=3.8" -summary = "User friendly Rasterio plugin to read raster datasets." -dependencies = [ - "attrs", - "cachetools", - "color-operations", - "httpx", - "importlib-resources>=1.1.0; python_version < \"3.9\"", - "morecantile<7.0,>=5.0", - "numexpr", - "numpy", - "pydantic~=2.0", - "pystac>=0.5.4", - "rasterio>=1.3.0", - "typing-extensions", -] -files = [ - {file = "rio_tiler-7.1.0-py3-none-any.whl", hash = "sha256:28e22271a7ab22891c82a070eaf459498a52184bb749e8ba7b78917e78d2fe5d"}, - {file = "rio_tiler-7.1.0.tar.gz", hash = "sha256:4dfa60e441ef9e60706049ecb20f5fe2dd269ccdabcc7426ece1af98e903e8a9"}, -] - [[package]] name = "sentry-sdk" -version = "2.17.0" +version = "2.18.0" requires_python = ">=3.6" summary = "Python client for Sentry (https://sentry.io)" dependencies = [ @@ -2131,33 +1930,33 @@ dependencies = [ "urllib3>=1.26.11", ] files = [ - {file = "sentry_sdk-2.17.0-py2.py3-none-any.whl", hash = "sha256:625955884b862cc58748920f9e21efdfb8e0d4f98cca4ab0d3918576d5b606ad"}, - {file = "sentry_sdk-2.17.0.tar.gz", hash = "sha256:dd0a05352b78ffeacced73a94e86f38b32e2eae15fff5f30ca5abb568a72eacf"}, + {file = "sentry_sdk-2.18.0-py2.py3-none-any.whl", hash = "sha256:ee70e27d1bbe4cd52a38e1bd28a5fadb9b17bc29d91b5f2b97ae29c0a7610442"}, + {file = "sentry_sdk-2.18.0.tar.gz", hash = "sha256:0dc21febd1ab35c648391c664df96f5f79fb0d92d7d4225cd9832e53a617cafd"}, ] [[package]] name = "sentry-sdk" -version = "2.17.0" +version = "2.18.0" extras = ["opentelemetry"] requires_python = ">=3.6" summary = "Python client for Sentry (https://sentry.io)" dependencies = [ "opentelemetry-distro>=0.35b0", - "sentry-sdk==2.17.0", + "sentry-sdk==2.18.0", ] files = [ - {file = "sentry_sdk-2.17.0-py2.py3-none-any.whl", hash = "sha256:625955884b862cc58748920f9e21efdfb8e0d4f98cca4ab0d3918576d5b606ad"}, - {file = "sentry_sdk-2.17.0.tar.gz", hash = "sha256:dd0a05352b78ffeacced73a94e86f38b32e2eae15fff5f30ca5abb568a72eacf"}, + {file = "sentry_sdk-2.18.0-py2.py3-none-any.whl", hash = "sha256:ee70e27d1bbe4cd52a38e1bd28a5fadb9b17bc29d91b5f2b97ae29c0a7610442"}, + {file = "sentry_sdk-2.18.0.tar.gz", hash = "sha256:0dc21febd1ab35c648391c664df96f5f79fb0d92d7d4225cd9832e53a617cafd"}, ] [[package]] name = "setuptools" -version = "75.3.0" -requires_python = ">=3.8" +version = "75.5.0" +requires_python = ">=3.9" summary = "Easily download, build, install, upgrade, and uninstall Python packages" files = [ - {file = "setuptools-75.3.0-py3-none-any.whl", hash = "sha256:f2504966861356aa38616760c0f66568e535562374995367b4e69c7143cf6bcd"}, - {file = "setuptools-75.3.0.tar.gz", hash = "sha256:fba5dd4d766e97be1b1681d98712680ae8f2f26d7881245f2ce9e40714f1a686"}, + {file = "setuptools-75.5.0-py3-none-any.whl", hash = "sha256:87cb777c3b96d638ca02031192d40390e0ad97737e27b6b4fa831bea86f2f829"}, + {file = "setuptools-75.5.0.tar.gz", hash = "sha256:5c4ccb41111392671f02bb5f8436dfc5a9a7185e80500531b133f5775c4163ef"}, ] [[package]] @@ -2431,10 +2230,10 @@ files = [ [[package]] name = "zipp" -version = "3.20.2" -requires_python = ">=3.8" +version = "3.21.0" +requires_python = ">=3.9" summary = "Backport of pathlib-compatible object wrapper for zip files" files = [ - {file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"}, - {file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"}, + {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"}, + {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"}, ] diff --git a/src/backend/pyproject.toml b/src/backend/pyproject.toml index a4977e1d..dbcfd037 100644 --- a/src/backend/pyproject.toml +++ b/src/backend/pyproject.toml @@ -34,7 +34,6 @@ dependencies = [ "pyodm>=1.5.11", "asgiref>=3.8.1", "drone-flightplan>=0.3.1", - "rio-tiler>=7.0.0", ] requires-python = ">=3.11" license = {text = "GPL-3.0-only"} From 244f3463fb8dd7ced138812a79a1202c4b75639e Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Mon, 18 Nov 2024 10:19:00 +0545 Subject: [PATCH 136/390] feat: update author_id in project lists --- src/backend/app/projects/project_schemas.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/app/projects/project_schemas.py b/src/backend/app/projects/project_schemas.py index caed48bb..33e7309f 100644 --- a/src/backend/app/projects/project_schemas.py +++ b/src/backend/app/projects/project_schemas.py @@ -338,7 +338,7 @@ async def all( await cur.execute( """ SELECT - p.id, p.slug, p.name, p.description, p.per_task_instructions, p.created_at, + p.id, p.slug, p.name, p.description, p.per_task_instructions, p.created_at, p.author_id, ST_AsGeoJSON(p.outline)::jsonb AS outline, p.requires_approval_from_manager_for_locking, From 64a97753a5f376e4bb8355f5166f52db044b9129 Mon Sep 17 00:00:00 2001 From: Pradip Thapa Date: Mon, 18 Nov 2024 10:22:14 +0545 Subject: [PATCH 137/390] feat: remove rio-tiler package & update author_id in project details endpoint (#337) * feat: add reprojection of orthophoto to EPSG:3857 before uploading to S3 * docs: added docs string on image processing function * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * feat: added try-except to handle/track the error * feat: remove rio tiler package & update authord_id in project details endpoint * feat: update author_id in project lists --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- src/backend/app/projects/project_routes.py | 34 +- src/backend/app/projects/project_schemas.py | 4 +- src/backend/pdm.lock | 625 +++++++------------- src/backend/pyproject.toml | 1 - 4 files changed, 216 insertions(+), 448 deletions(-) diff --git a/src/backend/app/projects/project_routes.py b/src/backend/app/projects/project_routes.py index 32c25657..a9ab36d5 100644 --- a/src/backend/app/projects/project_routes.py +++ b/src/backend/app/projects/project_routes.py @@ -27,16 +27,14 @@ from app.projects import project_schemas, project_deps, project_logic, image_processing from app.db import database from app.models.enums import HTTPStatus, State -from app.s3 import get_cog_path, s3_client +from app.s3 import s3_client from app.config import settings from app.users.user_deps import login_required from app.users.user_schemas import AuthUser from app.tasks import task_schemas from app.utils import geojson_to_kml, timestamp from app.users import user_schemas -from rio_tiler.errors import TileOutsideBounds from minio.deleteobjects import DeleteObject -import asyncio router = APIRouter( @@ -584,33 +582,3 @@ async def odm_webhook( log.info(f"Task ID: {task_id}, Status: Webhook received") return {"message": "Webhook received", "task_id": task_id} - - -@router.get( - "/orthophoto/{z}/{x}/{y}.png", - tags=["Image Processing"], -) -async def get_orthophoto_tile( - project_id: str, - task_id: str, - z: int, - x: int, - y: int, -): - """ - Endpoint to serve COG tiles as PNG images with safer and more efficient handling. - """ - cog_path = get_cog_path(settings.S3_BUCKET_NAME, project_id, task_id) - - try: - # Use asyncio.to_thread to move blocking raster file I/O to a separate thread - tile = await asyncio.to_thread( - project_logic.read_tile_from_cog, cog_path, x, y, z - ) - return Response(content=tile, media_type="image/png") - - except TileOutsideBounds: - # Return a 204 No Content if tile is outside the bounds - return Response(status_code=204, content="") - except Exception as e: - raise HTTPException(status_code=500, detail=f"Unexpected error: {str(e)}") diff --git a/src/backend/app/projects/project_schemas.py b/src/backend/app/projects/project_schemas.py index ad183a45..33e7309f 100644 --- a/src/backend/app/projects/project_schemas.py +++ b/src/backend/app/projects/project_schemas.py @@ -199,6 +199,7 @@ class DbProject(BaseModel): is_terrain_follow: bool = False image_url: Optional[str] = None created_at: datetime + author_id: str async def one(db: Connection, project_id: uuid.UUID): """Get a single project & all associated tasks by ID.""" @@ -337,7 +338,7 @@ async def all( await cur.execute( """ SELECT - p.id, p.slug, p.name, p.description, p.per_task_instructions, p.created_at, + p.id, p.slug, p.name, p.description, p.per_task_instructions, p.created_at, p.author_id, ST_AsGeoJSON(p.outline)::jsonb AS outline, p.requires_approval_from_manager_for_locking, @@ -536,6 +537,7 @@ class ProjectInfo(BaseModel): completed_task_count: Optional[int] = 0 status: Optional[str] = "not-started" created_at: datetime + author_id: str @model_validator(mode="after") def set_image_url(cls, values): diff --git a/src/backend/pdm.lock b/src/backend/pdm.lock index d780989f..34c0aeda 100644 --- a/src/backend/pdm.lock +++ b/src/backend/pdm.lock @@ -5,21 +5,11 @@ groups = ["default", "debug", "dev", "docs", "monitoring", "test"] strategy = ["cross_platform"] lock_version = "4.5.0" -content_hash = "sha256:8888b73b062f86c4e1d3ef1525c6cb7c606849e6471a601c6f8a70893e38a0c9" +content_hash = "sha256:e524477903e8b42669f32cc8281c4d9bae68f5f8b21c21d9f2bf5a406bde42dd" [[metadata.targets]] requires_python = ">=3.11" -[[package]] -name = "affine" -version = "2.4.0" -requires_python = ">=3.7" -summary = "Matrices describing affine transformation of the plane" -files = [ - {file = "affine-2.4.0-py3-none-any.whl", hash = "sha256:8a3df80e2b2378aef598a83c1392efd47967afec4242021a0b06b4c7cbc61a92"}, - {file = "affine-2.4.0.tar.gz", hash = "sha256:a24d818d6a836c131976d22f8c27b8d3ca32d0af64c1d8d29deb7bafa4da1eea"}, -] - [[package]] name = "aiosmtplib" version = "3.0.2" @@ -32,7 +22,7 @@ files = [ [[package]] name = "alembic" -version = "1.13.3" +version = "1.14.0" requires_python = ">=3.8" summary = "A database migration tool for SQLAlchemy." dependencies = [ @@ -43,8 +33,8 @@ dependencies = [ "typing-extensions>=4", ] files = [ - {file = "alembic-1.13.3-py3-none-any.whl", hash = "sha256:908e905976d15235fae59c9ac42c4c5b75cfcefe3d27c0fbf7ae15a37715d80e"}, - {file = "alembic-1.13.3.tar.gz", hash = "sha256:203503117415561e203aa14541740643a611f641517f0209fcae63e9fa09f1a2"}, + {file = "alembic-1.14.0-py3-none-any.whl", hash = "sha256:99bd884ca390466db5e27ffccff1d179ec5c05c965cfefc0607e69f9e411cb25"}, + {file = "alembic-1.14.0.tar.gz", hash = "sha256:b00892b53b3642d0b8dbedba234dbf1924b69be83a9a769d5a624b01094e304b"}, ] [[package]] @@ -135,19 +125,6 @@ files = [ {file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"}, ] -[[package]] -name = "attrs" -version = "24.2.0" -requires_python = ">=3.7" -summary = "Classes Without Boilerplate" -dependencies = [ - "importlib-metadata; python_version < \"3.8\"", -] -files = [ - {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, - {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, -] - [[package]] name = "babel" version = "2.16.0" @@ -192,16 +169,6 @@ files = [ {file = "bcrypt-4.2.0.tar.gz", hash = "sha256:cf69eaf5185fd58f268f805b505ce31f9b9fc2d64b376642164e9244540c1221"}, ] -[[package]] -name = "cachetools" -version = "5.5.0" -requires_python = ">=3.7" -summary = "Extensible memoizing collections and decorators" -files = [ - {file = "cachetools-5.5.0-py3-none-any.whl", hash = "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292"}, - {file = "cachetools-5.5.0.tar.gz", hash = "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a"}, -] - [[package]] name = "certifi" version = "2024.8.30" @@ -337,55 +304,6 @@ files = [ {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, ] -[[package]] -name = "click-plugins" -version = "1.1.1" -summary = "An extension module for click to enable registering CLI commands via setuptools entry-points." -dependencies = [ - "click>=4.0", -] -files = [ - {file = "click-plugins-1.1.1.tar.gz", hash = "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b"}, - {file = "click_plugins-1.1.1-py2.py3-none-any.whl", hash = "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8"}, -] - -[[package]] -name = "cligj" -version = "0.7.2" -requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, <4" -summary = "Click params for commmand line interfaces to GeoJSON" -dependencies = [ - "click>=4.0", -] -files = [ - {file = "cligj-0.7.2-py3-none-any.whl", hash = "sha256:c1ca117dbce1fe20a5809dc96f01e1c2840f6dcc939b3ddbb1111bf330ba82df"}, - {file = "cligj-0.7.2.tar.gz", hash = "sha256:a4bc13d623356b373c2c27c53dbd9c68cae5d526270bfa71f6c6fa69669c6b27"}, -] - -[[package]] -name = "color-operations" -version = "0.1.6" -requires_python = ">=3.8" -summary = "Apply basic color-oriented image operations." -dependencies = [ - "numpy", -] -files = [ - {file = "color_operations-0.1.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:65662664bb1d39e4d48a16ccd010e4fd2281a5abb7102ebf1d65245319ee1268"}, - {file = "color_operations-0.1.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6faaa11e03fa88cdf3564a6abaadd02068c7f88df968cefa3bd33d1a1e30d6c2"}, - {file = "color_operations-0.1.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fbe49f8b91ed0c93dd1c5ec4baa144fcfe6a70ecaa81d9ca8c8ae2ad84dc560e"}, - {file = "color_operations-0.1.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3770e4e7bd0a972a65c5df313d5e32532db42b2f10898c417f769de93a7ba167"}, - {file = "color_operations-0.1.6-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6d499de4d820183e9a0599b6e9ad445b7bc84c50c9162e7c3ba05660c34a668"}, - {file = "color_operations-0.1.6-cp311-cp311-win_amd64.whl", hash = "sha256:5c6d35dc7c194595b1391e0ccc2e38cbd7cb87be37dd27ed49a058bb7c1a5442"}, - {file = "color_operations-0.1.6-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:906316d4e67d057496d4547a8050f1c555c49d712e0f4f79908ee5da8ca7aef3"}, - {file = "color_operations-0.1.6-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e6fce57bcda78a871b58b30df05b478c4b2da9736ef500554bb1c9c41e02aca2"}, - {file = "color_operations-0.1.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c0d3fb1085d83f0082a223901a91325a68b8d03b10ed9d40881d4489dcc641f0"}, - {file = "color_operations-0.1.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:715672ee6d827d4b068f7558f9e473de54eafced3c9a195641b0cf39d9aea700"}, - {file = "color_operations-0.1.6-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59b6fea23da0d19afc15bb56c4707275d5ac6c7fd27936c5c64fcdf628c82a53"}, - {file = "color_operations-0.1.6-cp312-cp312-win_amd64.whl", hash = "sha256:375226cdc52b8b3fe576efb47e0fb4b3dc2c9a8ecbb82c208e86df7153a76882"}, - {file = "color_operations-0.1.6.tar.gz", hash = "sha256:9b5ff7409d189b8254a3524fc78202e2db4021be973592875d61722abe027ec6"}, -] - [[package]] name = "colorama" version = "0.4.6" @@ -398,7 +316,7 @@ files = [ [[package]] name = "commitizen" -version = "3.30.0" +version = "3.31.0" requires_python = ">=3.8" summary = "Python commitizen client tool" dependencies = [ @@ -416,57 +334,57 @@ dependencies = [ "typing-extensions<5.0.0,>=4.0.1; python_version < \"3.8\"", ] files = [ - {file = "commitizen-3.30.0-py3-none-any.whl", hash = "sha256:8dc226a136aee61207e396101fcd89e73de67a57c06e066db982310863caaf65"}, - {file = "commitizen-3.30.0.tar.gz", hash = "sha256:ae67a47c1a700b4f35ac12de0c35c7ba96f152b9377d22b6226bb87372c527b0"}, + {file = "commitizen-3.31.0-py3-none-any.whl", hash = "sha256:a28df7ab5b8665d48796c422a97dcfae0d0fce7e2d28404c0e386cf1ebd42c8f"}, + {file = "commitizen-3.31.0.tar.gz", hash = "sha256:6ab973e91d07c1e745c6c0efe6dd0708b1f6d8fd7e4ab5e7c773b5ceb3df4ff0"}, ] [[package]] name = "coverage" -version = "7.6.4" +version = "7.6.7" requires_python = ">=3.9" summary = "Code coverage measurement for Python" files = [ - {file = "coverage-7.6.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:73d2b73584446e66ee633eaad1a56aad577c077f46c35ca3283cd687b7715b0b"}, - {file = "coverage-7.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51b44306032045b383a7a8a2c13878de375117946d68dcb54308111f39775a25"}, - {file = "coverage-7.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b3fb02fe73bed561fa12d279a417b432e5b50fe03e8d663d61b3d5990f29546"}, - {file = "coverage-7.6.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed8fe9189d2beb6edc14d3ad19800626e1d9f2d975e436f84e19efb7fa19469b"}, - {file = "coverage-7.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b369ead6527d025a0fe7bd3864e46dbee3aa8f652d48df6174f8d0bac9e26e0e"}, - {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ade3ca1e5f0ff46b678b66201f7ff477e8fa11fb537f3b55c3f0568fbfe6e718"}, - {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:27fb4a050aaf18772db513091c9c13f6cb94ed40eacdef8dad8411d92d9992db"}, - {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4f704f0998911abf728a7783799444fcbbe8261c4a6c166f667937ae6a8aa522"}, - {file = "coverage-7.6.4-cp311-cp311-win32.whl", hash = "sha256:29155cd511ee058e260db648b6182c419422a0d2e9a4fa44501898cf918866cf"}, - {file = "coverage-7.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:8902dd6a30173d4ef09954bfcb24b5d7b5190cf14a43170e386979651e09ba19"}, - {file = "coverage-7.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12394842a3a8affa3ba62b0d4ab7e9e210c5e366fbac3e8b2a68636fb19892c2"}, - {file = "coverage-7.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b6b4c83d8e8ea79f27ab80778c19bc037759aea298da4b56621f4474ffeb117"}, - {file = "coverage-7.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d5b8007f81b88696d06f7df0cb9af0d3b835fe0c8dbf489bad70b45f0e45613"}, - {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b57b768feb866f44eeed9f46975f3d6406380275c5ddfe22f531a2bf187eda27"}, - {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5915fcdec0e54ee229926868e9b08586376cae1f5faa9bbaf8faf3561b393d52"}, - {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b58c672d14f16ed92a48db984612f5ce3836ae7d72cdd161001cc54512571f2"}, - {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2fdef0d83a2d08d69b1f2210a93c416d54e14d9eb398f6ab2f0a209433db19e1"}, - {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cf717ee42012be8c0cb205dbbf18ffa9003c4cbf4ad078db47b95e10748eec5"}, - {file = "coverage-7.6.4-cp312-cp312-win32.whl", hash = "sha256:7bb92c539a624cf86296dd0c68cd5cc286c9eef2d0c3b8b192b604ce9de20a17"}, - {file = "coverage-7.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:1032e178b76a4e2b5b32e19d0fd0abbce4b58e77a1ca695820d10e491fa32b08"}, - {file = "coverage-7.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:023bf8ee3ec6d35af9c1c6ccc1d18fa69afa1cb29eaac57cb064dbb262a517f9"}, - {file = "coverage-7.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0ac3d42cb51c4b12df9c5f0dd2f13a4f24f01943627120ec4d293c9181219ba"}, - {file = "coverage-7.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8fe4984b431f8621ca53d9380901f62bfb54ff759a1348cd140490ada7b693c"}, - {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5fbd612f8a091954a0c8dd4c0b571b973487277d26476f8480bfa4b2a65b5d06"}, - {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dacbc52de979f2823a819571f2e3a350a7e36b8cb7484cdb1e289bceaf35305f"}, - {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dab4d16dfef34b185032580e2f2f89253d302facba093d5fa9dbe04f569c4f4b"}, - {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:862264b12ebb65ad8d863d51f17758b1684560b66ab02770d4f0baf2ff75da21"}, - {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5beb1ee382ad32afe424097de57134175fea3faf847b9af002cc7895be4e2a5a"}, - {file = "coverage-7.6.4-cp313-cp313-win32.whl", hash = "sha256:bf20494da9653f6410213424f5f8ad0ed885e01f7e8e59811f572bdb20b8972e"}, - {file = "coverage-7.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:182e6cd5c040cec0a1c8d415a87b67ed01193ed9ad458ee427741c7d8513d963"}, - {file = "coverage-7.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a181e99301a0ae128493a24cfe5cfb5b488c4e0bf2f8702091473d033494d04f"}, - {file = "coverage-7.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:df57bdbeffe694e7842092c5e2e0bc80fff7f43379d465f932ef36f027179806"}, - {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bcd1069e710600e8e4cf27f65c90c7843fa8edfb4520fb0ccb88894cad08b11"}, - {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99b41d18e6b2a48ba949418db48159d7a2e81c5cc290fc934b7d2380515bd0e3"}, - {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1e54712ba3474f34b7ef7a41e65bd9037ad47916ccb1cc78769bae324c01a"}, - {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53d202fd109416ce011578f321460795abfe10bb901b883cafd9b3ef851bacfc"}, - {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:c48167910a8f644671de9f2083a23630fbf7a1cb70ce939440cd3328e0919f70"}, - {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc8ff50b50ce532de2fa7a7daae9dd12f0a699bfcd47f20945364e5c31799fef"}, - {file = "coverage-7.6.4-cp313-cp313t-win32.whl", hash = "sha256:b8d3a03d9bfcaf5b0141d07a88456bb6a4c3ce55c080712fec8418ef3610230e"}, - {file = "coverage-7.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:f3ddf056d3ebcf6ce47bdaf56142af51bb7fad09e4af310241e9db7a3a8022e1"}, - {file = "coverage-7.6.4.tar.gz", hash = "sha256:29fc0f17b1d3fea332f8001d4558f8214af7f1d87a345f3a133c901d60347c73"}, + {file = "coverage-7.6.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7e61b0e77ff4dddebb35a0e8bb5a68bf0f8b872407d8d9f0c726b65dfabe2469"}, + {file = "coverage-7.6.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1a5407a75ca4abc20d6252efeb238377a71ce7bda849c26c7a9bece8680a5d99"}, + {file = "coverage-7.6.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df002e59f2d29e889c37abd0b9ee0d0e6e38c24f5f55d71ff0e09e3412a340ec"}, + {file = "coverage-7.6.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:673184b3156cba06154825f25af33baa2671ddae6343f23175764e65a8c4c30b"}, + {file = "coverage-7.6.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e69ad502f1a2243f739f5bd60565d14a278be58be4c137d90799f2c263e7049a"}, + {file = "coverage-7.6.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60dcf7605c50ea72a14490d0756daffef77a5be15ed1b9fea468b1c7bda1bc3b"}, + {file = "coverage-7.6.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9c2eb378bebb2c8f65befcb5147877fc1c9fbc640fc0aad3add759b5df79d55d"}, + {file = "coverage-7.6.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3c0317288f032221d35fa4cbc35d9f4923ff0dfd176c79c9b356e8ef8ef2dff4"}, + {file = "coverage-7.6.7-cp311-cp311-win32.whl", hash = "sha256:951aade8297358f3618a6e0660dc74f6b52233c42089d28525749fc8267dccd2"}, + {file = "coverage-7.6.7-cp311-cp311-win_amd64.whl", hash = "sha256:5e444b8e88339a2a67ce07d41faabb1d60d1004820cee5a2c2b54e2d8e429a0f"}, + {file = "coverage-7.6.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f07ff574986bc3edb80e2c36391678a271d555f91fd1d332a1e0f4b5ea4b6ea9"}, + {file = "coverage-7.6.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:49ed5ee4109258973630c1f9d099c7e72c5c36605029f3a91fe9982c6076c82b"}, + {file = "coverage-7.6.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3e8796434a8106b3ac025fd15417315d7a58ee3e600ad4dbcfddc3f4b14342c"}, + {file = "coverage-7.6.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3b925300484a3294d1c70f6b2b810d6526f2929de954e5b6be2bf8caa1f12c1"}, + {file = "coverage-7.6.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c42ec2c522e3ddd683dec5cdce8e62817afb648caedad9da725001fa530d354"}, + {file = "coverage-7.6.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0266b62cbea568bd5e93a4da364d05de422110cbed5056d69339bd5af5685433"}, + {file = "coverage-7.6.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e5f2a0f161d126ccc7038f1f3029184dbdf8f018230af17ef6fd6a707a5b881f"}, + {file = "coverage-7.6.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c132b5a22821f9b143f87446805e13580b67c670a548b96da945a8f6b4f2efbb"}, + {file = "coverage-7.6.7-cp312-cp312-win32.whl", hash = "sha256:7c07de0d2a110f02af30883cd7dddbe704887617d5c27cf373362667445a4c76"}, + {file = "coverage-7.6.7-cp312-cp312-win_amd64.whl", hash = "sha256:fd49c01e5057a451c30c9b892948976f5d38f2cbd04dc556a82743ba8e27ed8c"}, + {file = "coverage-7.6.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:46f21663e358beae6b368429ffadf14ed0a329996248a847a4322fb2e35d64d3"}, + {file = "coverage-7.6.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:40cca284c7c310d622a1677f105e8507441d1bb7c226f41978ba7c86979609ab"}, + {file = "coverage-7.6.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77256ad2345c29fe59ae861aa11cfc74579c88d4e8dbf121cbe46b8e32aec808"}, + {file = "coverage-7.6.7-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87ea64b9fa52bf395272e54020537990a28078478167ade6c61da7ac04dc14bc"}, + {file = "coverage-7.6.7-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d608a7808793e3615e54e9267519351c3ae204a6d85764d8337bd95993581a8"}, + {file = "coverage-7.6.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdd94501d65adc5c24f8a1a0eda110452ba62b3f4aeaba01e021c1ed9cb8f34a"}, + {file = "coverage-7.6.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:82c809a62e953867cf57e0548c2b8464207f5f3a6ff0e1e961683e79b89f2c55"}, + {file = "coverage-7.6.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bb684694e99d0b791a43e9fc0fa58efc15ec357ac48d25b619f207c41f2fd384"}, + {file = "coverage-7.6.7-cp313-cp313-win32.whl", hash = "sha256:963e4a08cbb0af6623e61492c0ec4c0ec5c5cf74db5f6564f98248d27ee57d30"}, + {file = "coverage-7.6.7-cp313-cp313-win_amd64.whl", hash = "sha256:14045b8bfd5909196a90da145a37f9d335a5d988a83db34e80f41e965fb7cb42"}, + {file = "coverage-7.6.7-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f2c7a045eef561e9544359a0bf5784b44e55cefc7261a20e730baa9220c83413"}, + {file = "coverage-7.6.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5dd4e4a49d9c72a38d18d641135d2fb0bdf7b726ca60a103836b3d00a1182acd"}, + {file = "coverage-7.6.7-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c95e0fa3d1547cb6f021ab72f5c23402da2358beec0a8e6d19a368bd7b0fb37"}, + {file = "coverage-7.6.7-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f63e21ed474edd23f7501f89b53280014436e383a14b9bd77a648366c81dce7b"}, + {file = "coverage-7.6.7-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ead9b9605c54d15be228687552916c89c9683c215370c4a44f1f217d2adcc34d"}, + {file = "coverage-7.6.7-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:0573f5cbf39114270842d01872952d301027d2d6e2d84013f30966313cadb529"}, + {file = "coverage-7.6.7-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:e2c8e3384c12dfa19fa9a52f23eb091a8fad93b5b81a41b14c17c78e23dd1d8b"}, + {file = "coverage-7.6.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:70a56a2ec1869e6e9fa69ef6b76b1a8a7ef709972b9cc473f9ce9d26b5997ce3"}, + {file = "coverage-7.6.7-cp313-cp313t-win32.whl", hash = "sha256:dbba8210f5067398b2c4d96b4e64d8fb943644d5eb70be0d989067c8ca40c0f8"}, + {file = "coverage-7.6.7-cp313-cp313t-win_amd64.whl", hash = "sha256:dfd14bcae0c94004baba5184d1c935ae0d1231b8409eb6c103a5fd75e8ecdc56"}, + {file = "coverage-7.6.7.tar.gz", hash = "sha256:d79d4826e41441c9a118ff045e4bccb9fdbdcb1d02413e7ea6eb5c87b5439d24"}, ] [[package]] @@ -484,24 +402,24 @@ files = [ [[package]] name = "debugpy" -version = "1.8.7" +version = "1.8.8" requires_python = ">=3.8" summary = "An implementation of the Debug Adapter Protocol for Python" files = [ - {file = "debugpy-1.8.7-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:caf528ff9e7308b74a1749c183d6808ffbedbb9fb6af78b033c28974d9b8831f"}, - {file = "debugpy-1.8.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cba1d078cf2e1e0b8402e6bda528bf8fda7ccd158c3dba6c012b7897747c41a0"}, - {file = "debugpy-1.8.7-cp311-cp311-win32.whl", hash = "sha256:171899588bcd412151e593bd40d9907133a7622cd6ecdbdb75f89d1551df13c2"}, - {file = "debugpy-1.8.7-cp311-cp311-win_amd64.whl", hash = "sha256:6e1c4ffb0c79f66e89dfd97944f335880f0d50ad29525dc792785384923e2211"}, - {file = "debugpy-1.8.7-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:4d27d842311353ede0ad572600c62e4bcd74f458ee01ab0dd3a1a4457e7e3706"}, - {file = "debugpy-1.8.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:703c1fd62ae0356e194f3e7b7a92acd931f71fe81c4b3be2c17a7b8a4b546ec2"}, - {file = "debugpy-1.8.7-cp312-cp312-win32.whl", hash = "sha256:2f729228430ef191c1e4df72a75ac94e9bf77413ce5f3f900018712c9da0aaca"}, - {file = "debugpy-1.8.7-cp312-cp312-win_amd64.whl", hash = "sha256:45c30aaefb3e1975e8a0258f5bbd26cd40cde9bfe71e9e5a7ac82e79bad64e39"}, - {file = "debugpy-1.8.7-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:d050a1ec7e925f514f0f6594a1e522580317da31fbda1af71d1530d6ea1f2b40"}, - {file = "debugpy-1.8.7-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2f4349a28e3228a42958f8ddaa6333d6f8282d5edaea456070e48609c5983b7"}, - {file = "debugpy-1.8.7-cp313-cp313-win32.whl", hash = "sha256:11ad72eb9ddb436afb8337891a986302e14944f0f755fd94e90d0d71e9100bba"}, - {file = "debugpy-1.8.7-cp313-cp313-win_amd64.whl", hash = "sha256:2efb84d6789352d7950b03d7f866e6d180284bc02c7e12cb37b489b7083d81aa"}, - {file = "debugpy-1.8.7-py2.py3-none-any.whl", hash = "sha256:57b00de1c8d2c84a61b90880f7e5b6deaf4c312ecbde3a0e8912f2a56c4ac9ae"}, - {file = "debugpy-1.8.7.zip", hash = "sha256:18b8f731ed3e2e1df8e9cdaa23fb1fc9c24e570cd0081625308ec51c82efe42e"}, + {file = "debugpy-1.8.8-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:c399023146e40ae373753a58d1be0a98bf6397fadc737b97ad612886b53df318"}, + {file = "debugpy-1.8.8-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09cc7b162586ea2171eea055985da2702b0723f6f907a423c9b2da5996ad67ba"}, + {file = "debugpy-1.8.8-cp311-cp311-win32.whl", hash = "sha256:eea8821d998ebeb02f0625dd0d76839ddde8cbf8152ebbe289dd7acf2cdc6b98"}, + {file = "debugpy-1.8.8-cp311-cp311-win_amd64.whl", hash = "sha256:d4483836da2a533f4b1454dffc9f668096ac0433de855f0c22cdce8c9f7e10c4"}, + {file = "debugpy-1.8.8-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:0cc94186340be87b9ac5a707184ec8f36547fb66636d1029ff4f1cc020e53996"}, + {file = "debugpy-1.8.8-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64674e95916e53c2e9540a056e5f489e0ad4872645399d778f7c598eacb7b7f9"}, + {file = "debugpy-1.8.8-cp312-cp312-win32.whl", hash = "sha256:5c6e885dbf12015aed73770f29dec7023cb310d0dc2ba8bfbeb5c8e43f80edc9"}, + {file = "debugpy-1.8.8-cp312-cp312-win_amd64.whl", hash = "sha256:19ffbd84e757a6ca0113574d1bf5a2298b3947320a3e9d7d8dc3377f02d9f864"}, + {file = "debugpy-1.8.8-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:705cd123a773d184860ed8dae99becd879dfec361098edbefb5fc0d3683eb804"}, + {file = "debugpy-1.8.8-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:890fd16803f50aa9cb1a9b9b25b5ec321656dd6b78157c74283de241993d086f"}, + {file = "debugpy-1.8.8-cp313-cp313-win32.whl", hash = "sha256:90244598214bbe704aa47556ec591d2f9869ff9e042e301a2859c57106649add"}, + {file = "debugpy-1.8.8-cp313-cp313-win_amd64.whl", hash = "sha256:4b93e4832fd4a759a0c465c967214ed0c8a6e8914bced63a28ddb0dd8c5f078b"}, + {file = "debugpy-1.8.8-py2.py3-none-any.whl", hash = "sha256:ec684553aba5b4066d4de510859922419febc710df7bba04fe9e7ef3de15d34f"}, + {file = "debugpy-1.8.8.zip", hash = "sha256:e6355385db85cbd666be703a96ab7351bc9e6c61d694893206f8001e22aee091"}, ] [[package]] @@ -516,15 +434,15 @@ files = [ [[package]] name = "deprecated" -version = "1.2.14" -requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.2.15" +requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" summary = "Python @deprecated decorator to deprecate old python classes, functions or methods." dependencies = [ "wrapt<2,>=1.10", ] files = [ - {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, - {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, + {file = "Deprecated-1.2.15-py2.py3-none-any.whl", hash = "sha256:353bc4a8ac4bfc96800ddab349d89c25dec1079f65fd53acdcc1e0b975b21320"}, + {file = "deprecated-1.2.15.tar.gz", hash = "sha256:683e561a90de76239796e6b6feac66b99030d2dd3fcf61ef996330f14bbb9b0d"}, ] [[package]] @@ -757,7 +675,7 @@ files = [ [[package]] name = "httpcore" -version = "1.0.6" +version = "1.0.7" requires_python = ">=3.8" summary = "A minimal low-level HTTP client." dependencies = [ @@ -765,8 +683,8 @@ dependencies = [ "h11<0.15,>=0.13", ] files = [ - {file = "httpcore-1.0.6-py3-none-any.whl", hash = "sha256:27b59625743b85577a8c0e10e55b50b5368a4f2cfe8cc7bcfa9cf00829c2682f"}, - {file = "httpcore-1.0.6.tar.gz", hash = "sha256:73f6dbd6eb8c21bbf7ef8efad555481853f5f6acdeaff1edb0694289269ee17f"}, + {file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"}, + {file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"}, ] [[package]] @@ -788,12 +706,12 @@ files = [ [[package]] name = "identify" -version = "2.6.1" -requires_python = ">=3.8" +version = "2.6.2" +requires_python = ">=3.9" summary = "File identification library for Python" files = [ - {file = "identify-2.6.1-py2.py3-none-any.whl", hash = "sha256:53863bcac7caf8d2ed85bd20312ea5dcfc22226800f6d6881f232d861db5a8f0"}, - {file = "identify-2.6.1.tar.gz", hash = "sha256:91478c5fb7c3aac5ff7bf9b4344f803843dc586832d5f110d672b19aa1984c98"}, + {file = "identify-2.6.2-py2.py3-none-any.whl", hash = "sha256:c097384259f49e372f4ea00a19719d95ae27dd5ff0fd77ad630aa891306b82f3"}, + {file = "identify-2.6.2.tar.gz", hash = "sha256:fab5c716c24d7a789775228823797296a2994b075fb6080ac83a102772a98cbd"}, ] [[package]] @@ -808,16 +726,16 @@ files = [ [[package]] name = "importlib-metadata" -version = "8.4.0" +version = "8.5.0" requires_python = ">=3.8" summary = "Read metadata from Python packages" dependencies = [ "typing-extensions>=3.6.4; python_version < \"3.8\"", - "zipp>=0.5", + "zipp>=3.20", ] files = [ - {file = "importlib_metadata-8.4.0-py3-none-any.whl", hash = "sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1"}, - {file = "importlib_metadata-8.4.0.tar.gz", hash = "sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5"}, + {file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"}, + {file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"}, ] [[package]] @@ -1101,7 +1019,7 @@ files = [ [[package]] name = "mkdocstrings" -version = "0.26.2" +version = "0.27.0" requires_python = ">=3.9" summary = "Automatic documentation from sources, for MkDocs." dependencies = [ @@ -1117,8 +1035,8 @@ dependencies = [ "typing-extensions>=4.1; python_version < \"3.10\"", ] files = [ - {file = "mkdocstrings-0.26.2-py3-none-any.whl", hash = "sha256:1248f3228464f3b8d1a15bd91249ce1701fe3104ac517a5f167a0e01ca850ba5"}, - {file = "mkdocstrings-0.26.2.tar.gz", hash = "sha256:34a8b50f1e6cfd29546c6c09fbe02154adfb0b361bb758834bf56aa284ba876e"}, + {file = "mkdocstrings-0.27.0-py3-none-any.whl", hash = "sha256:6ceaa7ea830770959b55a16203ac63da24badd71325b96af950e59fd37366332"}, + {file = "mkdocstrings-0.27.0.tar.gz", hash = "sha256:16adca6d6b0a1f9e0c07ff0b02ced8e16f228a9d65a37c063ec4c14d7b76a657"}, ] [[package]] @@ -1136,21 +1054,6 @@ files = [ {file = "mkdocstrings_python-1.12.2.tar.gz", hash = "sha256:7a1760941c0b52a2cd87b960a9e21112ffe52e7df9d0b9583d04d47ed2e186f3"}, ] -[[package]] -name = "morecantile" -version = "6.1.0" -requires_python = ">=3.8" -summary = "Construct and use map tile grids (a.k.a TileMatrixSet / TMS)." -dependencies = [ - "attrs", - "pydantic~=2.0", - "pyproj~=3.1", -] -files = [ - {file = "morecantile-6.1.0-py3-none-any.whl", hash = "sha256:2c8bfb79298b3b27efba8c734f01ea32b7af859153f553b3e3f6a67258b3b001"}, - {file = "morecantile-6.1.0.tar.gz", hash = "sha256:4445c6fbf741f3ee5d0130d18ec65c917e6d9f98e98a8f9d4a8a60d39c0c3b0a"}, -] - [[package]] name = "nodeenv" version = "1.9.1" @@ -1161,32 +1064,6 @@ files = [ {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, ] -[[package]] -name = "numexpr" -version = "2.10.1" -requires_python = ">=3.9" -summary = "Fast numerical expression evaluator for NumPy" -dependencies = [ - "numpy>=1.23.0", -] -files = [ - {file = "numexpr-2.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a3c0b0bf165b2d886eb981afa4e77873ca076f5d51c491c4d7b8fc10f17c876f"}, - {file = "numexpr-2.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56648a04679063175681195670ad53e5c8ca19668166ed13875199b5600089c7"}, - {file = "numexpr-2.10.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce04ae6efe2a9d0be1a0e114115c3ae70c68b8b8fbc615c5c55c15704b01e6a4"}, - {file = "numexpr-2.10.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:45f598182b4f5c153222e47d5163c3bee8d5ebcaee7e56dd2a5898d4d97e4473"}, - {file = "numexpr-2.10.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6a50370bea77ba94c3734a44781c716751354c6bfda2d369af3aed3d67d42871"}, - {file = "numexpr-2.10.1-cp311-cp311-win32.whl", hash = "sha256:fa4009d84a8e6e21790e718a80a22d57fe7f215283576ef2adc4183f7247f3c7"}, - {file = "numexpr-2.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:fcbf013bb8494e8ef1d11fa3457827c1571c6a3153982d709e5d17594999d4dd"}, - {file = "numexpr-2.10.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:82fc95c301b15ff4823f98989ee363a2d5555d16a7cfd3710e98ddee726eaaaa"}, - {file = "numexpr-2.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cbf79fef834f88607f977ab9867061dcd9b40ccb08bb28547c6dc6c73e560895"}, - {file = "numexpr-2.10.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:552c8d4b2e3b87cdb2abb40a781b9a61a9090a9f66ac7357fc5a0b93aff76be3"}, - {file = "numexpr-2.10.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22cc65e9121aeb3187a2b50827715b2b087ea70e8ab21416ea52662322087b43"}, - {file = "numexpr-2.10.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:00204e5853713b5eba5f3d0bc586a5d8d07f76011b597c8b4087592cc2ec2928"}, - {file = "numexpr-2.10.1-cp312-cp312-win32.whl", hash = "sha256:82bf04a1495ac475de4ab49fbe0a3a2710ed3fd1a00bc03847316b5d7602402d"}, - {file = "numexpr-2.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:300e577b3c006dd7a8270f1bb2e8a00ee15bf235b1650fe2a6febec2954bc2c3"}, - {file = "numexpr-2.10.1.tar.gz", hash = "sha256:9bba99d354a65f1a008ab8b87f07d84404c668e66bab624df5b6b5373403cf81"}, -] - [[package]] name = "numpy" version = "1.26.4" @@ -1224,190 +1101,191 @@ files = [ [[package]] name = "opentelemetry-api" -version = "1.27.0" +version = "1.28.1" requires_python = ">=3.8" summary = "OpenTelemetry Python API" dependencies = [ "deprecated>=1.2.6", - "importlib-metadata<=8.4.0,>=6.0", + "importlib-metadata<=8.5.0,>=6.0", ] files = [ - {file = "opentelemetry_api-1.27.0-py3-none-any.whl", hash = "sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7"}, - {file = "opentelemetry_api-1.27.0.tar.gz", hash = "sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342"}, + {file = "opentelemetry_api-1.28.1-py3-none-any.whl", hash = "sha256:bfe86c95576cf19a914497f439fd79c9553a38de0adbdc26f7cfc46b0c00b16c"}, + {file = "opentelemetry_api-1.28.1.tar.gz", hash = "sha256:6fa7295a12c707f5aebef82da3d9ec5afe6992f3e42bfe7bec0339a44b3518e7"}, ] [[package]] name = "opentelemetry-distro" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "OpenTelemetry Python Distro" dependencies = [ "opentelemetry-api~=1.12", - "opentelemetry-instrumentation==0.48b0", + "opentelemetry-instrumentation==0.49b1", "opentelemetry-sdk~=1.13", ] files = [ - {file = "opentelemetry_distro-0.48b0-py3-none-any.whl", hash = "sha256:b2f8fce114325b020769af3b9bf503efb8af07efc190bd1b9deac7843171664a"}, - {file = "opentelemetry_distro-0.48b0.tar.gz", hash = "sha256:5cb15915780ac4972583286a56683d43bd4ca95371d72f5f3f179c8b0b2ddc91"}, + {file = "opentelemetry_distro-0.49b1-py3-none-any.whl", hash = "sha256:c3a87a4a284c3d7cb680b0f320cb8dba8358b5958f0df837e00db2fbd700a71f"}, + {file = "opentelemetry_distro-0.49b1.tar.gz", hash = "sha256:3eb644547170122ade8a24da8cc02d795f4ccec69a19ae9fe3a0e5b930e56917"}, ] [[package]] name = "opentelemetry-instrumentation" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python" dependencies = [ "opentelemetry-api~=1.4", - "setuptools>=16.0", + "opentelemetry-semantic-conventions==0.49b1", + "packaging>=18.0", "wrapt<2.0.0,>=1.0.0", ] files = [ - {file = "opentelemetry_instrumentation-0.48b0-py3-none-any.whl", hash = "sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44"}, - {file = "opentelemetry_instrumentation-0.48b0.tar.gz", hash = "sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35"}, + {file = "opentelemetry_instrumentation-0.49b1-py3-none-any.whl", hash = "sha256:0a9d3821736104013693ef3b8a9d29b41f2f3a81ee2d8c9288b52d62bae5747c"}, + {file = "opentelemetry_instrumentation-0.49b1.tar.gz", hash = "sha256:2d0e41181b7957ba061bb436b969ad90545ac3eba65f290830009b4264d2824e"}, ] [[package]] name = "opentelemetry-instrumentation-asgi" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "ASGI instrumentation for OpenTelemetry" dependencies = [ "asgiref~=3.0", "opentelemetry-api~=1.12", - "opentelemetry-instrumentation==0.48b0", - "opentelemetry-semantic-conventions==0.48b0", - "opentelemetry-util-http==0.48b0", + "opentelemetry-instrumentation==0.49b1", + "opentelemetry-semantic-conventions==0.49b1", + "opentelemetry-util-http==0.49b1", ] files = [ - {file = "opentelemetry_instrumentation_asgi-0.48b0-py3-none-any.whl", hash = "sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d"}, - {file = "opentelemetry_instrumentation_asgi-0.48b0.tar.gz", hash = "sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785"}, + {file = "opentelemetry_instrumentation_asgi-0.49b1-py3-none-any.whl", hash = "sha256:8dcbc438cb138789fcb20ae38b6e7f23088e066d77b54bae205c5744856603c6"}, + {file = "opentelemetry_instrumentation_asgi-0.49b1.tar.gz", hash = "sha256:d1a2b4cb76490be28bcad3c0f562c4b3c84157148c922ca298bb04ed9e36c005"}, ] [[package]] name = "opentelemetry-instrumentation-dbapi" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "OpenTelemetry Database API instrumentation" dependencies = [ "opentelemetry-api~=1.12", - "opentelemetry-instrumentation==0.48b0", - "opentelemetry-semantic-conventions==0.48b0", + "opentelemetry-instrumentation==0.49b1", + "opentelemetry-semantic-conventions==0.49b1", "wrapt<2.0.0,>=1.0.0", ] files = [ - {file = "opentelemetry_instrumentation_dbapi-0.48b0-py3-none-any.whl", hash = "sha256:0d11a73ecbf55b11e8fbc93e9e97366958b98ccb4b691c776b32e4b20b3ce8bb"}, - {file = "opentelemetry_instrumentation_dbapi-0.48b0.tar.gz", hash = "sha256:89821288199f4f5225e74543bf14addf9b1824b8b5f1e83ad0d9dafa844f33b0"}, + {file = "opentelemetry_instrumentation_dbapi-0.49b1-py3-none-any.whl", hash = "sha256:ff4fc87f6b6a8fd40bb383efabcdb94078ff6fc7e8f8bf1c501256fb4e8064ed"}, + {file = "opentelemetry_instrumentation_dbapi-0.49b1.tar.gz", hash = "sha256:aa19a0dc96a127b155778b7c3aa58d1db100e3c1b4be2b61cd7aa318af9079cd"}, ] [[package]] name = "opentelemetry-instrumentation-fastapi" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "OpenTelemetry FastAPI Instrumentation" dependencies = [ "opentelemetry-api~=1.12", - "opentelemetry-instrumentation-asgi==0.48b0", - "opentelemetry-instrumentation==0.48b0", - "opentelemetry-semantic-conventions==0.48b0", - "opentelemetry-util-http==0.48b0", + "opentelemetry-instrumentation-asgi==0.49b1", + "opentelemetry-instrumentation==0.49b1", + "opentelemetry-semantic-conventions==0.49b1", + "opentelemetry-util-http==0.49b1", ] files = [ - {file = "opentelemetry_instrumentation_fastapi-0.48b0-py3-none-any.whl", hash = "sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2"}, - {file = "opentelemetry_instrumentation_fastapi-0.48b0.tar.gz", hash = "sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2"}, + {file = "opentelemetry_instrumentation_fastapi-0.49b1-py3-none-any.whl", hash = "sha256:3398940102c8ef613b9c55fc4f179cc92413de456f6bec6eeb1995270de2b087"}, + {file = "opentelemetry_instrumentation_fastapi-0.49b1.tar.gz", hash = "sha256:13d9d4d70b4bb831468b8e40807353731cad7fbfaeedde0070d93bcb2c417b07"}, ] [[package]] name = "opentelemetry-instrumentation-logging" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "OpenTelemetry Logging instrumentation" dependencies = [ "opentelemetry-api~=1.12", - "opentelemetry-instrumentation==0.48b0", + "opentelemetry-instrumentation==0.49b1", ] files = [ - {file = "opentelemetry_instrumentation_logging-0.48b0-py3-none-any.whl", hash = "sha256:75e5357d9b8c12071a19e1fef664dc1f430ef45874445c324ba4439a00972dc0"}, - {file = "opentelemetry_instrumentation_logging-0.48b0.tar.gz", hash = "sha256:529eb13eedf57d6b2f94e20e996271db2957b817b9457fe4796365d6d4238dec"}, + {file = "opentelemetry_instrumentation_logging-0.49b1-py3-none-any.whl", hash = "sha256:65f632ea0b450b4a8517b31ccf48b011a36e6335d00c1cb0674204db33a35834"}, + {file = "opentelemetry_instrumentation_logging-0.49b1.tar.gz", hash = "sha256:65c2eabe9d7d29d153c3b80e445f8649693c7f6c8ce5add12dd0328e47f593c7"}, ] [[package]] name = "opentelemetry-instrumentation-psycopg2" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "OpenTelemetry psycopg2 instrumentation" dependencies = [ "opentelemetry-api~=1.12", - "opentelemetry-instrumentation-dbapi==0.48b0", - "opentelemetry-instrumentation==0.48b0", + "opentelemetry-instrumentation-dbapi==0.49b1", + "opentelemetry-instrumentation==0.49b1", ] files = [ - {file = "opentelemetry_instrumentation_psycopg2-0.48b0-py3-none-any.whl", hash = "sha256:6a935f33b3d8908bee29b6b178bf84e56d93902c31282714113ffec922056aa4"}, - {file = "opentelemetry_instrumentation_psycopg2-0.48b0.tar.gz", hash = "sha256:f86c8d15deefe80475d9778ddc425e1ae56b325ecb32653e2ad0f78abef1717d"}, + {file = "opentelemetry_instrumentation_psycopg2-0.49b1-py3-none-any.whl", hash = "sha256:6472cd8cea96f14c979a3a7b799f8d3cc7ebb615bcd2a725a6f82eeda0b71d55"}, + {file = "opentelemetry_instrumentation_psycopg2-0.49b1.tar.gz", hash = "sha256:de986a39f98d86a4193ed1b69f744333daae28d9706eeb7408fddebebad836d7"}, ] [[package]] name = "opentelemetry-instrumentation-requests" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "OpenTelemetry requests instrumentation" dependencies = [ "opentelemetry-api~=1.12", - "opentelemetry-instrumentation==0.48b0", - "opentelemetry-semantic-conventions==0.48b0", - "opentelemetry-util-http==0.48b0", + "opentelemetry-instrumentation==0.49b1", + "opentelemetry-semantic-conventions==0.49b1", + "opentelemetry-util-http==0.49b1", ] files = [ - {file = "opentelemetry_instrumentation_requests-0.48b0-py3-none-any.whl", hash = "sha256:d4f01852121d0bd4c22f14f429654a735611d4f7bf3cf93f244bdf1489b2233d"}, - {file = "opentelemetry_instrumentation_requests-0.48b0.tar.gz", hash = "sha256:67ab9bd877a0352ee0db4616c8b4ae59736ddd700c598ed907482d44f4c9a2b3"}, + {file = "opentelemetry_instrumentation_requests-0.49b1-py3-none-any.whl", hash = "sha256:4a7f8321f9cca5b4da3a96b63dde0c7a41775302f4e9e0267a775f9800efac59"}, + {file = "opentelemetry_instrumentation_requests-0.49b1.tar.gz", hash = "sha256:329726afd607e1078e80bc2fb43741bd73e77c2d36804d9250d965858df8bd36"}, ] [[package]] name = "opentelemetry-sdk" -version = "1.27.0" +version = "1.28.1" requires_python = ">=3.8" summary = "OpenTelemetry Python SDK" dependencies = [ - "opentelemetry-api==1.27.0", - "opentelemetry-semantic-conventions==0.48b0", + "opentelemetry-api==1.28.1", + "opentelemetry-semantic-conventions==0.49b1", "typing-extensions>=3.7.4", ] files = [ - {file = "opentelemetry_sdk-1.27.0-py3-none-any.whl", hash = "sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d"}, - {file = "opentelemetry_sdk-1.27.0.tar.gz", hash = "sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f"}, + {file = "opentelemetry_sdk-1.28.1-py3-none-any.whl", hash = "sha256:72aad7f5fcbe37113c4ab4899f6cdeb6ac77ed3e62f25a85e3627b12583dad0f"}, + {file = "opentelemetry_sdk-1.28.1.tar.gz", hash = "sha256:100fa371b2046ffba6a340c18f0b2a0463acad7461e5177e126693b613a6ca57"}, ] [[package]] name = "opentelemetry-semantic-conventions" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "OpenTelemetry Semantic Conventions" dependencies = [ "deprecated>=1.2.6", - "opentelemetry-api==1.27.0", + "opentelemetry-api==1.28.1", ] files = [ - {file = "opentelemetry_semantic_conventions-0.48b0-py3-none-any.whl", hash = "sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f"}, - {file = "opentelemetry_semantic_conventions-0.48b0.tar.gz", hash = "sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a"}, + {file = "opentelemetry_semantic_conventions-0.49b1-py3-none-any.whl", hash = "sha256:dd6f3ac8169d2198c752e1a63f827e5f5e110ae9b0ce33f2aad9a3baf0739743"}, + {file = "opentelemetry_semantic_conventions-0.49b1.tar.gz", hash = "sha256:91817883b159ffb94c2ca9548509c4fe0aafce7c24f437aa6ac3fc613aa9a758"}, ] [[package]] name = "opentelemetry-util-http" -version = "0.48b0" +version = "0.49b1" requires_python = ">=3.8" summary = "Web util for OpenTelemetry" files = [ - {file = "opentelemetry_util_http-0.48b0-py3-none-any.whl", hash = "sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb"}, - {file = "opentelemetry_util_http-0.48b0.tar.gz", hash = "sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c"}, + {file = "opentelemetry_util_http-0.49b1-py3-none-any.whl", hash = "sha256:0290b942f7888b6310df6803e52e12f4043b8f224db0659f62dc7b70059eb94f"}, + {file = "opentelemetry_util_http-0.49b1.tar.gz", hash = "sha256:6c2bc6f7e20e286dbdfcccb9d895fa290ec9d7c596cdf2e06bf1d8e434b2edd0"}, ] [[package]] name = "packaging" -version = "24.1" +version = "24.2" requires_python = ">=3.8" summary = "Core utilities for Python packages" files = [ - {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, - {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, + {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, + {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, ] [[package]] @@ -1519,15 +1397,15 @@ files = [ [[package]] name = "psycopg-pool" -version = "3.2.3" +version = "3.2.4" requires_python = ">=3.8" summary = "Connection Pool for Psycopg" dependencies = [ "typing-extensions>=4.6", ] files = [ - {file = "psycopg_pool-3.2.3-py3-none-any.whl", hash = "sha256:53bd8e640625e01b2927b2ad96df8ed8e8f91caea4597d45e7673fc7bbb85eb1"}, - {file = "psycopg_pool-3.2.3.tar.gz", hash = "sha256:bb942f123bef4b7fbe4d55421bd3fb01829903c95c0f33fd42b7e94e5ac9b52a"}, + {file = "psycopg_pool-3.2.4-py3-none-any.whl", hash = "sha256:f6a22cff0f21f06d72fb2f5cb48c618946777c49385358e0c88d062c59cbd224"}, + {file = "psycopg_pool-3.2.4.tar.gz", hash = "sha256:61774b5bbf23e8d22bedc7504707135aaf744679f8ef9b3fe29942920746a6ed"}, ] [[package]] @@ -1731,12 +1609,12 @@ files = [ [[package]] name = "pyjwt" -version = "2.9.0" -requires_python = ">=3.8" +version = "2.10.0" +requires_python = ">=3.9" summary = "JSON Web Token implementation in Python" files = [ - {file = "PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850"}, - {file = "pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c"}, + {file = "PyJWT-2.10.0-py3-none-any.whl", hash = "sha256:543b77207db656de204372350926bed5a86201c4cbff159f623f79c7bb487a15"}, + {file = "pyjwt-2.10.0.tar.gz", hash = "sha256:7628a7eb7938959ac1b26e819a1df0fd3259505627b575e4bad6d08f76db695c"}, ] [[package]] @@ -1767,16 +1645,6 @@ files = [ {file = "pyodm-1.5.12.tar.gz", hash = "sha256:d0433182ac6d5587786391c91d0eeafe0d78c71d618336af78964620dafe87c4"}, ] -[[package]] -name = "pyparsing" -version = "3.2.0" -requires_python = ">=3.9" -summary = "pyparsing module - Classes and methods to define and execute parsing grammars" -files = [ - {file = "pyparsing-3.2.0-py3-none-any.whl", hash = "sha256:93d9577b88da0bbea8cc8334ee8b918ed014968fd2ec383e868fb8afb1ccef84"}, - {file = "pyparsing-3.2.0.tar.gz", hash = "sha256:cbf74e27246d595d9a74b186b810f6fbb86726dbf3b9532efb343f6d7294fe9c"}, -] - [[package]] name = "pyproj" version = "3.7.0" @@ -1807,19 +1675,6 @@ files = [ {file = "pyproj-3.7.0.tar.gz", hash = "sha256:bf658f4aaf815d9d03c8121650b6f0b8067265c36e31bc6660b98ef144d81813"}, ] -[[package]] -name = "pystac" -version = "1.11.0" -requires_python = ">=3.10" -summary = "Python library for working with the SpatioTemporal Asset Catalog (STAC) specification" -dependencies = [ - "python-dateutil>=2.7.0", -] -files = [ - {file = "pystac-1.11.0-py3-none-any.whl", hash = "sha256:10ac7c7b4ea6c5ec8333829a09ec1a33b596f02d1a97ffbbd72cd1b6c10598c1"}, - {file = "pystac-1.11.0.tar.gz", hash = "sha256:acb1e04be398a0cda2d8870ab5e90457783a8014a206590233171d8b2ae0d9e7"}, -] - [[package]] name = "pytest" version = "8.3.3" @@ -1968,90 +1823,58 @@ files = [ {file = "questionary-2.0.1.tar.gz", hash = "sha256:bcce898bf3dbb446ff62830c86c5c6fb9a22a54146f0f5597d3da43b10d8fc8b"}, ] -[[package]] -name = "rasterio" -version = "1.4.2" -requires_python = ">=3.9" -summary = "Fast and direct raster I/O for use with Numpy and SciPy" -dependencies = [ - "affine", - "attrs", - "certifi", - "click-plugins", - "click>=4.0", - "cligj>=0.5", - "importlib-metadata; python_version < \"3.10\"", - "numpy>=1.24", - "pyparsing", -] -files = [ - {file = "rasterio-1.4.2-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:019e6fbfea250fea91987a38abc7a02c752b50beadb3178d82a5d47e8e265313"}, - {file = "rasterio-1.4.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:a9830e0c9d09d2680079b8a31085cc2a2b885b1ed6c4d95d2a91e2813efc22aa"}, - {file = "rasterio-1.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea3f38da794e7a4df409f2c57799a26a777a2560025ad401fe33a0b8efe90a5a"}, - {file = "rasterio-1.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:0c74d6a2e64fae6c2293bf520fa4048e12598379736953c34ca3dfb058cedfc5"}, - {file = "rasterio-1.4.2-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:84ce104a3017c04bfb809f268faaef4287458916f7af4f25a39b93f420fa8ef4"}, - {file = "rasterio-1.4.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:856c740e621211a19f0efddc2f0a61cc3d37c89c50699ea6cb249da3930d601b"}, - {file = "rasterio-1.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43a21306c8dc265f50d3cb8a13a58d50e055477ace1003bb8a507658a4124c37"}, - {file = "rasterio-1.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:83bf03b39dc7e1d932907d1b05d99a53b7fc184c215a27b938f4697db7295f53"}, - {file = "rasterio-1.4.2-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:e405e92ab03f5606a959d4a7d9ae1589e2212f9720c2db55853bfa8c91f6d736"}, - {file = "rasterio-1.4.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:7dbf3d084e1f72f322d378eb2b9e155fbe0ead97f0a1b0065a389e9435a5a3db"}, - {file = "rasterio-1.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6f2952e1b4ad01f0dcf97f477050d8122ca781abbb3ef8b5a5751835a222317"}, - {file = "rasterio-1.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:25ec2a35548c1c45ea1dd5341e777e5aeea8f79310bbae6aaed4d5f6a4c53f26"}, - {file = "rasterio-1.4.2.tar.gz", hash = "sha256:1be35ccb4d998a4c48fa51bbee9e37927ecd9b9e954a2b2581b8f3e9bb165332"}, -] - [[package]] name = "regex" -version = "2024.9.11" +version = "2024.11.6" requires_python = ">=3.8" summary = "Alternative regular expression module, to replace re." files = [ - {file = "regex-2024.9.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2cce2449e5927a0bf084d346da6cd5eb016b2beca10d0013ab50e3c226ffc0df"}, - {file = "regex-2024.9.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3b37fa423beefa44919e009745ccbf353d8c981516e807995b2bd11c2c77d268"}, - {file = "regex-2024.9.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:64ce2799bd75039b480cc0360907c4fb2f50022f030bf9e7a8705b636e408fad"}, - {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4cc92bb6db56ab0c1cbd17294e14f5e9224f0cc6521167ef388332604e92679"}, - {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d05ac6fa06959c4172eccd99a222e1fbf17b5670c4d596cb1e5cde99600674c4"}, - {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:040562757795eeea356394a7fb13076ad4f99d3c62ab0f8bdfb21f99a1f85664"}, - {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6113c008a7780792efc80f9dfe10ba0cd043cbf8dc9a76ef757850f51b4edc50"}, - {file = "regex-2024.9.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e5fb5f77c8745a60105403a774fe2c1759b71d3e7b4ca237a5e67ad066c7199"}, - {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:54d9ff35d4515debf14bc27f1e3b38bfc453eff3220f5bce159642fa762fe5d4"}, - {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:df5cbb1fbc74a8305b6065d4ade43b993be03dbe0f8b30032cced0d7740994bd"}, - {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7fb89ee5d106e4a7a51bce305ac4efb981536301895f7bdcf93ec92ae0d91c7f"}, - {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a738b937d512b30bf75995c0159c0ddf9eec0775c9d72ac0202076c72f24aa96"}, - {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e28f9faeb14b6f23ac55bfbbfd3643f5c7c18ede093977f1df249f73fd22c7b1"}, - {file = "regex-2024.9.11-cp311-cp311-win32.whl", hash = "sha256:18e707ce6c92d7282dfce370cd205098384b8ee21544e7cb29b8aab955b66fa9"}, - {file = "regex-2024.9.11-cp311-cp311-win_amd64.whl", hash = "sha256:313ea15e5ff2a8cbbad96ccef6be638393041b0a7863183c2d31e0c6116688cf"}, - {file = "regex-2024.9.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b0d0a6c64fcc4ef9c69bd5b3b3626cc3776520a1637d8abaa62b9edc147a58f7"}, - {file = "regex-2024.9.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:49b0e06786ea663f933f3710a51e9385ce0cba0ea56b67107fd841a55d56a231"}, - {file = "regex-2024.9.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5b513b6997a0b2f10e4fd3a1313568e373926e8c252bd76c960f96fd039cd28d"}, - {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee439691d8c23e76f9802c42a95cfeebf9d47cf4ffd06f18489122dbb0a7ad64"}, - {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8f877c89719d759e52783f7fe6e1c67121076b87b40542966c02de5503ace42"}, - {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23b30c62d0f16827f2ae9f2bb87619bc4fba2044911e2e6c2eb1af0161cdb766"}, - {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85ab7824093d8f10d44330fe1e6493f756f252d145323dd17ab6b48733ff6c0a"}, - {file = "regex-2024.9.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8dee5b4810a89447151999428fe096977346cf2f29f4d5e29609d2e19e0199c9"}, - {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98eeee2f2e63edae2181c886d7911ce502e1292794f4c5ee71e60e23e8d26b5d"}, - {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:57fdd2e0b2694ce6fc2e5ccf189789c3e2962916fb38779d3e3521ff8fe7a822"}, - {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d552c78411f60b1fdaafd117a1fca2f02e562e309223b9d44b7de8be451ec5e0"}, - {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a0b2b80321c2ed3fcf0385ec9e51a12253c50f146fddb2abbb10f033fe3d049a"}, - {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:18406efb2f5a0e57e3a5881cd9354c1512d3bb4f5c45d96d110a66114d84d23a"}, - {file = "regex-2024.9.11-cp312-cp312-win32.whl", hash = "sha256:e464b467f1588e2c42d26814231edecbcfe77f5ac414d92cbf4e7b55b2c2a776"}, - {file = "regex-2024.9.11-cp312-cp312-win_amd64.whl", hash = "sha256:9e8719792ca63c6b8340380352c24dcb8cd7ec49dae36e963742a275dfae6009"}, - {file = "regex-2024.9.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c157bb447303070f256e084668b702073db99bbb61d44f85d811025fcf38f784"}, - {file = "regex-2024.9.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4db21ece84dfeefc5d8a3863f101995de646c6cb0536952c321a2650aa202c36"}, - {file = "regex-2024.9.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:220e92a30b426daf23bb67a7962900ed4613589bab80382be09b48896d211e92"}, - {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb1ae19e64c14c7ec1995f40bd932448713d3c73509e82d8cd7744dc00e29e86"}, - {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f47cd43a5bfa48f86925fe26fbdd0a488ff15b62468abb5d2a1e092a4fb10e85"}, - {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9d4a76b96f398697fe01117093613166e6aa8195d63f1b4ec3f21ab637632963"}, - {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ea51dcc0835eea2ea31d66456210a4e01a076d820e9039b04ae8d17ac11dee6"}, - {file = "regex-2024.9.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7aaa315101c6567a9a45d2839322c51c8d6e81f67683d529512f5bcfb99c802"}, - {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c57d08ad67aba97af57a7263c2d9006d5c404d721c5f7542f077f109ec2a4a29"}, - {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f8404bf61298bb6f8224bb9176c1424548ee1181130818fcd2cbffddc768bed8"}, - {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dd4490a33eb909ef5078ab20f5f000087afa2a4daa27b4c072ccb3cb3050ad84"}, - {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:eee9130eaad130649fd73e5cd92f60e55708952260ede70da64de420cdcad554"}, - {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6a2644a93da36c784e546de579ec1806bfd2763ef47babc1b03d765fe560c9f8"}, - {file = "regex-2024.9.11-cp313-cp313-win32.whl", hash = "sha256:e997fd30430c57138adc06bba4c7c2968fb13d101e57dd5bb9355bf8ce3fa7e8"}, - {file = "regex-2024.9.11-cp313-cp313-win_amd64.whl", hash = "sha256:042c55879cfeb21a8adacc84ea347721d3d83a159da6acdf1116859e2427c43f"}, - {file = "regex-2024.9.11.tar.gz", hash = "sha256:6c188c307e8433bcb63dc1915022deb553b4203a70722fc542c363bf120a01fd"}, + {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638"}, + {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7"}, + {file = "regex-2024.11.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45"}, + {file = "regex-2024.11.6-cp311-cp311-win32.whl", hash = "sha256:c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9"}, + {file = "regex-2024.11.6-cp311-cp311-win_amd64.whl", hash = "sha256:02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60"}, + {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a"}, + {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9"}, + {file = "regex-2024.11.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad"}, + {file = "regex-2024.11.6-cp312-cp312-win32.whl", hash = "sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54"}, + {file = "regex-2024.11.6-cp312-cp312-win_amd64.whl", hash = "sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b"}, + {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84"}, + {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4"}, + {file = "regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d"}, + {file = "regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff"}, + {file = "regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a"}, + {file = "regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519"}, ] [[package]] @@ -2097,33 +1920,9 @@ files = [ {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, ] -[[package]] -name = "rio-tiler" -version = "7.1.0" -requires_python = ">=3.8" -summary = "User friendly Rasterio plugin to read raster datasets." -dependencies = [ - "attrs", - "cachetools", - "color-operations", - "httpx", - "importlib-resources>=1.1.0; python_version < \"3.9\"", - "morecantile<7.0,>=5.0", - "numexpr", - "numpy", - "pydantic~=2.0", - "pystac>=0.5.4", - "rasterio>=1.3.0", - "typing-extensions", -] -files = [ - {file = "rio_tiler-7.1.0-py3-none-any.whl", hash = "sha256:28e22271a7ab22891c82a070eaf459498a52184bb749e8ba7b78917e78d2fe5d"}, - {file = "rio_tiler-7.1.0.tar.gz", hash = "sha256:4dfa60e441ef9e60706049ecb20f5fe2dd269ccdabcc7426ece1af98e903e8a9"}, -] - [[package]] name = "sentry-sdk" -version = "2.17.0" +version = "2.18.0" requires_python = ">=3.6" summary = "Python client for Sentry (https://sentry.io)" dependencies = [ @@ -2131,33 +1930,33 @@ dependencies = [ "urllib3>=1.26.11", ] files = [ - {file = "sentry_sdk-2.17.0-py2.py3-none-any.whl", hash = "sha256:625955884b862cc58748920f9e21efdfb8e0d4f98cca4ab0d3918576d5b606ad"}, - {file = "sentry_sdk-2.17.0.tar.gz", hash = "sha256:dd0a05352b78ffeacced73a94e86f38b32e2eae15fff5f30ca5abb568a72eacf"}, + {file = "sentry_sdk-2.18.0-py2.py3-none-any.whl", hash = "sha256:ee70e27d1bbe4cd52a38e1bd28a5fadb9b17bc29d91b5f2b97ae29c0a7610442"}, + {file = "sentry_sdk-2.18.0.tar.gz", hash = "sha256:0dc21febd1ab35c648391c664df96f5f79fb0d92d7d4225cd9832e53a617cafd"}, ] [[package]] name = "sentry-sdk" -version = "2.17.0" +version = "2.18.0" extras = ["opentelemetry"] requires_python = ">=3.6" summary = "Python client for Sentry (https://sentry.io)" dependencies = [ "opentelemetry-distro>=0.35b0", - "sentry-sdk==2.17.0", + "sentry-sdk==2.18.0", ] files = [ - {file = "sentry_sdk-2.17.0-py2.py3-none-any.whl", hash = "sha256:625955884b862cc58748920f9e21efdfb8e0d4f98cca4ab0d3918576d5b606ad"}, - {file = "sentry_sdk-2.17.0.tar.gz", hash = "sha256:dd0a05352b78ffeacced73a94e86f38b32e2eae15fff5f30ca5abb568a72eacf"}, + {file = "sentry_sdk-2.18.0-py2.py3-none-any.whl", hash = "sha256:ee70e27d1bbe4cd52a38e1bd28a5fadb9b17bc29d91b5f2b97ae29c0a7610442"}, + {file = "sentry_sdk-2.18.0.tar.gz", hash = "sha256:0dc21febd1ab35c648391c664df96f5f79fb0d92d7d4225cd9832e53a617cafd"}, ] [[package]] name = "setuptools" -version = "75.3.0" -requires_python = ">=3.8" +version = "75.5.0" +requires_python = ">=3.9" summary = "Easily download, build, install, upgrade, and uninstall Python packages" files = [ - {file = "setuptools-75.3.0-py3-none-any.whl", hash = "sha256:f2504966861356aa38616760c0f66568e535562374995367b4e69c7143cf6bcd"}, - {file = "setuptools-75.3.0.tar.gz", hash = "sha256:fba5dd4d766e97be1b1681d98712680ae8f2f26d7881245f2ce9e40714f1a686"}, + {file = "setuptools-75.5.0-py3-none-any.whl", hash = "sha256:87cb777c3b96d638ca02031192d40390e0ad97737e27b6b4fa831bea86f2f829"}, + {file = "setuptools-75.5.0.tar.gz", hash = "sha256:5c4ccb41111392671f02bb5f8436dfc5a9a7185e80500531b133f5775c4163ef"}, ] [[package]] @@ -2431,10 +2230,10 @@ files = [ [[package]] name = "zipp" -version = "3.20.2" -requires_python = ">=3.8" +version = "3.21.0" +requires_python = ">=3.9" summary = "Backport of pathlib-compatible object wrapper for zip files" files = [ - {file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"}, - {file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"}, + {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"}, + {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"}, ] diff --git a/src/backend/pyproject.toml b/src/backend/pyproject.toml index a4977e1d..dbcfd037 100644 --- a/src/backend/pyproject.toml +++ b/src/backend/pyproject.toml @@ -34,7 +34,6 @@ dependencies = [ "pyodm>=1.5.11", "asgiref>=3.8.1", "drone-flightplan>=0.3.1", - "rio-tiler>=7.0.0", ] requires-python = ">=3.11" license = {text = "GPL-3.0-only"} From 15ea6945a3f25476cb81f1f54b6b92a6cfcecb8f Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Mon, 18 Nov 2024 11:07:16 +0545 Subject: [PATCH 138/390] fix: remove rio_tiler from project logic --- src/backend/app/projects/project_logic.py | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/backend/app/projects/project_logic.py b/src/backend/app/projects/project_logic.py index 82e66d03..f6be2532 100644 --- a/src/backend/app/projects/project_logic.py +++ b/src/backend/app/projects/project_logic.py @@ -20,8 +20,6 @@ from app.projects import project_schemas from minio import S3Error from psycopg.rows import dict_row -from rio_tiler.io import Reader -from rio_tiler.errors import TileOutsideBounds async def get_centroids(db: Connection): @@ -270,23 +268,3 @@ def get_project_info_from_s3(project_id: uuid.UUID, task_id: uuid.UUID): except Exception as e: log.exception(f"An error occurred while retrieving assets info: {e}") raise HTTPException(status_code=500, detail=str(e)) - - -def read_tile_from_cog(cog_path: str, x: int, y: int, z: int) -> bytes: - """ - Helper function to safely read a tile from a COG file. - This function is run in a separate thread. - """ - try: - # Open the COG file safely and fetch the specified tile - with Reader(cog_path) as tiff: - img = tiff.tile(int(x), int(y), int(z), tilesize=256) - tile = img.render() # Render the tile as a PNG byte array - return tile - - except TileOutsideBounds: - # Reraise to handle in async function - raise - except Exception as e: - # Catch any unforeseen errors and reraise as needed - raise HTTPException(status_code=500, detail=f"Unexpected error: {str(e)}") From 84bfea2004a2ac2ac0f4339fc6dbb650b513d4ce Mon Sep 17 00:00:00 2001 From: Sujit <90745363+suzit-10@users.noreply.github.com> Date: Mon, 18 Nov 2024 13:21:58 +0545 Subject: [PATCH 139/390] Feat: Refactor project creartion form UI and improve map interactivity (#339) * feat(project-creation-form): form wrapper UI update * feat(project-creation-form): form header update * feat(project-creation-form): form step switcher UI update * feat(project-creation-form): update wrapper of form content and description * feat(project-creation-form): update basic information form information and form content * feat(project-creation-form): update define AOI form information and form content * feat(project-creation-form): update Key parameters form information and form content UI * feat(project-creation-form): update generate task step form information and form content UI * feat(project-creation-form): add animaiton on info text * feat(project-creation-form): update contribution step form information and form content UI * feat(project-creation-form): update style on form wrapper * feat(dashboard): make UI responsive * feat(project-creation-form): clear all state on form component unmount * feat(task-description): prevent click event untill processing starter api and status updation success * feat(project-description): add getLayerOptionsByStatus static function * feat(project-description): refactor dynamic fill color as per task status using `getLayerOptionsByStatus` * feat(project-description): separate the logic of showing `go To Task`/`Lock Task` button by the use of `showPrimaryButton` function * feat: restrict user redirection to complete profile if user profile is loading * feat: add maxBounds `[[-179, -89],[179, 89]]` to restrict map panning --------- Co-authored-by: Sujit --- .../CreateProjectHeader/index.tsx | 21 +- .../CreateprojectLayout/index.tsx | 26 +- .../BasicInformation/index.tsx | 16 +- .../Contributions/index.tsx | 17 +- .../DescriptionContents/DefineAOI/index.tsx | 17 +- .../GenerateTask/index.tsx | 20 +- .../KeyParameters/index.tsx | 2 +- .../FormContents/BasicInformation/index.tsx | 2 +- .../FormContents/Contributions/index.tsx | 2 +- .../FormContents/DefineAOI/index.tsx | 368 +++++++++--------- .../GenerateTask/MapSection/index.tsx | 2 +- .../FormContents/GenerateTask/index.tsx | 90 +++-- .../FormContents/KeyParameters/index.tsx | 4 +- .../CreateProject/StepSwitcher/index.tsx | 114 +++--- .../src/components/CreateProject/index.tsx | 2 +- .../Dashboard/DashboardSidebar/index.tsx | 2 +- .../DescriptionBox/index.tsx | 44 ++- .../IndividualProject/MapSection/index.tsx | 95 +---- .../useMapLibreGLMap/index.ts | 4 + .../components/common/UserProfile/index.tsx | 12 +- .../src/constants/projectDescription.ts | 97 +++++ src/frontend/src/views/Dashboard/index.tsx | 15 +- 22 files changed, 529 insertions(+), 443 deletions(-) create mode 100644 src/frontend/src/constants/projectDescription.ts diff --git a/src/frontend/src/components/CreateProject/CreateProjectHeader/index.tsx b/src/frontend/src/components/CreateProject/CreateProjectHeader/index.tsx index d563610f..ef9f073e 100644 --- a/src/frontend/src/components/CreateProject/CreateProjectHeader/index.tsx +++ b/src/frontend/src/components/CreateProject/CreateProjectHeader/index.tsx @@ -7,13 +7,26 @@ import hasErrorBoundary from '@Utils/hasErrorBoundary'; const CreateProjectHeader = () => { const dispatch = useTypedDispatch(); return ( - - + {/* dispatch(toggleModal('quit-create-project'))} + /> */} + +
dispatch(toggleModal('quit-create-project'))} + role="presentation" + > + Project / +
+  Add Project +
+ dispatch(toggleModal('quit-create-project'))} /> -
Project /
-  Add Project
); }; diff --git a/src/frontend/src/components/CreateProject/CreateprojectLayout/index.tsx b/src/frontend/src/components/CreateProject/CreateprojectLayout/index.tsx index 67129049..abc9460a 100644 --- a/src/frontend/src/components/CreateProject/CreateprojectLayout/index.tsx +++ b/src/frontend/src/components/CreateProject/CreateprojectLayout/index.tsx @@ -26,6 +26,7 @@ import { convertGeojsonToFile } from '@Utils/convertLayerUtils'; import prepareFormData from '@Utils/prepareFormData'; import hasErrorBoundary from '@Utils/hasErrorBoundary'; import { getFrontOverlap, getSideOverlap, gsdToAltitude } from '@Utils/index'; +import { useEffect } from 'react'; /** * This function looks up the provided map of components to find and return @@ -260,20 +261,35 @@ const CreateprojectLayout = () => { createProject(formData); }; + useEffect(() => { + return () => { + reset(); + dispatch(resetUploadedAndDrawnAreas()); + dispatch( + setCreateProjectState({ + activeStep: 1, + splitGeojson: null, + uploadedProjectArea: null, + uploadedNoFlyZone: null, + }), + ); + }; + }, [reset, dispatch]); + return (
-
+
{/* description */} -
+
{getActiveStepDescription(stepDescriptionComponents, activeStep)}
{/* form section */} -
-
+
+
{getActiveStepForm(activeStep, formProps)}
- + {activeStep !== 1 ? (
+ +
+

Basic Information

+

+ Fill in your basic project information such as name and description +

+
+
); } diff --git a/src/frontend/src/components/CreateProject/DescriptionContents/Contributions/index.tsx b/src/frontend/src/components/CreateProject/DescriptionContents/Contributions/index.tsx index 3dad442c..3704458f 100644 --- a/src/frontend/src/components/CreateProject/DescriptionContents/Contributions/index.tsx +++ b/src/frontend/src/components/CreateProject/DescriptionContents/Contributions/index.tsx @@ -1,10 +1,15 @@ +import { FlexColumn } from '@Components/common/Layouts'; import { contributionsInfo } from '@Constants/createProject'; export default function Contributions() { - return contributionsInfo?.map(info => ( -
-

{info.key}

-

{info.description}

-
- )); + return ( + + {contributionsInfo?.map(info => ( +
+

{info.key}

+

{info.description}

+
+ ))} +
+ ); } diff --git a/src/frontend/src/components/CreateProject/DescriptionContents/DefineAOI/index.tsx b/src/frontend/src/components/CreateProject/DescriptionContents/DefineAOI/index.tsx index 1ec99fa5..f508b2be 100644 --- a/src/frontend/src/components/CreateProject/DescriptionContents/DefineAOI/index.tsx +++ b/src/frontend/src/components/CreateProject/DescriptionContents/DefineAOI/index.tsx @@ -1,10 +1,15 @@ +import { FlexColumn } from '@Components/common/Layouts'; import { DefineAOIInfo } from '@Constants/createProject'; export default function DefineAOI() { - return DefineAOIInfo?.map(info => ( -
-

{info.key}

-

{info.description}

-
- )); + return ( + + {DefineAOIInfo?.map(info => ( +
+

{info.key}

+

{info.description}

+
+ ))} +
+ ); } diff --git a/src/frontend/src/components/CreateProject/DescriptionContents/GenerateTask/index.tsx b/src/frontend/src/components/CreateProject/DescriptionContents/GenerateTask/index.tsx index b336b4ed..23dd31d2 100644 --- a/src/frontend/src/components/CreateProject/DescriptionContents/GenerateTask/index.tsx +++ b/src/frontend/src/components/CreateProject/DescriptionContents/GenerateTask/index.tsx @@ -1,18 +1,18 @@ +import { FlexColumn } from '@Components/common/Layouts'; import { taskGenerationGuidelines } from '@Constants/createProject'; export default function GenerateTask() { return ( -
-

Generate task

-

- Split the task into smaller chunks based on the given dimensions to - ensure more efficient and precise data collection and analysis. -

-
+
-

- {taskGenerationGuidelines?.title} +

Generate task

+

+ Split the task into smaller chunks based on the given dimensions to + ensure more efficient and precise data collection and analysis.

+
+
+

{taskGenerationGuidelines?.title}

    {taskGenerationGuidelines?.guidelines?.map(item => (
  1. @@ -21,6 +21,6 @@ export default function GenerateTask() { ))}
-
+ ); } diff --git a/src/frontend/src/components/CreateProject/DescriptionContents/KeyParameters/index.tsx b/src/frontend/src/components/CreateProject/DescriptionContents/KeyParameters/index.tsx index 99999db0..1e7d927b 100644 --- a/src/frontend/src/components/CreateProject/DescriptionContents/KeyParameters/index.tsx +++ b/src/frontend/src/components/CreateProject/DescriptionContents/KeyParameters/index.tsx @@ -11,7 +11,7 @@ export default function KeyParameters() { ); return ( -
+
{keyParamOption === 'basic' ? ( keyParametersInfo?.map(info => (
diff --git a/src/frontend/src/components/CreateProject/FormContents/BasicInformation/index.tsx b/src/frontend/src/components/CreateProject/FormContents/BasicInformation/index.tsx index e8d73068..c58a89a1 100644 --- a/src/frontend/src/components/CreateProject/FormContents/BasicInformation/index.tsx +++ b/src/frontend/src/components/CreateProject/FormContents/BasicInformation/index.tsx @@ -11,7 +11,7 @@ export default function BasicInformation({ const { register, errors, control } = formProps; return ( -
+
+ { }; return ( - -
-
-
-

- Project Area * -

- {!projectArea ? ( - <> - - - {drawnProjectArea && ( - { - dispatch( - setCreateProjectState({ drawnProjectArea: null }), - ); - if (resetDrawTool) { - resetDrawTool(); - } - }} - /> - )} - - {!drawProjectAreaEnable && ( - <> - -
- or -
-
- - { - // console.log(value, 'value12'); - return ( - - ); - }} - /> - - - - )} - - ) : ( - <> +
+
+
+

+ Project Area * +

+ {!projectArea ? ( + <> + -

- Total Area: {m2ToKm2(Math.trunc(totalProjectArea as number))} -

-
- { + {drawnProjectArea && ( + { dispatch( - setCreateProjectState({ isNoflyzonePresent: val }), + setCreateProjectState({ drawnProjectArea: null }), ); + if (resetDrawTool) { + resetDrawTool(); + } }} - value={isNoflyzonePresent} /> -
- {isNoflyzonePresent === 'yes' && ( -
- {noFlyZone ? ( - <> + )} + + {!drawProjectAreaEnable && ( + <> + +
+ or +
+
+ + { + // console.log(value, 'value12'); + return ( + + ); + }} + /> + + + + )} + + ) : ( + <> + +

+ Total Area: {m2ToKm2(Math.trunc(totalProjectArea as number))} +

+
+ { + dispatch( + setCreateProjectState({ isNoflyzonePresent: val }), + ); + }} + value={isNoflyzonePresent} + /> +
+ {isNoflyzonePresent === 'yes' && ( +
+ {noFlyZone ? ( + <> + +

+ Total Area:{' '} + {m2ToKm2(Math.trunc(noFlyZoneArea as number))} +

+ + ) : ( + <> + -

- Total Area:{' '} - {m2ToKm2(Math.trunc(noFlyZoneArea as number))} -

- - ) : ( - <> - - - {drawnNoFlyZone && ( - { - dispatch( - setCreateProjectState({ - drawnNoFlyZone: null, - }), - ); - if (resetDrawTool) { - resetDrawTool(); - } - }} +
+ or +
+
+ + ( + + )} /> - )} -
- {!drawNoFlyZoneEnable && ( - <> - -
- or -
-
- - ( - - )} - /> - - - )} - - )} -
- )} - - )} -
-
- -
+ + + )} + + )} +
+ )} + + )} +
+
+
- +
); }; diff --git a/src/frontend/src/components/CreateProject/FormContents/GenerateTask/MapSection/index.tsx b/src/frontend/src/components/CreateProject/FormContents/GenerateTask/MapSection/index.tsx index 8751fec9..33f64dde 100644 --- a/src/frontend/src/components/CreateProject/FormContents/GenerateTask/MapSection/index.tsx +++ b/src/frontend/src/components/CreateProject/FormContents/GenerateTask/MapSection/index.tsx @@ -83,7 +83,7 @@ const MapSection = () => { isMapLoaded={isMapLoaded} style={{ width: '100%', - height: '448px', + height: '100%', }} > diff --git a/src/frontend/src/components/CreateProject/FormContents/GenerateTask/index.tsx b/src/frontend/src/components/CreateProject/FormContents/GenerateTask/index.tsx index 0357e2db..316363f2 100644 --- a/src/frontend/src/components/CreateProject/FormContents/GenerateTask/index.tsx +++ b/src/frontend/src/components/CreateProject/FormContents/GenerateTask/index.tsx @@ -46,52 +46,50 @@ export default function GenerateTask({ formProps }: { formProps: any }) { }); return ( -
-
-
- - - setError('')} - /> - {error && } -

Recommended : 50-700

-
- -
-
- -
+
+
+ + + setError('')} + /> + {error && } +

Recommended : 50-700

+
+ +
+
+
); diff --git a/src/frontend/src/components/CreateProject/FormContents/KeyParameters/index.tsx b/src/frontend/src/components/CreateProject/FormContents/KeyParameters/index.tsx index 0e6d815b..d7d48144 100644 --- a/src/frontend/src/components/CreateProject/FormContents/KeyParameters/index.tsx +++ b/src/frontend/src/components/CreateProject/FormContents/KeyParameters/index.tsx @@ -59,7 +59,7 @@ const KeyParameters = ({ formProps }: { formProps: UseFormPropsType }) => { : altitudeInputValue; return ( -
+
{/* { )} -
+
{FinalOutputOptions?.map((option, index) => ( { const activeStep = useTypedSelector(state => state.createproject.activeStep); const toggleStep = () => {}; return ( -
- {data?.map((step: IIndividualStep, i = 1) => { - const index = i + 1; - return ( -
-
-
-
-

- {step.label} -

-

- {step.name} -

-
-
-
index - ? 'naxatw-border-red naxatw-bg-red' - : 'naxatw-bg-transparent' - }`} - onClick={() => { - if (switchSteps) { - toggleStep(); - } - }} - > - {activeStep >= index && ( - index - ? 'naxatw-text-white' - : 'naxatw-text-red' - } lg:naxatw-text-lg xl:naxatw-text-xl`} - /> - )} +
+
+ {data?.map((step: IIndividualStep, i = 1) => { + const index = i + 1; + return ( +
+
+
+
+

+ {step.label} +

+

+ {step.name} +

- {data?.length > index && ( +
= index - ? 'naxatw-border-solid naxatw-border-red' - : 'naxatw-border-dashed' + className={`${ + activeStep === index + ? 'currentstep-pointer pulse-animation naxatw-border-red' + : '' + } naxatw-flex naxatw-items-center naxatw-justify-center naxatw-rounded-full naxatw-border-[0.15rem] lg:naxatw-h-7 lg:naxatw-w-7 xl:naxatw-h-9 xl:naxatw-w-9 ${ + activeStep > index + ? 'naxatw-border-red naxatw-bg-red' + : 'naxatw-bg-transparent' }`} - /> - )} + onClick={() => { + if (switchSteps) { + toggleStep(); + } + }} + > + {activeStep >= index && ( + index + ? 'naxatw-text-white' + : 'naxatw-text-red' + } lg:naxatw-text-lg xl:naxatw-text-xl`} + /> + )} +
+ {data?.length > index && ( +
= index + ? 'naxatw-border-solid naxatw-border-red' + : 'naxatw-border-dashed' + }`} + /> + )} +
-
- ); - })} + ); + })} +
); }; diff --git a/src/frontend/src/components/CreateProject/index.tsx b/src/frontend/src/components/CreateProject/index.tsx index 159a5e42..d2cb6b85 100644 --- a/src/frontend/src/components/CreateProject/index.tsx +++ b/src/frontend/src/components/CreateProject/index.tsx @@ -6,7 +6,7 @@ import CreateProjectHeader from './CreateProjectHeader'; const CreateProject = () => { return ( -
+
diff --git a/src/frontend/src/components/Dashboard/DashboardSidebar/index.tsx b/src/frontend/src/components/Dashboard/DashboardSidebar/index.tsx index c7aa2dc7..5b315db1 100644 --- a/src/frontend/src/components/Dashboard/DashboardSidebar/index.tsx +++ b/src/frontend/src/components/Dashboard/DashboardSidebar/index.tsx @@ -9,7 +9,7 @@ const DashboardSidebar = () => { const userDetails = getLocalStorageValue('userprofile'); const role = localStorage.getItem('signedInAs'); return ( - + profile diff --git a/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx b/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx index eeb12e07..9f447a42 100644 --- a/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx +++ b/src/frontend/src/components/DroneOperatorTask/DescriptionSection/DescriptionBox/index.tsx @@ -20,6 +20,7 @@ import { import { useTypedSelector } from '@Store/hooks'; import { toggleModal } from '@Store/actions/common'; import { postTaskStatus } from '@Services/project'; +import Skeleton from '@Components/RadixComponents/Skeleton'; import DescriptionBoxComponent from './DescriptionComponent'; import QuestionBox from '../QuestionBox'; import UploadsInformation from '../UploadsInformation'; @@ -43,10 +44,20 @@ const DescriptionBox = () => { }, }, ); - const { data: taskAssetsInformation }: Record = - useGetTaskAssetsInfo(projectId as string, taskId as string); + const { + data: taskAssetsInformation, + isFetching: taskAssetsInfoLoading, + }: Record = useGetTaskAssetsInfo( + projectId as string, + taskId as string, + ); - const { mutate: updateStatus } = useMutation({ + const { mutate: updateStatus, isLoading: statusUpdating } = useMutation< + any, + any, + any, + unknown + >({ mutationFn: postTaskStatus, onSuccess: () => { queryClient.invalidateQueries(['task-assets-info']); @@ -56,17 +67,19 @@ const DescriptionBox = () => { }, }); - const { mutate: reStartImageryProcess } = useMutation({ - mutationFn: () => postProcessImagery(projectId as string, taskId as string), - onSuccess: () => { - updateStatus({ - projectId, - taskId, - data: { event: 'image_upload', updated_at: new Date().toISOString() }, - }); - toast.success('Image processing re-started'); - }, - }); + const { mutate: reStartImageryProcess, isLoading: imageProcessingStarting } = + useMutation({ + mutationFn: () => + postProcessImagery(projectId as string, taskId as string), + onSuccess: () => { + updateStatus({ + projectId, + taskId, + data: { event: 'image_upload', updated_at: new Date().toISOString() }, + }); + toast.success('Image processing re-started'); + }, + }); const { data: taskDescription }: Record = useGetIndividualTaskQuery(taskId as string, { @@ -226,6 +239,8 @@ const DescriptionBox = () => { ]} /> + {taskAssetsInfoLoading && } + {taskAssetsInformation?.assets_url && (
diff --git a/src/frontend/src/components/IndividualProject/MapSection/index.tsx b/src/frontend/src/components/IndividualProject/MapSection/index.tsx index 6cedff46..c82499b5 100644 --- a/src/frontend/src/components/IndividualProject/MapSection/index.tsx +++ b/src/frontend/src/components/IndividualProject/MapSection/index.tsx @@ -19,6 +19,10 @@ import { useTypedDispatch, useTypedSelector } from '@Store/hooks'; import { useMutation } from '@tanstack/react-query'; import getBbox from '@turf/bbox'; import hasErrorBoundary from '@Utils/hasErrorBoundary'; +import { + getLayerOptionsByStatus, + showPrimaryButton, +} from '@Constants/projectDescription'; import Legend from './Legend'; const MapSection = ({ projectData }: { projectData: Record }) => { @@ -233,81 +237,9 @@ const MapSection = ({ projectData }: { projectData: Record }) => { visibleOnMap={task?.id && taskStatusObj} geojson={task.outline as GeojsonType} interactions={['feature']} - layerOptions={ - taskStatusObj?.[`${task?.id}`] === 'LOCKED_FOR_MAPPING' - ? { - type: 'fill', - paint: { - 'fill-color': '#98BBC8', - 'fill-outline-color': '#484848', - 'fill-opacity': 0.8, - }, - } - : taskStatusObj?.[`${task?.id}`] === 'REQUEST_FOR_MAPPING' - ? { - type: 'fill', - paint: { - 'fill-color': '#F3C5C5', - 'fill-outline-color': '#484848', - 'fill-opacity': 0.7, - }, - } - : taskStatusObj?.[`${task?.id}`] === 'UNLOCKED_TO_VALIDATE' - ? { - type: 'fill', - paint: { - 'fill-color': '#176149', - 'fill-outline-color': '#484848', - 'fill-opacity': 0.5, - }, - } - : taskStatusObj?.[`${task?.id}`] === 'IMAGE_PROCESSED' - ? { - type: 'fill', - paint: { - 'fill-color': '#ACD2C4', - 'fill-outline-color': '#484848', - 'fill-opacity': 0.7, - }, - } - : taskStatusObj?.[`${task?.id}`] === 'IMAGE_UPLOADED' - ? { - type: 'fill', - paint: { - 'fill-color': '#9C77B2', - 'fill-outline-color': '#484848', - 'fill-opacity': 0.5, - }, - } - : taskStatusObj?.[`${task?.id}`] === - 'IMAGE_PROCESSING_FAILED' - ? { - type: 'fill', - paint: { - 'fill-color': '#f00000', - 'fill-outline-color': '#484848', - 'fill-opacity': 0.5, - }, - } - : taskStatusObj?.[`${task?.id}`] === - 'UNFLYABLE_TASK' - ? { - type: 'fill', - paint: { - 'fill-color': '#9EA5AD', - 'fill-outline-color': '#484848', - 'fill-opacity': 0.7, - }, - } - : { - type: 'fill', - paint: { - 'fill-color': '#ffffff', - 'fill-outline-color': '#484848', - 'fill-opacity': 0.5, - }, - } - } + layerOptions={getLayerOptionsByStatus( + taskStatusObj?.[`${task?.id}`], + )} hasImage={ taskStatusObj?.[`${task?.id}`] === 'LOCKED_FOR_MAPPING' || false } @@ -336,14 +268,11 @@ const MapSection = ({ projectData }: { projectData: Record }) => { }); }} hideButton={ - !( - !taskStatusObj?.[selectedTaskId] || - taskStatusObj?.[selectedTaskId] === 'UNLOCKED_TO_MAP' || - (taskStatusObj?.[selectedTaskId] === 'LOCKED_FOR_MAPPING' && - lockedUser?.id === userDetails?.id) || - taskStatusObj?.[selectedTaskId] === 'IMAGE_UPLOADED' || - taskStatusObj?.[selectedTaskId] === 'IMAGE_PROCESSED' || - taskStatusObj?.[selectedTaskId] === 'IMAGE_PROCESSING_FAILED' + !showPrimaryButton( + taskStatusObj?.[selectedTaskId], + lockedUser?.id, + userDetails?.id, + projectData?.author_id, ) } buttonText={ diff --git a/src/frontend/src/components/common/MapLibreComponents/useMapLibreGLMap/index.ts b/src/frontend/src/components/common/MapLibreComponents/useMapLibreGLMap/index.ts index 481faf67..33679469 100644 --- a/src/frontend/src/components/common/MapLibreComponents/useMapLibreGLMap/index.ts +++ b/src/frontend/src/components/common/MapLibreComponents/useMapLibreGLMap/index.ts @@ -19,6 +19,10 @@ export default function useMapLibreGLMap({ center: [0, 0], zoom: 1, attributionControl: false, + maxBounds: [ + [-179, -89], + [179, 89], + ], ...mapOptions, }); setMap(mapInstance); diff --git a/src/frontend/src/components/common/UserProfile/index.tsx b/src/frontend/src/components/common/UserProfile/index.tsx index bd6e0f8d..cf552fea 100644 --- a/src/frontend/src/components/common/UserProfile/index.tsx +++ b/src/frontend/src/components/common/UserProfile/index.tsx @@ -15,19 +15,21 @@ export default function UserProfile() { const userProfile = getLocalStorageValue('userprofile'); const role = localStorage.getItem('signedInAs'); - const { data: userDetails }: Record = useGetUserDetailsQuery({ - enabled: !!(userProfile?.role && role), - }); + const { data: userDetails, isFetching }: Record = + useGetUserDetailsQuery({ + enabled: !!(userProfile?.role && role), + }); useEffect(() => { if ( !userProfile || userProfile?.role?.includes(role) || - userDetails?.role?.includes(role) + userDetails?.role?.includes(role) || + isFetching ) return; navigate('/complete-profile'); - }, [userProfile, role, navigate, userDetails]); + }, [userProfile, role, navigate, userDetails, isFetching]); const settingOptions = [ { diff --git a/src/frontend/src/constants/projectDescription.ts b/src/frontend/src/constants/projectDescription.ts new file mode 100644 index 00000000..cf99e1e6 --- /dev/null +++ b/src/frontend/src/constants/projectDescription.ts @@ -0,0 +1,97 @@ +// eslint-disable-next-line import/prefer-default-export +export const getLayerOptionsByStatus = (status: string) => { + const layerOptions = { + LOCKED_FOR_MAPPING: { + type: 'fill', + paint: { + 'fill-color': '#98BBC8', + 'fill-outline-color': '#484848', + 'fill-opacity': 0.8, + }, + }, + REQUEST_FOR_MAPPING: { + type: 'fill', + paint: { + 'fill-color': '#F3C5C5', + 'fill-outline-color': '#484848', + 'fill-opacity': 0.7, + }, + }, + UNLOCKED_TO_VALIDATE: { + type: 'fill', + paint: { + 'fill-color': '#176149', + 'fill-outline-color': '#484848', + 'fill-opacity': 0.5, + }, + }, + IMAGE_PROCESSED: { + type: 'fill', + paint: { + 'fill-color': '#ACD2C4', + 'fill-outline-color': '#484848', + 'fill-opacity': 0.7, + }, + }, + IMAGE_UPLOADED: { + type: 'fill', + paint: { + 'fill-color': '#9C77B2', + 'fill-outline-color': '#484848', + 'fill-opacity': 0.5, + }, + }, + IMAGE_PROCESSING_FAILED: { + type: 'fill', + paint: { + 'fill-color': '#f00000', + 'fill-outline-color': '#484848', + 'fill-opacity': 0.5, + }, + }, + UNFLYABLE_TASK: { + type: 'fill', + paint: { + 'fill-color': '#9EA5AD', + 'fill-outline-color': '#484848', + 'fill-opacity': 0.7, + }, + }, + default: { + type: 'fill', + paint: { + 'fill-color': '#ffffff', + 'fill-outline-color': '#484848', + 'fill-opacity': 0.5, + }, + }, + }; + + // @ts-ignore + return layerOptions?.[status] || layerOptions.default; +}; + +export const showPrimaryButton = ( + status: string, + lockedUser: any, + currentUser: any, + author: any, +) => { + switch (status) { + case 'UNLOCKED_TO_MAP': + return true; + case 'LOCKED_FOR_MAPPING': + if (lockedUser === currentUser || author === currentUser) return true; + return false; + case 'IMAGE_UPLOADED': + if (lockedUser === currentUser || author === currentUser) return true; + return false; + case 'IMAGE_PROCESSED': + return true; + case 'IMAGE_PROCESSING_FAILED': + if (lockedUser === currentUser || author === currentUser) return true; + return false; + default: + return false; + } +}; diff --git a/src/frontend/src/views/Dashboard/index.tsx b/src/frontend/src/views/Dashboard/index.tsx index cb313867..5cf80459 100644 --- a/src/frontend/src/views/Dashboard/index.tsx +++ b/src/frontend/src/views/Dashboard/index.tsx @@ -1,5 +1,4 @@ import { useGetDashboardTaskStaticsQuery } from '@Api/dashboard'; -import { FlexRow } from '@Components/common/Layouts'; import { DashboardSidebar, DashboardCard } from '@Components/Dashboard'; import { DashboardCardSkeleton } from '@Components/Dashboard/DashboardCard'; import RequestLogs from '@Components/Dashboard/RequestLogs'; @@ -46,16 +45,14 @@ const Dashboard = () => { }); return ( -
- -
Profile
-
-
-
+
+
Profile
+
+
-
-
+
+
{isLoading ? ( <> {Array.from({ length: 4 }, (_, index) => ( From 847b19f0b001a0e70a046636f02ce43620966418 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Mon, 18 Nov 2024 18:56:54 +0545 Subject: [PATCH 140/390] feat: update registration registration of drone operator --- src/backend/app/db/db_models.py | 2 + .../app/migrations/versions/2803924c6ff9_.py | 34 +++++++ .../app/migrations/versions/e8770c11aa10_.py | 40 -------- src/backend/app/s3.py | 18 ---- src/backend/app/tasks/task_routes.py | 2 +- src/backend/app/tasks/task_schemas.py | 26 +++++- src/backend/app/users/user_schemas.py | 91 +++++++++++++------ 7 files changed, 126 insertions(+), 87 deletions(-) create mode 100644 src/backend/app/migrations/versions/2803924c6ff9_.py delete mode 100644 src/backend/app/migrations/versions/e8770c11aa10_.py diff --git a/src/backend/app/db/db_models.py b/src/backend/app/db/db_models.py index caeddf7c..3320174b 100644 --- a/src/backend/app/db/db_models.py +++ b/src/backend/app/db/db_models.py @@ -292,3 +292,5 @@ class DbUserProfile(Base): drone_you_own = cast(str, Column(String, nullable=True)) certified_drone_operator = cast(bool, Column(Boolean, default=False)) certificate_url = cast(str, Column(String, nullable=True)) + # drone registration certificate + registration_certificate_url = cast(str, Column(String, nullable=True)) diff --git a/src/backend/app/migrations/versions/2803924c6ff9_.py b/src/backend/app/migrations/versions/2803924c6ff9_.py new file mode 100644 index 00000000..aa585c54 --- /dev/null +++ b/src/backend/app/migrations/versions/2803924c6ff9_.py @@ -0,0 +1,34 @@ +""" + +Revision ID: 2803924c6ff9 +Revises: 4ea77c60b715 +Create Date: 2024-11-18 06:40:07.595863 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision: str = '2803924c6ff9' +down_revision: Union[str, None] = '4ea77c60b715' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('user_profile', sa.Column('certificate_url', sa.String(), nullable=True)) + op.add_column('user_profile', sa.Column('registration_certificate_url', sa.String(), nullable=True)) + op.drop_column('user_profile', 'certificate') + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('user_profile', sa.Column('certificate', postgresql.BYTEA(), autoincrement=False, nullable=True)) + op.drop_column('user_profile', 'registration_certificate_url') + op.drop_column('user_profile', 'certificate_url') + # ### end Alembic commands ### diff --git a/src/backend/app/migrations/versions/e8770c11aa10_.py b/src/backend/app/migrations/versions/e8770c11aa10_.py deleted file mode 100644 index 9ba8f8f0..00000000 --- a/src/backend/app/migrations/versions/e8770c11aa10_.py +++ /dev/null @@ -1,40 +0,0 @@ -""" - -Revision ID: e8770c11aa10 -Revises: 4ea77c60b715 -Create Date: 2024-11-14 05:49:54.523347 - -""" - -from typing import Sequence, Union - -from alembic import op -import sqlalchemy as sa -from sqlalchemy.dialects import postgresql - -# revision identifiers, used by Alembic. -revision: str = "e8770c11aa10" -down_revision: Union[str, None] = "4ea77c60b715" -branch_labels: Union[str, Sequence[str], None] = None -depends_on: Union[str, Sequence[str], None] = None - - -def upgrade() -> None: - # ### commands auto generated by Alembic - please adjust! ### - op.add_column( - "user_profile", sa.Column("certificate_url", sa.String(), nullable=True) - ) - op.drop_column("user_profile", "certificate") - # ### end Alembic commands ### - - -def downgrade() -> None: - # ### commands auto generated by Alembic - please adjust! ### - op.add_column( - "user_profile", - sa.Column( - "certificate", postgresql.BYTEA(), autoincrement=False, nullable=True - ), - ) - op.drop_column("user_profile", "certificate_url") - # ### end Alembic commands ### diff --git a/src/backend/app/s3.py b/src/backend/app/s3.py index 22d83113..fb036633 100644 --- a/src/backend/app/s3.py +++ b/src/backend/app/s3.py @@ -213,21 +213,3 @@ def get_object_metadata(bucket_name: str, object_name: str): """ client = s3_client() return client.stat_object(bucket_name, object_name) - - -def get_cog_path(bucket_name: str, project_id: str, task_id: str): - """Generate the presigned URL for a COG file in an S3 bucket. - - Args: - bucket_name (str): The name of the S3 bucket. - project_id (str): The unique project identifier. - orthophoto_name (str): The name of the COG file. - - Returns: - str: The presigned URL to access the COG file. - """ - # Construct the S3 path for the COG file - s3_path = f"dtm-data/projects/{project_id}/{task_id}/orthophoto/odm_orthophoto.tif" - - # Get the presigned URL - return get_presigned_url(bucket_name, s3_path) diff --git a/src/backend/app/tasks/task_routes.py b/src/backend/app/tasks/task_routes.py index db96a2c5..cc37f152 100644 --- a/src/backend/app/tasks/task_routes.py +++ b/src/backend/app/tasks/task_routes.py @@ -36,7 +36,7 @@ async def get_task_stats( return await task_logic.get_task_stats(db, user_data) -@router.get("/", response_model=list[task_schemas.UserTasksStatsOut]) +@router.get("/") async def list_tasks( db: Annotated[Connection, Depends(database.get_db)], user_data: Annotated[AuthUser, Depends(login_required)], diff --git a/src/backend/app/tasks/task_schemas.py b/src/backend/app/tasks/task_schemas.py index 16c43576..69d5d9bd 100644 --- a/src/backend/app/tasks/task_schemas.py +++ b/src/backend/app/tasks/task_schemas.py @@ -1,4 +1,5 @@ -from pydantic import BaseModel +from app.config import settings +from pydantic import BaseModel, model_validator from app.models.enums import EventType, HTTPStatus, State import uuid from datetime import datetime @@ -8,6 +9,7 @@ from psycopg.rows import class_row, dict_row from typing import List, Literal, Optional from pydantic.functional_validators import field_validator +from app.s3 import is_connection_secure class Geometry(BaseModel): @@ -170,6 +172,23 @@ class UserTasksStatsOut(BaseModel): project_task_index: int project_name: str updated_at: Optional[datetime] + registration_certificate_url: Optional[str] + + @model_validator(mode="after") + def set_registration_certificate_url(cls, values): + """Set registration_certificate_url before rendering the model.""" + url = values.registration_certificate_url + if not url: + return values + + minio_url, is_secure = is_connection_secure(settings.S3_ENDPOINT) + # Ensure image_dir starts with a forward slash + url = url if url.startswith("/") else f"/{url}" + # Construct the full URL + protocol = "https" if is_secure else "http" + url = f"{protocol}://{minio_url}/{settings.S3_BUCKET_NAME}{url}" + values.registration_certificate_url = url + return values @staticmethod async def get_tasks_by_user( @@ -186,13 +205,16 @@ async def get_tasks_by_user( ST_Area(ST_Transform(tasks.outline, 3857)) / 1000000 AS task_area, task_events.created_at, task_events.updated_at, - task_events.state + task_events.state, + user_profile.registration_certificate_url AS registration_certificate_url FROM task_events LEFT JOIN tasks ON task_events.task_id = tasks.id LEFT JOIN projects ON task_events.project_id = projects.id + LEFT JOIN + user_profile ON task_events.user_id = user_profile.user_id WHERE ( %(role)s = 'DRONE_PILOT' diff --git a/src/backend/app/users/user_schemas.py b/src/backend/app/users/user_schemas.py index 1b5f5608..d0630afd 100644 --- a/src/backend/app/users/user_schemas.py +++ b/src/backend/app/users/user_schemas.py @@ -101,6 +101,7 @@ class BaseUserProfile(BaseModel): certified_drone_operator: Optional[bool] = False role: Optional[List[UserRole]] = None certificate_file: Optional[str] = None + registration_file: Optional[str] = None @field_validator("role", mode="after") @classmethod @@ -143,19 +144,40 @@ class DbUserProfile(BaseUserProfile): user_id: int @staticmethod - async def _handle_certificate_file(profile: BaseModel, user_id: int): - """Handle the certificate file upload and return the presigned URL.""" - certificate_file = getattr(profile, "certificate_file", None) - if certificate_file: - s3_path = f"dtm-data/users/{user_id}/certificate/{certificate_file}" - try: - presigned_url = get_presigned_url( - settings.S3_BUCKET_NAME, s3_path, expires=1 - ) - return presigned_url, s3_path - except Exception as e: - log.error(f"Failed to generate presigned URL for certificate file: {e}") - return None + async def _handle_file_upload(profile: UserProfileCreate, user_id: int): + """ + Handle file uploads (certificate and registration) and return presigned URLs and S3 paths. + + Args: + profile (UserProfileCreate): The user profile containing file fields. + user_id (int): The user's ID. + + Returns: + dict: A dictionary with presigned URLs and S3 paths for each file type. + """ + result = {} + + file_paths = { + "certificate_file": f"dtm-data/users/{user_id}/certificate/{profile.certificate_file}", + "registration_file": f"dtm-data/users/{user_id}/registration/{profile.registration_file}", + } + + for file_type, s3_path in file_paths.items(): + file_name = getattr(profile, file_type, None) + if file_name: + try: + presigned_url = get_presigned_url( + settings.S3_BUCKET_NAME, s3_path, expires=1 + ) + result[file_type] = { + "presigned_url": presigned_url, + "s3_path": s3_path, + } + except Exception as e: + log.error(f"Failed to generate presigned URL for {file_type}: {e}") + result[file_type] = {"error": str(e)} + + return result @staticmethod async def _update_roles(db: Connection, user_id: int, new_roles: Optional[list]): @@ -178,11 +200,18 @@ async def create(db: Connection, user_id: int, profile_create: UserProfileCreate """Create a new user profile.""" model_data = profile_create.model_dump(exclude_none=True, exclude={"password"}) - # Handle certificate file - result = await DbUserProfile._handle_certificate_file(profile_create, user_id) - if result: - certificate_url, path = result - model_data["certificate_url"] = path + field_mapping = { + "certificate_file": "certificate_url", + "registration_file": "registration_certificate_url", + } + + results = await DbUserProfile._handle_file_upload(profile_create, user_id) + for file_type, file_data in results.items(): + if file_data.get("s3_path"): + model_data[field_mapping[file_type]] = file_data["s3_path"] + + model_data.pop("certificate_file", None) + model_data.pop("registration_file", None) # Prepare the SQL query for inserting the new profile columns = ", ".join(model_data.keys()) @@ -198,21 +227,30 @@ async def create(db: Connection, user_id: int, profile_create: UserProfileCreate async with db.cursor() as cur: await cur.execute(sql, model_data) - if result: - model_data["certificate_url"] = certificate_url + for file_type, url_key in field_mapping.items(): + if results.get(file_type): + model_data[url_key] = results[file_type].get("presigned_url") return model_data @staticmethod async def update(db: Connection, user_id: int, profile_update: UserProfileUpdate): """Update or insert a user profile.""" + field_mapping = { + "certificate_file": "certificate_url", + "registration_file": "registration_certificate_url", + } + model_data = profile_update.model_dump( exclude_none=True, exclude={"password", "old_password", "certificate_file"} ) - result = await DbUserProfile._handle_certificate_file(profile_update, user_id) - if result: - certificate_url, path = result - model_data["certificate_url"] = path + results = await DbUserProfile._handle_file_upload(profile_update, user_id) + for file_type, file_data in results.items(): + if file_data.get("s3_path"): + model_data[field_mapping[file_type]] = file_data["s3_path"] + + model_data.pop("certificate_file", None) + model_data.pop("registration_file", None) await DbUserProfile._update_roles(db, user_id, model_data.get("role")) @@ -255,8 +293,9 @@ async def update(db: Connection, user_id: int, profile_update: UserProfileUpdate "user_id": user_id, }, ) - if result: - model_data["certificate_url"] = certificate_url + for file_type, url_key in field_mapping.items(): + if results.get(file_type): + model_data[url_key] = results[file_type].get("presigned_url") return model_data From 604452d59023f37e3a8fb3a40b072cb952253a07 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 13:13:40 +0000 Subject: [PATCH 141/390] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../app/migrations/versions/2803924c6ff9_.py | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/backend/app/migrations/versions/2803924c6ff9_.py b/src/backend/app/migrations/versions/2803924c6ff9_.py index aa585c54..c3d735a2 100644 --- a/src/backend/app/migrations/versions/2803924c6ff9_.py +++ b/src/backend/app/migrations/versions/2803924c6ff9_.py @@ -5,6 +5,7 @@ Create Date: 2024-11-18 06:40:07.595863 """ + from typing import Sequence, Union from alembic import op @@ -12,23 +13,33 @@ from sqlalchemy.dialects import postgresql # revision identifiers, used by Alembic. -revision: str = '2803924c6ff9' -down_revision: Union[str, None] = '4ea77c60b715' +revision: str = "2803924c6ff9" +down_revision: Union[str, None] = "4ea77c60b715" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: # ### commands auto generated by Alembic - please adjust! ### - op.add_column('user_profile', sa.Column('certificate_url', sa.String(), nullable=True)) - op.add_column('user_profile', sa.Column('registration_certificate_url', sa.String(), nullable=True)) - op.drop_column('user_profile', 'certificate') + op.add_column( + "user_profile", sa.Column("certificate_url", sa.String(), nullable=True) + ) + op.add_column( + "user_profile", + sa.Column("registration_certificate_url", sa.String(), nullable=True), + ) + op.drop_column("user_profile", "certificate") # ### end Alembic commands ### def downgrade() -> None: # ### commands auto generated by Alembic - please adjust! ### - op.add_column('user_profile', sa.Column('certificate', postgresql.BYTEA(), autoincrement=False, nullable=True)) - op.drop_column('user_profile', 'registration_certificate_url') - op.drop_column('user_profile', 'certificate_url') + op.add_column( + "user_profile", + sa.Column( + "certificate", postgresql.BYTEA(), autoincrement=False, nullable=True + ), + ) + op.drop_column("user_profile", "registration_certificate_url") + op.drop_column("user_profile", "certificate_url") # ### end Alembic commands ### From 6e5ba0f11ff2d76cb0144b7ec2969207af262411 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 19 Nov 2024 09:45:21 +0545 Subject: [PATCH 142/390] [pre-commit.ci] pre-commit autoupdate (#340) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/commitizen-tools/commitizen: v3.30.1 → v3.31.0](https://github.com/commitizen-tools/commitizen/compare/v3.30.1...v3.31.0) - [github.com/astral-sh/ruff-pre-commit: v0.7.3 → v0.7.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.7.3...v0.7.4) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b876e5ef..8d045fd4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -79,7 +79,7 @@ repos: # Versioning: Commit messages & changelog - repo: https://github.com/commitizen-tools/commitizen - rev: v3.30.1 + rev: v3.31.0 hooks: - id: commitizen stages: [commit-msg] @@ -87,7 +87,7 @@ repos: # Lint / autoformat: Python code - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: "v0.7.3" + rev: "v0.7.4" hooks: # Run the linter - id: ruff From 140382419a5bbed7eb7fc9230338ca388284d187 Mon Sep 17 00:00:00 2001 From: Sujit <90745363+suzit-10@users.noreply.github.com> Date: Tue, 19 Nov 2024 10:16:18 +0545 Subject: [PATCH 143/390] Fix: Application crash on file upload and implement zoom to orthophoto (#341) * feat(project-creation-form): form wrapper UI update * feat(project-creation-form): form header update * feat(project-creation-form): form step switcher UI update * feat(project-creation-form): update wrapper of form content and description * feat(project-creation-form): update basic information form information and form content * feat(project-creation-form): update define AOI form information and form content * feat(project-creation-form): update Key parameters form information and form content UI * feat(project-creation-form): update generate task step form information and form content UI * feat(project-creation-form): add animaiton on info text * feat(project-creation-form): update contribution step form information and form content UI * feat(project-creation-form): update style on form wrapper * feat(dashboard): make UI responsive * feat(project-creation-form): clear all state on form component unmount * feat(task-description): prevent click event untill processing starter api and status updation success * feat(project-description): add getLayerOptionsByStatus static function * feat(project-description): refactor dynamic fill color as per task status using `getLayerOptionsByStatus` * feat(project-description): separate the logic of showing `go To Task`/`Lock Task` button by the use of `showPrimaryButton` function * feat: restrict user redirection to complete profile if user profile is loading * feat: add maxBounds `[[-179, -89],[179, 89]]` to restrict map panning * fix(#332): fix crash application on file upload on firefox in firefox `File.lastmodifiedDate` has no longer support fixed replacing `lastModifiedDate` with `lastModified` * feat: add zoomToLayer optional feature on COGOrthophotoViewer component * feat(orthophoto-preview): implement zoom to orthohphoto --------- Co-authored-by: Sujit --- .../ModalContent/TaskOrthophotoPreview.tsx | 18 +++++------------- .../COGOrthophotoViewer/index.tsx | 11 ++++++++++- .../src/components/common/UploadArea/index.tsx | 6 +++--- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/frontend/src/components/DroneOperatorTask/ModalContent/TaskOrthophotoPreview.tsx b/src/frontend/src/components/DroneOperatorTask/ModalContent/TaskOrthophotoPreview.tsx index 902068be..68dff04f 100644 --- a/src/frontend/src/components/DroneOperatorTask/ModalContent/TaskOrthophotoPreview.tsx +++ b/src/frontend/src/components/DroneOperatorTask/ModalContent/TaskOrthophotoPreview.tsx @@ -4,7 +4,8 @@ import COGOrthophotoViewer from '@Components/common/MapLibreComponents/COGOrthop import MapContainer from '@Components/common/MapLibreComponents/MapContainer'; import { setSelectedTaskDetailToViewOrthophoto } from '@Store/actions/droneOperatorTask'; import { useTypedSelector } from '@Store/hooks'; -import { LngLatBoundsLike, RasterSourceSpecification } from 'maplibre-gl'; +import hasErrorBoundary from '@Utils/hasErrorBoundary'; +import { RasterSourceSpecification } from 'maplibre-gl'; import { useEffect, useMemo } from 'react'; import { useDispatch } from 'react-redux'; @@ -12,10 +13,6 @@ const { COG_URL } = process.env; const TaskOrthophotoPreview = () => { const dispatch = useDispatch(); - const taskOutline = useTypedSelector( - state => - state.droneOperatorTask.selectedTaskDetailToViewOrthophoto?.outline, - ); const taskIdFromRedux = useTypedSelector( state => state.droneOperatorTask.selectedTaskDetailToViewOrthophoto?.taskId, ); @@ -26,7 +23,7 @@ const TaskOrthophotoPreview = () => { const { map, isMapLoaded } = useMapLibreGLMap({ containerId: 'orthophoto-map', mapOptions: { - zoom: 21, + zoom: 5, center: [0, 0], }, disableRotation: true, @@ -42,12 +39,6 @@ const TaskOrthophotoPreview = () => { [projectId, taskId], ); - useEffect(() => { - if (!map || !isMapLoaded || !taskOutline) return; - const { bbox } = taskOutline.properties; - map?.fitBounds(bbox as LngLatBoundsLike, { padding: 50, duration: 500 }); - }, [map, isMapLoaded, taskOutline]); - useEffect(() => { return () => { dispatch(setSelectedTaskDetailToViewOrthophoto(null)); @@ -70,10 +61,11 @@ const TaskOrthophotoPreview = () => { id="task-orthophoto" source={orthophotoSource} visibleOnMap + zoomToLayer />
); }; -export default TaskOrthophotoPreview; +export default hasErrorBoundary(TaskOrthophotoPreview); diff --git a/src/frontend/src/components/common/MapLibreComponents/COGOrthophotoViewer/index.tsx b/src/frontend/src/components/common/MapLibreComponents/COGOrthophotoViewer/index.tsx index 3a465717..c3488d9b 100644 --- a/src/frontend/src/components/common/MapLibreComponents/COGOrthophotoViewer/index.tsx +++ b/src/frontend/src/components/common/MapLibreComponents/COGOrthophotoViewer/index.tsx @@ -9,6 +9,7 @@ interface IViewOrthophotoProps { id: string; source: RasterSourceSpecification; visibleOnMap?: Boolean; + zoomToLayer?: Boolean; } const COGOrthophotoViewer = ({ @@ -17,6 +18,7 @@ const COGOrthophotoViewer = ({ id, source, visibleOnMap, + zoomToLayer = false, }: IViewOrthophotoProps) => { useEffect(() => { if (!map || !isMapLoaded || !source || !visibleOnMap) return; @@ -34,14 +36,21 @@ const COGOrthophotoViewer = ({ }); } + const zoomToSource = setTimeout(() => { + if (map?.getSource(id) && zoomToLayer) + // @ts-ignore + map?.fitBounds(map?.getSource(id)?.bounds, { padding: 50 }); + }, 1000); + // eslint-disable-next-line consistent-return return () => { if (map?.getSource(id)) { map?.removeSource(id); if (map?.getLayer(id)) map?.removeLayer(id); } + clearTimeout(zoomToSource); }; - }, [map, isMapLoaded, id, source, visibleOnMap]); + }, [map, isMapLoaded, id, source, visibleOnMap, zoomToLayer]); return null; }; diff --git a/src/frontend/src/components/common/UploadArea/index.tsx b/src/frontend/src/components/common/UploadArea/index.tsx index 258434d1..8fdb5cfd 100644 --- a/src/frontend/src/components/common/UploadArea/index.tsx +++ b/src/frontend/src/components/common/UploadArea/index.tsx @@ -141,14 +141,14 @@ export default function FileUpload({ key={id} className="naxatw-items-center naxatw-justify-between naxatw-rounded-lg naxatw-border naxatw-px-4 naxatw-py-2" > - +
{file?.name}
{file && file?.lastModified && (

- Uploaded on - {format(new Date(file.lastModifiedDate), 'MMM dd yyyy')} + Uploaded on{' '} + {format(new Date(file.lastModified), 'MMM dd yyyy')}

)}
From 98e93328a980a17ba3ab7bee5a74339f119442c9 Mon Sep 17 00:00:00 2001 From: Stephen Mather <1174901+smathermather@users.noreply.github.com> Date: Tue, 19 Nov 2024 22:46:53 -0500 Subject: [PATCH 144/390] Upload align.laz along with Drone Images (#343) * Upload GCP along with Drone Images * Add align.laz to available uploads * Add descriptions for align * add align.laz modal --------- Co-authored-by: Niraj Adhikari --- src/backend/app/projects/image_processing.py | 12 +++++++++-- .../DescriptionSection/UploadsBox/index.tsx | 21 +++++++++++++++---- src/frontend/src/constants/modalContents.tsx | 2 +- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/backend/app/projects/image_processing.py b/src/backend/app/projects/image_processing.py index f9b6020d..ae74ced9 100644 --- a/src/backend/app/projects/image_processing.py +++ b/src/backend/app/projects/image_processing.py @@ -49,7 +49,9 @@ def options_list_to_dict(self, options=[]): return opts def download_object(self, bucket_name: str, obj, images_folder: str): - if obj.object_name.endswith((".jpg", ".jpeg", ".JPG", ".png", ".PNG")): + if obj.object_name.endswith( + (".jpg", ".jpeg", ".JPG", ".png", ".PNG", ".txt", ".laz") + ): # Images and GCP File local_path = Path(images_folder) / Path(obj.object_name).name local_path.parent.mkdir(parents=True, exist_ok=True) get_file_from_bucket(bucket_name, obj.object_name, local_path) @@ -86,7 +88,13 @@ def list_images(self, directory): path = Path(directory) for file in path.rglob("*"): - if file.suffix.lower() in {".jpg", ".jpeg", ".png"}: + if file.suffix.lower() in { + ".jpg", + ".jpeg", + ".png", + ".txt", + ".laz", + }: # Images, GCP File, and align.laz images.append(str(file)) return images diff --git a/src/frontend/src/components/DroneOperatorTask/DescriptionSection/UploadsBox/index.tsx b/src/frontend/src/components/DroneOperatorTask/DescriptionSection/UploadsBox/index.tsx index c88c0ae0..c7f91783 100644 --- a/src/frontend/src/components/DroneOperatorTask/DescriptionSection/UploadsBox/index.tsx +++ b/src/frontend/src/components/DroneOperatorTask/DescriptionSection/UploadsBox/index.tsx @@ -6,7 +6,11 @@ import { toggleModal } from '@Store/actions/common'; import { setFiles } from '@Store/actions/droneOperatorTask'; import { useTypedDispatch, useTypedSelector } from '@Store/hooks'; -const UploadsBox = ({ label = 'Upload Raw Image' }: { label?: string }) => { +const UploadsBox = ({ + label = 'Upload Images, GCP, and align.laz', +}: { + label?: string; +}) => { const dispatch = useTypedDispatch(); const files = useTypedSelector(state => state.droneOperatorTask.files); const handleFileChange = (event: any) => { @@ -34,9 +38,18 @@ const UploadsBox = ({ label = 'Upload Raw Image' }: { label?: string }) => { cloud_upload -

- The supported file formats are .jpg, .jpeg, .png -

+
+

+ The supported file formats are .jpg, .jpeg, .png. +

+

+ The GCP file should be named gcp_list.txt +

+

+ The align file should be named align.laz +

+
+ {files.length > 0 && (

{files.length} items selected diff --git a/src/frontend/src/constants/modalContents.tsx b/src/frontend/src/constants/modalContents.tsx index 0ffc584c..f31689ed 100644 --- a/src/frontend/src/constants/modalContents.tsx +++ b/src/frontend/src/constants/modalContents.tsx @@ -36,7 +36,7 @@ export function getModalContent(content: ModalContentsType): ModalReturnType { case 'raw-image-preview': return { className: '!naxatw-w-[95vw] md:!naxatw-w-[60vw]', - title: 'Upload Raw Image', + title: 'Upload Images, GCP, and align.laz', content: , }; From 84e76958971ddecbf21e99ae778543a976eefee6 Mon Sep 17 00:00:00 2001 From: Pradip Thapa Date: Fri, 22 Nov 2024 10:03:15 +0545 Subject: [PATCH 145/390] fix: update take-off point from 200m to 350m (#348) --- src/backend/app/waypoints/waypoint_routes.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backend/app/waypoints/waypoint_routes.py b/src/backend/app/waypoints/waypoint_routes.py index c4317103..fab6f6ba 100644 --- a/src/backend/app/waypoints/waypoint_routes.py +++ b/src/backend/app/waypoints/waypoint_routes.py @@ -66,11 +66,11 @@ async def get_task_waypoint( if take_off_point: take_off_point = [take_off_point.longitude, take_off_point.latitude] - # Validate that the take-off point is within a 200m buffer of the task boundary - if not check_point_within_buffer(take_off_point, task_geojson, 200): + # Validate that the take-off point is within a 350 buffer of the task boundary + if not check_point_within_buffer(take_off_point, task_geojson, 350): raise HTTPException( status_code=400, - detail="Take off point should be within 200m of the boundary", + detail="Take off point should be within 350m of the boundary", ) # Update take_off_point in tasks table From cd748c70482dc6e4913ec61181bdda18ad146f40 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Fri, 22 Nov 2024 13:56:02 +0545 Subject: [PATCH 146/390] docs: add pull request template --- .github/pull_request_template.md | 39 ++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..b08d06ce --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,39 @@ +## What type of PR is this? (check all applicable) + +- [ ] 🍕 Feature +- [ ] 🐛 Bug Fix +- [ ] 📝 Documentation +- [ ] 🧑‍💻 Refactor +- [ ] ✅ Test +- [ ] 🤖 Build or CI +- [ ] ❓ Other (please specify) + +## Related Issue + +Example: Fixes #123 + +## Describe this PR + +A brief description of how this solves the issue. + +## Screenshots + +Please provide screenshots of the change. + +## Alternative Approaches Considered + +Did you attempt any other approaches that are not documented in code? + +## Review Guide + +Notes for the reviewer. How to test this change? + +## Checklist before requesting a review + +- 📖 Read the HOT Code of Conduct: +- 👷‍♀️ Create small PRs. In most cases, this will be possible. +- ✅ Provide tests for your changes. +- 📝 Use descriptive commit messages. +- 📗 Update any related documentation and include any relevant screenshots. + +## [optional] What gif best describes this PR or how it makes you feel? \ No newline at end of file From e08a0d424e889204b1e60107d10a8cf03c76c96e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 22 Nov 2024 08:13:26 +0000 Subject: [PATCH 147/390] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b08d06ce..b00c0cc0 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -36,4 +36,4 @@ Notes for the reviewer. How to test this change? - 📝 Use descriptive commit messages. - 📗 Update any related documentation and include any relevant screenshots. -## [optional] What gif best describes this PR or how it makes you feel? \ No newline at end of file +## [optional] What gif best describes this PR or how it makes you feel? From eb7d058ad87860f2648371b4469c535b93346bda Mon Sep 17 00:00:00 2001 From: Bijay Rauniyar <155698689+bijayrauniyar0@users.noreply.github.com> Date: Fri, 22 Nov 2024 15:13:39 +0545 Subject: [PATCH 148/390] refactor(frontend): reset takeoff point state incase the location is not valid (#351) --- .../src/components/DroneOperatorTask/MapSection/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/frontend/src/components/DroneOperatorTask/MapSection/index.tsx b/src/frontend/src/components/DroneOperatorTask/MapSection/index.tsx index e8ccced3..f5c25ba3 100644 --- a/src/frontend/src/components/DroneOperatorTask/MapSection/index.tsx +++ b/src/frontend/src/components/DroneOperatorTask/MapSection/index.tsx @@ -88,6 +88,7 @@ const MapSection = ({ className }: { className?: string }) => { }, onError: (err: any) => { toast.error(err?.response?.data?.detail || err.message); + dispatch(setSelectedTakeOffPoint(null)); }, }); From deb917e2f426525bea6c9f651dcad6379074476b Mon Sep 17 00:00:00 2001 From: Niraj Adhikari Date: Fri, 22 Nov 2024 15:19:51 +0545 Subject: [PATCH 149/390] optimize: zoom to geotiff to bounds --- .../ModalContent/TaskOrthophotoPreview.tsx | 14 ++++++++------ .../COGOrthophotoViewer/index.tsx | 18 ++++++++++++------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/frontend/src/components/DroneOperatorTask/ModalContent/TaskOrthophotoPreview.tsx b/src/frontend/src/components/DroneOperatorTask/ModalContent/TaskOrthophotoPreview.tsx index 68dff04f..fdf981ab 100644 --- a/src/frontend/src/components/DroneOperatorTask/ModalContent/TaskOrthophotoPreview.tsx +++ b/src/frontend/src/components/DroneOperatorTask/ModalContent/TaskOrthophotoPreview.tsx @@ -57,12 +57,14 @@ const TaskOrthophotoPreview = () => { }} > - + {isMapLoaded && ( + + )}

); diff --git a/src/frontend/src/components/common/MapLibreComponents/COGOrthophotoViewer/index.tsx b/src/frontend/src/components/common/MapLibreComponents/COGOrthophotoViewer/index.tsx index c3488d9b..9780bd9e 100644 --- a/src/frontend/src/components/common/MapLibreComponents/COGOrthophotoViewer/index.tsx +++ b/src/frontend/src/components/common/MapLibreComponents/COGOrthophotoViewer/index.tsx @@ -23,6 +23,16 @@ const COGOrthophotoViewer = ({ useEffect(() => { if (!map || !isMapLoaded || !source || !visibleOnMap) return; + const handleZoomToGeoTiff = () => { + if (map?.getSource(id)) + // @ts-ignore + map?.fitBounds(map?.getSource(id)?.bounds, { + padding: 50, + duration: 1000, + zoom: 18, + }); + }; + // Registers the 'cog' protocol with the mapLibre instance, enabling support for Cloud Optimized GeoTIFF (COG) files mapLibre?.addProtocol('cog', cogProtocol); @@ -36,19 +46,15 @@ const COGOrthophotoViewer = ({ }); } - const zoomToSource = setTimeout(() => { - if (map?.getSource(id) && zoomToLayer) - // @ts-ignore - map?.fitBounds(map?.getSource(id)?.bounds, { padding: 50 }); - }, 1000); + if (zoomToLayer && map?.getLayer(id)) map.on('idle', handleZoomToGeoTiff); // eslint-disable-next-line consistent-return return () => { if (map?.getSource(id)) { map?.removeSource(id); if (map?.getLayer(id)) map?.removeLayer(id); + map.off('idle', handleZoomToGeoTiff); } - clearTimeout(zoomToSource); }; }, [map, isMapLoaded, id, source, visibleOnMap, zoomToLayer]); From 4fd6d67e519a1c8e14c328af425d12b340e88c17 Mon Sep 17 00:00:00 2001 From: Sujit Date: Mon, 25 Nov 2024 16:34:46 +0545 Subject: [PATCH 150/390] fix(profile-update): UI Issue --- src/frontend/src/views/UpdateUserProfile/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/views/UpdateUserProfile/index.tsx b/src/frontend/src/views/UpdateUserProfile/index.tsx index a5cce424..7c576740 100644 --- a/src/frontend/src/views/UpdateUserProfile/index.tsx +++ b/src/frontend/src/views/UpdateUserProfile/index.tsx @@ -43,7 +43,7 @@ const UpdateUserProfile = () => {
-
+
{ />
-
+
{getActiveFormContent(userProfileActiveTab, signedInAs)}
From 2392956651287d31d2e1cbb6b00adea1b66dbe9b Mon Sep 17 00:00:00 2001 From: Sujit Date: Mon, 25 Nov 2024 16:38:47 +0545 Subject: [PATCH 151/390] feat: add method parameter on `callApiSimultaneously` function --- src/frontend/src/utils/callApiSimultaneously.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/utils/callApiSimultaneously.ts b/src/frontend/src/utils/callApiSimultaneously.ts index d649bac3..ed879494 100644 --- a/src/frontend/src/utils/callApiSimultaneously.ts +++ b/src/frontend/src/utils/callApiSimultaneously.ts @@ -2,7 +2,11 @@ import axios from 'axios'; import { toast } from 'react-toastify'; // function that calls the api simultaneously -export default async function callApiSimultaneously(urls: any, data: any) { +export default async function callApiSimultaneously( + urls: any, + data: any, + method: 'post' | 'patch' | 'put' = 'put', +) { // eslint-disable-next-line no-promise-executor-return const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); @@ -12,6 +16,9 @@ export default async function callApiSimultaneously(urls: any, data: any) { n: number, ): Promise => { try { + if (method === 'put') return await axios.put(url, singleData); + if (method === 'patch') return await axios.patch(url, singleData); + if (method === 'post') return await axios.post(url, singleData); return await axios.put(url, singleData); } catch (err) { if (n === 1) throw err; From 77ab1d112fba826312eb87b83a7be610e9bf96b0 Mon Sep 17 00:00:00 2001 From: Sujit Date: Tue, 26 Nov 2024 10:02:53 +0545 Subject: [PATCH 152/390] feat(update-profile): post add files `certificate` and `drone registration` file along with the other details --- .../UpdateUserDetails/OtherDetails/index.tsx | 98 ++++++++++++++++--- 1 file changed, 84 insertions(+), 14 deletions(-) diff --git a/src/frontend/src/components/UpdateUserDetails/OtherDetails/index.tsx b/src/frontend/src/components/UpdateUserDetails/OtherDetails/index.tsx index dc870efc..3cb865e3 100644 --- a/src/frontend/src/components/UpdateUserDetails/OtherDetails/index.tsx +++ b/src/frontend/src/components/UpdateUserDetails/OtherDetails/index.tsx @@ -1,4 +1,4 @@ -import { useForm } from 'react-hook-form'; +import { Controller, useForm } from 'react-hook-form'; import { getLocalStorageValue } from '@Utils/getLocalStorageValue'; import { Flex, FlexColumn } from '@Components/common/Layouts'; import { FormControl, Input, Label } from '@Components/common/FormUI'; @@ -12,6 +12,7 @@ import { Button } from '@Components/RadixComponents/Button'; import { patchUserProfile } from '@Services/common'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { toast } from 'react-toastify'; +import callApiSimultaneously from '@Utils/callApiSimultaneously'; const OtherDetails = () => { const userProfile = getLocalStorageValue('userprofile'); @@ -27,12 +28,15 @@ const OtherDetails = () => { experience_years: userProfile?.experience_years || null, certified_drone_operator: userProfile?.certified_drone_operator || false, drone_you_own: userProfile?.drone_you_own || null, + certificate_file: userProfile?.certificate_file || null, + registration_file: userProfile?.registration_file || null, }; const queryClient = useQueryClient(); - const { register, handleSubmit, setValue, formState } = useForm({ - defaultValues: initialState, - }); + const { register, handleSubmit, setValue, control, formState, getValues } = + useForm({ + defaultValues: initialState, + }); const { mutate: updateOtherDetails, isLoading } = useMutation< any, @@ -41,7 +45,23 @@ const OtherDetails = () => { unknown >({ mutationFn: payloadDataObject => patchUserProfile(payloadDataObject), - onSuccess: () => { + onSuccess: async data => { + const results = data.data?.results; + const values = getValues(); + const urlsToUpload = []; + const assetsToUpload = []; + if (results?.certificate_url) { + urlsToUpload.push(results?.certificate_url); + assetsToUpload.push(values?.certificate_file[0]); + } + if (results?.registration_certificate_url) { + urlsToUpload.push(results?.registration_certificate_url); + assetsToUpload.push(values?.registration_file?.[0]); + } + if (urlsToUpload.length) { + await callApiSimultaneously(urlsToUpload, assetsToUpload, 'patch'); + } + queryClient.invalidateQueries(['user-profile']); toast.success('Details Updated Successfully'); @@ -54,11 +74,18 @@ const OtherDetails = () => { }); const onSubmit = (formData: Record) => { - updateOtherDetails({ userId: userProfile?.id, data: formData }); + updateOtherDetails({ + userId: userProfile?.id, + data: { + ...formData, + certificate_file: formData?.certificate_file?.[0]?.file?.name, + registration_file: formData?.registration_file?.[0]?.file?.name, + }, + }); }; return ( -
+

Other Details @@ -127,14 +154,57 @@ const OtherDetails = () => { formState.errors?.certified_drone_operator?.message as string } /> + {isCertifiedDroneOperator === 'yes' && ( + { + return ( + <> + {}} + // @ts-ignore + setValue={setValue} + name="certificate_file" + data={value} + onChange={() => {}} + fileAccept=".pdf, .jpeg, .png" + placeholder="The supported file formats are pdf, .jpeg, .png" + /> + + + ); + }} + /> + )} + + + + { + // console.log(value, 'value12'); + return ( + {}} + // @ts-ignore + setValue={setValue} + name="registration_file" + data={value} + onChange={() => {}} + fileAccept=".pdf, .jpeg, .png" + placeholder="The supported file formats are pdf, .jpeg, .png" + /> + ); + }} + /> - {}} - onChange={() => {}} - setValue={() => {}} - placeholder="*The supported file formats are pdf, .jpeg, .png" - />