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:
Backend IM Bot 2025-04-13 20:10:08 +00:00
parent f14c0308dc
commit 4832f4a698
5 changed files with 159 additions and 69 deletions

View 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')

View File

@ -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)

View File

@ -1,110 +1,99 @@
from typing import Dict, Any, List, Optional
import uuid
from datetime import datetime
from dataclasses import dataclass
from uuid import uuid4
# In-memory store for fruits
_fruits_store: List[Dict[str, Any]] = []
# In-memory storage for countries
_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:
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:
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
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:
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:
Dict[str, Any]: The created fruit data with generated ID and timestamp.
Raises:
ValueError: If the fruit data is invalid.
Optional[Dict[str, Any]]: The created country data if successful, None if validation fails.
"""
if not validate_fruit_data(fruit_data):
raise ValueError("Invalid fruit data. Name, color, and shape are required.")
new_fruit = {
"id": str(uuid.uuid4()),
"name": fruit_data["name"].strip(),
"color": fruit_data["color"].strip(),
"shape": fruit_data["shape"].strip(),
"created_at": datetime.utcnow().isoformat()
if not validate_country_data(name, landmass_size):
return None
country_data = {
"id": str(uuid4()),
"name": name.strip(),
"landmass_size": float(landmass_size)
}
_fruits_store.append(new_fruit)
return new_fruit
_countries_store.append(country_data)
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:
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:
name (str): The name of the fruit to find.
name (str): The name of the country to find.
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()
for fruit in _fruits_store:
if fruit["name"].lower() == name:
return fruit
name = name.lower()
for country in _countries_store:
if country["name"].lower() == name:
return country
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:
color (str): The color to filter by.
country (Dict[str, Any]): The raw country data.
Returns:
List[Dict[str, Any]]: List of fruits matching the color.
Dict[str, Any]: Formatted country data.
"""
color = color.strip().lower()
return [fruit for fruit in _fruits_store if fruit["color"].lower() == color]
def get_fruits_by_shape(shape: str) -> List[Dict[str, Any]]:
"""
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]
return {
"id": country["id"],
"name": country["name"],
"landmass_size": country["landmass_size"],
"landmass_size_formatted": f"{country['landmass_size']:,.2f} km²"
}

14
models/country.py Normal file
View 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
View 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"
}
}