diff --git a/app/Entities/UserDTOs/certification_entity.py b/app/Entities/UserDTOs/certification_entity.py index d7015c0..737fe28 100644 --- a/app/Entities/UserDTOs/certification_entity.py +++ b/app/Entities/UserDTOs/certification_entity.py @@ -1,93 +1,35 @@ -from typing import Optional,List +from typing import Optional, List, Annotated from uuid import UUID from datetime import datetime, date -from pydantic import BaseModel, field_validator +from pydantic import BaseModel, Field from Schema.SQL.Enums.enums import (CertificationType, Tools) + + class CreateCertification(BaseModel): profile_id: UUID - name: str + name: Annotated[str, Field(min_length=1, strip_whitespace=True)] type: CertificationType - issuing_organization: str + issuing_organization: Annotated[str, Field(min_length=1, strip_whitespace=True)] issue_date: date expiry_date: Optional[date] = None - credential_id: str - credential_url:str - tools:Optional[List[Tools]] + credential_id: Annotated[str, Field(min_length=1, strip_whitespace=True)] + credential_url: Annotated[str, Field(min_length=1, strip_whitespace=True)] + tools: Optional[List[Tools]] = None issuing_organization_logo: Optional[str] = None - @field_validator('name') - def name_must_not_be_empty(cls ,v): - if not v.strip(): - raise ValueError("Name cannot be empty.") - return v.strip() - - @field_validator('issuing_organization') - def issuing_organization_must_not_be_empty(cls, v): - if not v.strip(): - raise ValueError("Issuing Organization cannot be empty.") - return v.strip() - - @field_validator('issue_date') - def issue_date_must_not_be_empty(cls, v): - if v is None: - raise ValueError("Issue Date cannot be empty.") - return v - - @field_validator('credential_id') - def credential_id_must_not_be_empty(cls,v): - if not v.strip(): - raise ValueError("Credential id cannot be empty.") - return v.strip() - - @field_validator('credential_url') - def credential_url_must_not_be_empty(cls,v): - if not v.strip(): - raise ValueError("Credential url cannot be empty.") - return v.strip() - class UpdateCertification(BaseModel): profile_id: Optional[UUID] = None - name: Optional[str] = None + name: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None type: Optional[CertificationType] = None - issuing_organization: Optional[str] = None + issuing_organization: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None issue_date: Optional[date] = None expiry_date: Optional[date] = None - credential_id: Optional[str] = None - credential_url: Optional[str] = None + credential_id: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None + credential_url: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None tools: Optional[List[Tools]] = None issuing_organization_logo: Optional[str] = None - @field_validator('name') - def name_must_not_be_empty(cls ,v): - if v is not None and not v.strip(): - raise ValueError("Name cannot be empty.") - return v.strip() if v else v - - @field_validator('issuing_organization') - def issuing_organization_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError("Issuing Organization cannot be empty.") - return v.strip() if v else v - - @field_validator('issue_date') - def issue_date_must_not_be_empty(cls, v): - # For optional updates, v can be None, which is valid - # If v is provided, it should be a valid date (validated by pydantic automatically) - return v - - @field_validator('credential_id') - def credential_id_must_not_be_empty(cls,v): - if v is not None and not v.strip(): - raise ValueError("Credential id cannot be empty.") - return v.strip() if v else v - - @field_validator('credential_url') - def credential_url_must_not_be_empty(cls,v): - if v is not None and not v.strip(): - raise ValueError("Credential url cannot be empty.") - return v.strip() if v else v - class ReadCertification(BaseModel): id: UUID diff --git a/app/Entities/UserDTOs/education_entity.py b/app/Entities/UserDTOs/education_entity.py index f5ed625..6305b0a 100644 --- a/app/Entities/UserDTOs/education_entity.py +++ b/app/Entities/UserDTOs/education_entity.py @@ -1,25 +1,25 @@ from __future__ import annotations -from typing import Optional, List +from typing import Optional, List, Annotated from uuid import UUID from datetime import datetime -from pydantic import BaseModel, field_validator +from pydantic import BaseModel, Field from Schema.SQL.Enums.enums import SchoolType, WorkLocationType, Tools, Degree class CreateEducation(BaseModel): profile_id: UUID - school_name: str + school_name: Annotated[str, Field(min_length=1, strip_whitespace=True)] school_logo_url: Optional[str] = None school_type: SchoolType degree: Degree - course_field_name: str + course_field_name: Annotated[str, Field(min_length=1, strip_whitespace=True)] currently_studying: bool location: Optional[CreateLocation] = None location_type: WorkLocationType - start_date_month: int + start_date_month: Annotated[int, Field(ge=1, le=12)] start_date_year: int - end_date_month: Optional[int] = None + end_date_month: Optional[Annotated[int, Field(ge=1, le=12)]] = None end_date_year: Optional[int] = None description_general: str description_detailed: Optional[str] = None @@ -29,37 +29,19 @@ class CreateEducation(BaseModel): cgpa: Optional[float] = None tools_used: Optional[List[Tools]] = None - @field_validator("school_name") - def school_must_not_be_empty(cls, v): - if not v.strip(): - raise ValueError("school_name cannot be empty") - return v.strip() - - @field_validator("course_field_name") - def field_must_not_be_empty(cls, v): - if not v.strip(): - raise ValueError("course_field_name cannot be empty") - return v.strip() - - @field_validator("start_date_month", "end_date_month") - def validate_month(cls, v): - if v is not None and (v < 1 or v > 12): - raise ValueError("Month must be between 1 and 12") - return v - class UpdateEducation(BaseModel): - school_name: Optional[str] = None + school_name: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None school_logo_url: Optional[str] = None school_type: Optional[SchoolType] = None degree: Optional[Degree] = None - course_field_name: Optional[str] = None + course_field_name: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None currently_studying: Optional[bool] = None location: Optional[CreateLocation] = None location_type: Optional[WorkLocationType] = None - start_date_month: Optional[int] = None + start_date_month: Optional[Annotated[int, Field(ge=1, le=12)]] = None start_date_year: Optional[int] = None - end_date_month: Optional[int] = None + end_date_month: Optional[Annotated[int, Field(ge=1, le=12)]] = None end_date_year: Optional[int] = None description_general: Optional[str] = None description_detailed: Optional[str] = None @@ -69,24 +51,6 @@ class UpdateEducation(BaseModel): cgpa: Optional[float] = None tools_used: Optional[List[Tools]] = None - @field_validator("school_name") - def school_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError("school_name cannot be empty") - return v.strip() if v else v - - @field_validator("course_field_name") - def field_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError("course_field_name cannot be empty") - return v.strip() if v else v - - @field_validator("start_date_month", "end_date_month") - def validate_month(cls, v): - if v is not None and (v < 1 or v > 12): - raise ValueError("Month must be between 1 and 12") - return v - class ReadEducation(BaseModel): id: UUID profile_id: UUID diff --git a/app/Entities/UserDTOs/links_entity.py b/app/Entities/UserDTOs/links_entity.py index 8bc591e..541a1c1 100644 --- a/app/Entities/UserDTOs/links_entity.py +++ b/app/Entities/UserDTOs/links_entity.py @@ -1,57 +1,39 @@ -from typing import Optional +from typing import Optional, Annotated from uuid import UUID from datetime import datetime -from pydantic import BaseModel, field_validator +from pydantic import BaseModel, Field class CreateLinks(BaseModel): user_id: UUID portfolio_link: Optional[str] = None - github_user_name: str + github_user_name: Annotated[str, Field(min_length=1, strip_whitespace=True)] github_link: Optional[str] = None - linkedin_user_name: str + linkedin_user_name: Annotated[str, Field(min_length=1, strip_whitespace=True)] linkedin_link: Optional[str] = None - leetcode_user_name: str + leetcode_user_name: Annotated[str, Field(min_length=1, strip_whitespace=True)] leetcode_link: Optional[str] = None - orcid_id: Optional[str] = None + orcid_id: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None orcid_link: Optional[str] = None primary_email: Optional[str] = None secondary_email: Optional[str] = None school_email: Optional[str] = None work_email: Optional[str] = None - @field_validator("github_user_name", "linkedin_user_name", "leetcode_user_name") - def validate_not_empty(cls, v: str): - if not v.strip(): - raise ValueError("Field cannot be empty") - return v.strip() - - @field_validator("orcid_id") - def validate_orcid_not_empty(cls, v: Optional[str]): - if v is not None and not v.strip(): - raise ValueError("Field cannot be empty") - return v.strip() if v else v - class UpdateLinks(BaseModel): portfolio_link: Optional[str] = None - github_user_name: Optional[str] = None + github_user_name: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None github_link: Optional[str] = None - linkedin_user_name: Optional[str] = None + linkedin_user_name: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None linkedin_link: Optional[str] = None - leetcode_user_name: Optional[str] = None + leetcode_user_name: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None leetcode_link: Optional[str] = None - orcid_id: Optional[str] = None + orcid_id: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None orcid_link: Optional[str] = None primary_email: Optional[str] = None secondary_email: Optional[str] = None school_email: Optional[str] = None work_email: Optional[str] = None - @field_validator("github_user_name", "linkedin_user_name", "leetcode_user_name", "orcid_id") - def validate_not_empty_if_present(cls, v: Optional[str]): - if v is not None and not v.strip(): - raise ValueError("Field cannot be empty") - return v.strip() if v else v - class ReadLinks(BaseModel): id: UUID user_id: UUID diff --git a/app/Entities/UserDTOs/location_entity.py b/app/Entities/UserDTOs/location_entity.py index 2fa08ce..0d13611 100644 --- a/app/Entities/UserDTOs/location_entity.py +++ b/app/Entities/UserDTOs/location_entity.py @@ -1,47 +1,23 @@ -from typing import Optional +from typing import Optional, Annotated from uuid import UUID from datetime import datetime -from pydantic import BaseModel, field_validator +from pydantic import BaseModel, Field class CreateLocation(BaseModel): id: Optional[UUID] = None city: str state: Optional[str] = None - country: str + country: Annotated[str, Field(min_length=1, strip_whitespace=True)] longitude: Optional[float] = None latitude: Optional[float] = None - @field_validator('city') - def city_must_not_be_empty(cls, v): - if not v.strip(): - raise ValueError('city cannot be empty') - return v.strip() - - @field_validator('country') - def country_must_not_be_empty(cls, v): - if not v.strip(): - raise ValueError('country cannot be empty') - return v.strip() - class UpdateLocation(BaseModel): - city: Optional[str] = None + city: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None state: Optional[str] = None - country: Optional[str] = None + country: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None longitude: Optional[float] = None latitude: Optional[float] = None - @field_validator('city') - def city_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError('city cannot be empty') - return v.strip() if v else v - - @field_validator('country') - def country_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError('country cannot be empty') - return v.strip() if v else v - class ReadLocation(BaseModel): id: UUID city: str diff --git a/app/Entities/UserDTOs/profile_entity.py b/app/Entities/UserDTOs/profile_entity.py index d01e6a6..773e5a5 100644 --- a/app/Entities/UserDTOs/profile_entity.py +++ b/app/Entities/UserDTOs/profile_entity.py @@ -1,7 +1,7 @@ from typing import Optional from uuid import UUID from datetime import datetime -from pydantic import BaseModel, validator +from pydantic import BaseModel # ---------------------- # Input DTOs @@ -9,22 +9,10 @@ class CreateProfile(BaseModel): user_id: UUID - @validator('user_id') - def user_id_must_be_valid_uuid(cls, v): - if not v: - raise ValueError('user_id cannot be empty') - return v - class UpdateProfile(BaseModel): user_id: Optional[UUID] = None - @validator('user_id') - def user_id_must_be_valid_uuid(cls, v): - if v is not None and not v: - raise ValueError('user_id cannot be empty') - return v - # ---------------------- # Output DTO diff --git a/app/Entities/UserDTOs/projects_entity.py b/app/Entities/UserDTOs/projects_entity.py index 21944ff..3f2981c 100644 --- a/app/Entities/UserDTOs/projects_entity.py +++ b/app/Entities/UserDTOs/projects_entity.py @@ -1,20 +1,20 @@ -from typing import Optional, List +from typing import Optional, List, Annotated from uuid import UUID from datetime import datetime -from pydantic import BaseModel, Field, field_validator +from pydantic import BaseModel, Field from Schema.SQL.Enums.enums import Domain, Tools class CreateProject(BaseModel): profile_id: UUID - name: str = Field(..., min_length=1) + name: Annotated[str, Field(min_length=1, strip_whitespace=True)] organization: Optional[str] = None - owner: str = Field(..., min_length=1) + owner: Annotated[str, Field(min_length=1, strip_whitespace=True)] private: bool - github_stars: int = 0 + github_stars: Annotated[int, Field(ge=0)] = 0 github_about: Optional[str] = None - github_open_issues: int = 0 - github_forks: int = 0 - description: str = Field(..., min_length=1) + github_open_issues: Annotated[int, Field(ge=0)] = 0 + github_forks: Annotated[int, Field(ge=0)] = 0 + description: Annotated[str, Field(min_length=1, strip_whitespace=True)] domain: Domain topics: Optional[List[str]] = None tools: List[Tools] @@ -26,37 +26,25 @@ class CreateProject(BaseModel): docs_page_link: Optional[str] = None own_domain_name: bool domain_name: Optional[str] = None - total_lines_contributed: Optional[int] = 0 + total_lines_contributed: Optional[Annotated[int, Field(ge=0)]] = 0 improper_uploads: Optional[bool] = False complexity_rating: Optional[float] = None testing_framework_present: bool testing_framework: Optional[str] = None project_organization_logo: Optional[str] = None - @field_validator("name", "owner", "description") - def must_not_be_empty(cls, v, info): - if not v.strip(): - raise ValueError(f"{info.field_name} cannot be empty") - return v.strip() - - @field_validator("github_stars", "github_open_issues", "github_forks", "total_lines_contributed") - def must_be_non_negative(cls, v, info): - if v is not None and v < 0: - raise ValueError(f"{info.field_name} cannot be negative") - return v - class UpdateProject(BaseModel): profile_id: Optional[UUID] = None - name: Optional[str] = None + name: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None organization: Optional[str] = None - owner: Optional[str] = None + owner: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None private: Optional[bool] = None - github_stars: Optional[int] = None + github_stars: Optional[Annotated[int, Field(ge=0)]] = None github_about: Optional[str] = None - github_open_issues: Optional[int] = None - github_forks: Optional[int] = None - description: Optional[str] = None + github_open_issues: Optional[Annotated[int, Field(ge=0)]] = None + github_forks: Optional[Annotated[int, Field(ge=0)]] = None + description: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None domain: Optional[Domain] = None topics: Optional[List[str]] = None tools: Optional[List[Tools]] = None @@ -75,18 +63,6 @@ class UpdateProject(BaseModel): testing_framework: Optional[str] = None project_organization_logo: Optional[str] = None - @field_validator("name", "owner", "description") - def must_not_be_empty_if_provided(cls, v, info): - if v is not None and not v.strip(): - raise ValueError(f"{info.field_name} cannot be empty") - return v.strip() if v else v - - @field_validator("github_stars", "github_open_issues", "github_forks") - def must_be_non_negative(cls, v, info): - if v is not None and v < 0: - raise ValueError(f"{info.field_name} cannot be negative") - return v - class ReadProject(BaseModel): id: UUID profile_id: UUID diff --git a/app/Entities/UserDTOs/publication_entity.py b/app/Entities/UserDTOs/publication_entity.py index 8a0c119..0822487 100644 --- a/app/Entities/UserDTOs/publication_entity.py +++ b/app/Entities/UserDTOs/publication_entity.py @@ -49,38 +49,15 @@ def description_must_not_be_empty(cls, v): class UpdatePublication(BaseModel): profile_id: Optional[UUID] = None - title: Optional[str] = None - publisher: Optional[str] = None - authors: Optional[List[str]] = None + title: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None + publisher: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None + authors: Optional[List[Annotated[str, Field(min_length=1, strip_whitespace=True)]]] = None publication_date: Optional[date] = None - publication_url: Optional[str] = None - description: Optional[str] = None + publication_url: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None + description: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None tools: Optional[List[Tools]] = None publisher_logo: Optional[str] = None - @field_validator("title") - def title_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError("title cannot be empty") - return v.strip() if v else v - - @field_validator("publisher") - def publisher_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError("publisher cannot be empty") - return v.strip() if v else v - - @field_validator("publication_url") - def url_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError("publication_url cannot be empty") - return v.strip() if v else v - - @field_validator("description") - def description_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError("description cannot be empty") - return v.strip() if v else v class ReadPublication(BaseModel): id: UUID diff --git a/app/Entities/UserDTOs/user_entity.py b/app/Entities/UserDTOs/user_entity.py index 48222d6..b8f78e5 100644 --- a/app/Entities/UserDTOs/user_entity.py +++ b/app/Entities/UserDTOs/user_entity.py @@ -1,7 +1,7 @@ -from typing import Optional, List +from typing import Optional, List, Annotated from uuid import UUID from datetime import datetime -from pydantic import BaseModel, field_validator +from pydantic import BaseModel, Field from Schema.SQL.Enums.enums import Rank, Domain, Tools @@ -9,10 +9,10 @@ # Input DTOs # ---------------------- class CreateUser(BaseModel): - github_user_name: str - first_name: Optional[str] = None + github_user_name: Annotated[str, Field(min_length=1, strip_whitespace=True)] + first_name: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None middle_name: Optional[str] = None - last_name: Optional[str] = None + last_name: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None rank: Rank = Rank.UNRANKED streak: Optional[int] = None primary_specialization: Domain @@ -28,30 +28,12 @@ class CreateUser(BaseModel): dream_position: Optional[str] = None tools_to_learn: Optional[List[Tools]] = [] - @field_validator('github_user_name') - def github_user_name_must_not_be_empty(cls, v): - if not v.strip(): - raise ValueError('github_user_name cannot be empty') - return v.strip() - - @field_validator('first_name') - def first_name_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError('first_name cannot be empty string') - return v.strip() if v else v - - @field_validator('last_name') - def last_name_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError('last_name cannot be empty string') - return v.strip() if v else v - class UpdateUser(BaseModel): - github_user_name: Optional[str] = None - first_name: Optional[str] = None + github_user_name: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None + first_name: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None middle_name: Optional[str] = None - last_name: Optional[str] = None + last_name: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None rank: Optional[Rank] = None streak: Optional[int] = None primary_specialization: Optional[Domain] = None @@ -67,24 +49,6 @@ class UpdateUser(BaseModel): dream_position: Optional[str] = None tools_to_learn: Optional[List[Tools]] = None - @field_validator('github_user_name') - def github_user_name_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError('github_user_name cannot be empty') - return v.strip() if v else v - - @field_validator('first_name') - def first_name_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError('first_name cannot be empty string') - return v.strip() if v else v - - @field_validator('last_name') - def last_name_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError('last_name cannot be empty string') - return v.strip() if v else v - # ---------------------- # Output DTO @@ -120,12 +84,12 @@ class Config: # Onboarding DTOs # ---------------------- class OnboardUser(BaseModel): - github_user_name: str - linkedin_user_name: str - leetcode_user_name: str - first_name: Optional[str] = None + github_user_name: Annotated[str, Field(min_length=1, strip_whitespace=True)] + linkedin_user_name: Annotated[str, Field(min_length=1, strip_whitespace=True)] + leetcode_user_name: Annotated[str, Field(min_length=1, strip_whitespace=True)] + first_name: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None middle_name: Optional[str] = None - last_name: Optional[str] = None + last_name: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None rank: Rank = Rank.UNRANKED streak: int = 0 primary_specialization: Domain @@ -135,33 +99,9 @@ class OnboardUser(BaseModel): dream_company: Optional[str] = None dream_company_logo: Optional[str] = None dream_position: Optional[str] = None - primary_email: str + primary_email: Annotated[str, Field(min_length=1, strip_whitespace=True)] tools_to_learn: Optional[List[Tools]] = [] - @field_validator('github_user_name', 'linkedin_user_name', 'leetcode_user_name') - def usernames_must_not_be_empty(cls, v): - if not v.strip(): - raise ValueError('username cannot be empty') - return v.strip() - - @field_validator('first_name') - def first_name_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError('first_name cannot be empty string') - return v.strip() if v else v - - @field_validator('last_name') - def last_name_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError('last_name cannot be empty string') - return v.strip() if v else v - - @field_validator('primary_email') - def primary_email_must_not_be_empty(cls, v): - if not v.strip(): - raise ValueError('primary_email cannot be empty') - return v.strip() - class OnboardCheckResponse(BaseModel): onboarded: bool diff --git a/app/Entities/UserDTOs/volunteering_entity.py b/app/Entities/UserDTOs/volunteering_entity.py index 4fd9e74..617697e 100644 --- a/app/Entities/UserDTOs/volunteering_entity.py +++ b/app/Entities/UserDTOs/volunteering_entity.py @@ -1,7 +1,7 @@ -from typing import Optional, List +from typing import Optional, List, Annotated from uuid import UUID from datetime import date, datetime -from pydantic import BaseModel, ValidationInfo, field_validator +from pydantic import BaseModel, ValidationInfo, field_validator, Field from Schema.SQL.Enums.enums import ( Cause, Tools, @@ -9,8 +9,8 @@ class CreateVolunteering(BaseModel): profile_id: UUID - organization: str - role: str + organization: Annotated[str, Field(min_length=1, strip_whitespace=True)] + role: Annotated[str, Field(min_length=1, strip_whitespace=True)] cause: Cause start_date: date end_date: Optional[date] = None @@ -19,18 +19,6 @@ class CreateVolunteering(BaseModel): tools: Optional[List[Tools]] = None organization_logo: Optional[str] = None - @field_validator("organization") - def organization_must_not_be_empty(cls, v): - if not v.strip(): - raise ValueError("organization cannot be empty") - return v.strip() - - @field_validator("role") - def role_must_not_be_empty(cls, v): - if not v.strip(): - raise ValueError("role cannot be empty") - return v.strip() - @field_validator("end_date") def validate_end_date(cls, v, info: ValidationInfo): start_date = info.data.get("start_date") @@ -41,8 +29,8 @@ def validate_end_date(cls, v, info: ValidationInfo): class UpdateVolunteering(BaseModel): profile_id: Optional[UUID] = None - organization: Optional[str] = None - role: Optional[str] = None + organization: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None + role: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None cause: Optional[Cause] = None start_date: Optional[date] = None end_date: Optional[date] = None @@ -51,18 +39,6 @@ class UpdateVolunteering(BaseModel): tools: Optional[List[Tools]] = None organization_logo: Optional[str] = None - @field_validator("organization") - def organization_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError("organization cannot be empty") - return v.strip() if v else v - - @field_validator("role") - def role_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError("role cannot be empty") - return v.strip() if v else v - @field_validator("end_date") def validate_end_date(cls, v, info: ValidationInfo): start_date = info.data.get("start_date") diff --git a/app/Entities/UserDTOs/workexperience_entity.py b/app/Entities/UserDTOs/workexperience_entity.py index cfb087d..9c361f0 100644 --- a/app/Entities/UserDTOs/workexperience_entity.py +++ b/app/Entities/UserDTOs/workexperience_entity.py @@ -1,9 +1,9 @@ from __future__ import annotations -from typing import Optional, List +from typing import Optional, List, Annotated from uuid import UUID from datetime import date, datetime -from pydantic import BaseModel, field_validator +from pydantic import BaseModel, field_validator, Field from Schema.SQL.Enums.enums import EmploymentType, WorkLocationType, Domain, Tools from Entities.UserDTOs.location_entity import CreateLocation, ReadLocation @@ -13,19 +13,19 @@ # ---------------------- class CreateWorkExperience(BaseModel): profile_id: UUID - title: str + title: Annotated[str, Field(min_length=1, strip_whitespace=True)] employment_type: EmploymentType domain: Optional[List[Domain]] = None - company_name: str + company_name: Annotated[str, Field(min_length=1, strip_whitespace=True)] company_logo: Optional[str] = None currently_working: bool location: Optional[CreateLocation] = None location_type: WorkLocationType - start_date_month: int + start_date_month: Annotated[int, Field(ge=1, le=12)] start_date_year: int - end_date_month: Optional[int] = None + end_date_month: Optional[Annotated[int, Field(ge=1, le=12)]] = None end_date_year: Optional[int] = None - description_general: str + description_general: Annotated[str, Field(min_length=1, strip_whitespace=True)] description_detailed: Optional[str] = None description_less: Optional[str] = None work_done: Optional[str] = None @@ -34,36 +34,6 @@ class CreateWorkExperience(BaseModel): work_done_multiplier: Optional[float] = None tools_used: Optional[List[Tools]] = None - @field_validator('title') - def title_must_not_be_empty(cls, v): - if not v.strip(): - raise ValueError('title cannot be empty') - return v.strip() - - @field_validator('company_name') - def company_name_must_not_be_empty(cls, v): - if not v.strip(): - raise ValueError('company_name cannot be empty') - return v.strip() - - @field_validator('description_general') - def description_general_must_not_be_empty(cls, v): - if not v.strip(): - raise ValueError('description_general cannot be empty') - return v.strip() - - @field_validator('start_date_month') - def validate_start_month(cls, v): - if v < 1 or v > 12: - raise ValueError('start_date_month must be between 1 and 12') - return v - - @field_validator('end_date_month') - def validate_end_month(cls, v): - if v is not None and (v < 1 or v > 12): - raise ValueError('end_date_month must be between 1 and 12') - return v - @field_validator('end_date_year') def validate_end_date(cls, v, values): if v is not None: @@ -79,19 +49,19 @@ def validate_end_date(cls, v, values): class UpdateWorkExperience(BaseModel): profile_id: Optional[UUID] = None - title: Optional[str] = None + title: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None employment_type: Optional[EmploymentType] = None domain: Optional[List[Domain]] = None - company_name: Optional[str] = None + company_name: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None company_logo: Optional[str] = None currently_working: Optional[bool] = None location: Optional[CreateLocation] = None location_type: Optional[WorkLocationType] = None - start_date_month: Optional[int] = None + start_date_month: Optional[Annotated[int, Field(ge=1, le=12)]] = None start_date_year: Optional[int] = None - end_date_month: Optional[int] = None + end_date_month: Optional[Annotated[int, Field(ge=1, le=12)]] = None end_date_year: Optional[int] = None - description_general: Optional[str] = None + description_general: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None description_detailed: Optional[str] = None description_less: Optional[str] = None work_done: Optional[str] = None @@ -100,36 +70,6 @@ class UpdateWorkExperience(BaseModel): work_done_multiplier: Optional[float] = None tools_used: Optional[List[Tools]] = None - @field_validator('title') - def title_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError('title cannot be empty') - return v.strip() if v else v - - @field_validator('company_name') - def company_name_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError('company_name cannot be empty') - return v.strip() if v else v - - @field_validator('description_general') - def description_general_must_not_be_empty(cls, v): - if v is not None and not v.strip(): - raise ValueError('description_general cannot be empty') - return v.strip() if v else v - - @field_validator('start_date_month') - def validate_start_month(cls, v): - if v is not None and (v < 1 or v > 12): - raise ValueError('start_date_month must be between 1 and 12') - return v - - @field_validator('end_date_month') - def validate_end_month(cls, v): - if v is not None and (v < 1 or v > 12): - raise ValueError('end_date_month must be between 1 and 12') - return v - @field_validator('end_date_year') def validate_end_date(cls, v, values): if v is not None: diff --git a/app/Entities/leetcode_entity.py b/app/Entities/leetcode_entity.py index 579bb50..5aedf6c 100644 --- a/app/Entities/leetcode_entity.py +++ b/app/Entities/leetcode_entity.py @@ -1,7 +1,7 @@ -from typing import List, Optional +from typing import List, Optional, Annotated from uuid import UUID from datetime import datetime -from pydantic import BaseModel, field_validator +from pydantic import BaseModel, Field from Schema.SQL.Models.models import LeetcodeTagCategory from Schema.SQL.Enums.enums import Tools @@ -12,7 +12,7 @@ # ------------------------------------------------------------------------- class CreateLeetcode(BaseModel): profile_id: UUID - lc_username: Optional[str] = None + lc_username: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None real_name: Optional[str] = None about_me: Optional[str] = None school: Optional[str] = None @@ -37,19 +37,9 @@ class CreateLeetcode(BaseModel): top_percentage: Optional[float] = None competition_badge: Optional[str] = None - @field_validator('profile_id') - def profile_id_must_be_present(cls, v): - if not v: - raise ValueError('profile_id is required') - return v - - @field_validator('lc_username') - def lc_username_trim(cls, v): - return v.strip() if v else v - class UpdateLeetcode(BaseModel): - lc_username: Optional[str] = None + lc_username: Optional[Annotated[str, Field(min_length=1, strip_whitespace=True)]] = None real_name: Optional[str] = None about_me: Optional[str] = None school: Optional[str] = None @@ -74,12 +64,6 @@ class UpdateLeetcode(BaseModel): top_percentage: Optional[float] = None competition_badge: Optional[str] = None - @field_validator('lc_username') - def lc_username_trim(cls, v): - if v is not None and not v.strip(): - raise ValueError('lc_username cannot be empty') - return v.strip() if v else v - class ReadLeetcode(BaseModel): id: UUID @@ -124,12 +108,6 @@ class CreateLeetcodeBadge(BaseModel): icon: Optional[str] = None hover_text: Optional[str] = None - @field_validator('leetcode_id') - def leetcode_id_must_be_present(cls, v): - if not v: - raise ValueError('leetcode_id is required') - return v - class UpdateLeetcodeBadge(BaseModel): name: Optional[str] = None @@ -159,12 +137,6 @@ class CreateLeetcodeTag(BaseModel): tag_name: Optional[str] = None problems_solved: Optional[int] = None - @field_validator('leetcode_id') - def leetcode_id_must_be_present(cls, v): - if not v: - raise ValueError('leetcode_id is required') - return v - class UpdateLeetcodeTag(BaseModel): tag_category: Optional[LeetcodeTagCategory] = None diff --git a/app/Utils/errors.py b/app/Utils/errors.py index 6afb6ba..c5323c0 100644 --- a/app/Utils/errors.py +++ b/app/Utils/errors.py @@ -9,5 +9,5 @@ def raise_api_error( detail: str, status: int = HTTP_500_INTERNAL_SERVER_ERROR ): - error = APIError(code=code, error=error, detail=detail, status=status) - raise HTTPException(status_code=status, detail=error.dict()) + api_error = APIError(code=code, error=error, detail=detail, status=status) + raise HTTPException(status_code=status, detail=api_error.dict()) diff --git a/requirements.txt b/requirements.txt index ada4331..e69de29 100644 Binary files a/requirements.txt and b/requirements.txt differ