feat: Generated endpoint endpoints/create-country.post.py via AI for Country and updated requirements.txt with auto lint fixes
This commit is contained in:
parent
f14c0308dc
commit
4832f4a698
28
alembic/versions/20250413_200932_33e40902_update_country.py
Normal file
28
alembic/versions/20250413_200932_33e40902_update_country.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
"""create countries table
|
||||||
|
Revision ID: 0002
|
||||||
|
Revises: 0001
|
||||||
|
Create Date: 2024-02-13 10:30:00.000000
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '0002'
|
||||||
|
down_revision = '0001'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.create_table(
|
||||||
|
'countries',
|
||||||
|
sa.Column('id', sa.String(36), primary_key=True),
|
||||||
|
sa.Column('name', sa.String(), nullable=False),
|
||||||
|
sa.Column('landmass_size', sa.Float(), nullable=False),
|
||||||
|
sa.Column('created_at', sa.DateTime(), server_default=sa.func.now()),
|
||||||
|
sa.Column('updated_at', sa.DateTime(), server_default=sa.func.now())
|
||||||
|
)
|
||||||
|
op.create_index(op.f('ix_countries_name'), 'countries', ['name'], unique=True)
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.drop_index(op.f('ix_countries_name'), table_name='countries')
|
||||||
|
op.drop_table('countries')
|
@ -0,0 +1,27 @@
|
|||||||
|
from fastapi import APIRouter, HTTPException, status
|
||||||
|
from typing import Dict, Any
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from database.country import create_country
|
||||||
|
from utils.formatters import format_country_response
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
class CountryCreate(BaseModel):
|
||||||
|
name: str
|
||||||
|
landmass_size: float
|
||||||
|
|
||||||
|
@router.post("/create-country", status_code=status.HTTP_201_CREATED, response_model=Dict[str, Any])
|
||||||
|
async def create_new_country(country_data: CountryCreate):
|
||||||
|
"""Create a new country"""
|
||||||
|
created_country = create_country(
|
||||||
|
name=country_data.name,
|
||||||
|
landmass_size=country_data.landmass_size
|
||||||
|
)
|
||||||
|
|
||||||
|
if not created_country:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail="Invalid country data or country already exists"
|
||||||
|
)
|
||||||
|
|
||||||
|
return format_country_response(created_country)
|
@ -1,110 +1,99 @@
|
|||||||
from typing import Dict, Any, List, Optional
|
from typing import Dict, Any, List, Optional
|
||||||
import uuid
|
from dataclasses import dataclass
|
||||||
from datetime import datetime
|
from uuid import uuid4
|
||||||
|
|
||||||
# In-memory store for fruits
|
# In-memory storage for countries
|
||||||
_fruits_store: List[Dict[str, Any]] = []
|
_countries_store: List[Dict[str, Any]] = []
|
||||||
|
|
||||||
def validate_fruit_data(fruit_data: Dict[str, Any]) -> bool:
|
@dataclass
|
||||||
|
class CountryData:
|
||||||
|
name: str
|
||||||
|
landmass_size: float
|
||||||
|
|
||||||
|
def validate_country_data(name: str, landmass_size: float) -> bool:
|
||||||
"""
|
"""
|
||||||
Validates fruit data before creation.
|
Validates the country data before creation.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
fruit_data (Dict[str, Any]): The fruit data to validate.
|
name (str): The name of the country.
|
||||||
|
landmass_size (float): The landmass size in square kilometers.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: True if data is valid, False otherwise.
|
bool: True if data is valid, False otherwise.
|
||||||
"""
|
"""
|
||||||
required_fields = ['name', 'color', 'shape']
|
if not name or not isinstance(name, str) or len(name.strip()) == 0:
|
||||||
|
return False
|
||||||
|
if not isinstance(landmass_size, (int, float)) or landmass_size <= 0:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Check if country name already exists
|
||||||
|
for country in _countries_store:
|
||||||
|
if country["name"].lower() == name.lower():
|
||||||
|
return False
|
||||||
|
|
||||||
if not all(field in fruit_data for field in required_fields):
|
|
||||||
return False
|
|
||||||
|
|
||||||
if not isinstance(fruit_data['name'], str) or len(fruit_data['name'].strip()) == 0:
|
|
||||||
return False
|
|
||||||
|
|
||||||
if not isinstance(fruit_data['color'], str) or len(fruit_data['color'].strip()) == 0:
|
|
||||||
return False
|
|
||||||
|
|
||||||
if not isinstance(fruit_data['shape'], str) or len(fruit_data['shape'].strip()) == 0:
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def create_fruit(fruit_data: Dict[str, Any]) -> Dict[str, Any]:
|
def create_country(name: str, landmass_size: float) -> Optional[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
Creates a new fruit entry in the in-memory store.
|
Creates a new country entry in the in-memory store.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
fruit_data (Dict[str, Any]): The fruit data containing name, color, and shape.
|
name (str): The name of the country.
|
||||||
|
landmass_size (float): The landmass size in square kilometers.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dict[str, Any]: The created fruit data with generated ID and timestamp.
|
Optional[Dict[str, Any]]: The created country data if successful, None if validation fails.
|
||||||
|
|
||||||
Raises:
|
|
||||||
ValueError: If the fruit data is invalid.
|
|
||||||
"""
|
"""
|
||||||
if not validate_fruit_data(fruit_data):
|
if not validate_country_data(name, landmass_size):
|
||||||
raise ValueError("Invalid fruit data. Name, color, and shape are required.")
|
return None
|
||||||
|
|
||||||
new_fruit = {
|
country_data = {
|
||||||
"id": str(uuid.uuid4()),
|
"id": str(uuid4()),
|
||||||
"name": fruit_data["name"].strip(),
|
"name": name.strip(),
|
||||||
"color": fruit_data["color"].strip(),
|
"landmass_size": float(landmass_size)
|
||||||
"shape": fruit_data["shape"].strip(),
|
|
||||||
"created_at": datetime.utcnow().isoformat()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_fruits_store.append(new_fruit)
|
_countries_store.append(country_data)
|
||||||
return new_fruit
|
return country_data
|
||||||
|
|
||||||
def get_all_fruits() -> List[Dict[str, Any]]:
|
def get_all_countries() -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
Retrieves all fruits from the in-memory store.
|
Retrieves all countries from the in-memory store.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List[Dict[str, Any]]: List of all stored fruits.
|
List[Dict[str, Any]]: A list of all stored countries.
|
||||||
"""
|
"""
|
||||||
return _fruits_store
|
return _countries_store
|
||||||
|
|
||||||
def get_fruit_by_name(name: str) -> Optional[Dict[str, Any]]:
|
def get_country_by_name(name: str) -> Optional[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
Retrieves a fruit by its name.
|
Retrieves a country by its name.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
name (str): The name of the fruit to find.
|
name (str): The name of the country to find.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Optional[Dict[str, Any]]: The fruit if found, None otherwise.
|
Optional[Dict[str, Any]]: The country data if found, None otherwise.
|
||||||
"""
|
"""
|
||||||
name = name.strip().lower()
|
name = name.lower()
|
||||||
for fruit in _fruits_store:
|
for country in _countries_store:
|
||||||
if fruit["name"].lower() == name:
|
if country["name"].lower() == name:
|
||||||
return fruit
|
return country
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_fruits_by_color(color: str) -> List[Dict[str, Any]]:
|
def format_country_response(country: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Retrieves all fruits of a specific color.
|
Formats the country data for API response.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
color (str): The color to filter by.
|
country (Dict[str, Any]): The raw country data.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List[Dict[str, Any]]: List of fruits matching the color.
|
Dict[str, Any]: Formatted country data.
|
||||||
"""
|
"""
|
||||||
color = color.strip().lower()
|
return {
|
||||||
return [fruit for fruit in _fruits_store if fruit["color"].lower() == color]
|
"id": country["id"],
|
||||||
|
"name": country["name"],
|
||||||
def get_fruits_by_shape(shape: str) -> List[Dict[str, Any]]:
|
"landmass_size": country["landmass_size"],
|
||||||
"""
|
"landmass_size_formatted": f"{country['landmass_size']:,.2f} km²"
|
||||||
Retrieves all fruits of a specific shape.
|
}
|
||||||
|
|
||||||
Args:
|
|
||||||
shape (str): The shape to filter by.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
List[Dict[str, Any]]: List of fruits matching the shape.
|
|
||||||
"""
|
|
||||||
shape = shape.strip().lower()
|
|
||||||
return [fruit for fruit in _fruits_store if fruit["shape"].lower() == shape]
|
|
14
models/country.py
Normal file
14
models/country.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from sqlalchemy import Column, String, Float, DateTime
|
||||||
|
from sqlalchemy.dialects.postgresql import UUID
|
||||||
|
from sqlalchemy.sql import func
|
||||||
|
from core.database import Base
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
class Country(Base):
|
||||||
|
__tablename__ = "countries"
|
||||||
|
|
||||||
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
||||||
|
name = Column(String, unique=True, nullable=False, index=True)
|
||||||
|
landmass_size = Column(Float, nullable=False)
|
||||||
|
created_at = Column(DateTime, default=func.now())
|
||||||
|
updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
|
32
schemas/country.py
Normal file
32
schemas/country.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
from pydantic import BaseModel, Field
|
||||||
|
from typing import Optional
|
||||||
|
from datetime import datetime
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
|
class CountryBase(BaseModel):
|
||||||
|
name: str = Field(..., description="Country name")
|
||||||
|
landmass_size: float = Field(..., gt=0, description="Size of country's landmass")
|
||||||
|
|
||||||
|
class CountryCreate(CountryBase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class CountryUpdate(BaseModel):
|
||||||
|
name: Optional[str] = Field(None, description="Country name")
|
||||||
|
landmass_size: Optional[float] = Field(None, gt=0, description="Size of country's landmass")
|
||||||
|
|
||||||
|
class CountrySchema(CountryBase):
|
||||||
|
id: UUID
|
||||||
|
created_at: datetime
|
||||||
|
updated_at: datetime
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
||||||
|
schema_extra = {
|
||||||
|
"example": {
|
||||||
|
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
||||||
|
"name": "United States",
|
||||||
|
"landmass_size": 9833517.0,
|
||||||
|
"created_at": "2023-01-01T12:00:00",
|
||||||
|
"updated_at": "2023-01-01T12:00:00"
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user