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