Files
Nitzan Pomerantz e4aa6487ff Ruff fixes
2025-10-30 22:24:40 +02:00

111 lines
3.1 KiB
Python

"""
Input validation functions for Govmap API client.
This module provides pure validation functions with no dependencies on other modules.
All functions are stateless and raise ValueError on validation failure.
"""
import logging
from typing import Optional, Tuple
logger = logging.getLogger(__name__)
def validate_address(address: str) -> str:
"""
Validate and sanitize address input.
Args:
address: Address string to validate
Returns:
Sanitized address string
Raises:
ValueError: If address is invalid
"""
if not address or not isinstance(address, str):
raise ValueError("Address must be a non-empty string")
address = address.strip()
if not address:
raise ValueError("Address cannot be empty or whitespace only")
if len(address) > 500:
raise ValueError("Address is too long (max 500 characters)")
return address
def validate_coordinates(point: Tuple[float, float]) -> Tuple[float, float]:
"""
Validate coordinate input.
Args:
point: Tuple of (longitude, latitude) in ITM projection
Returns:
Validated coordinate tuple
Raises:
ValueError: If coordinates are invalid
"""
if not isinstance(point, (tuple, list)) or len(point) != 2:
raise ValueError("Point must be a tuple of (longitude, latitude)")
try:
lon, lat = float(point[0]), float(point[1])
except (TypeError, ValueError):
raise ValueError("Coordinates must be numeric values")
# Basic validation for Israeli coordinates (ITM projection)
# ITM bounds for Israel: X (longitude) ~150,000-300,000, Y (latitude) ~3,500,000-4,000,000
if not (150000 <= lon <= 300000): # ITM longitude bounds for Israel
logger.warning(
f"Longitude {lon} appears to be outside Israeli ITM bounds (150,000-300,000)"
)
if not (3500000 <= lat <= 4000000): # ITM latitude bounds for Israel
logger.warning(
f"Latitude {lat} appears to be outside Israeli ITM bounds (3,500,000-4,000,000)"
)
return (lon, lat)
def validate_positive_int(value: int, name: str, max_value: Optional[int] = None) -> int:
"""
Validate positive integer input.
Args:
value: Value to validate
name: Name of the parameter (for error messages)
max_value: Optional maximum allowed value
Returns:
Validated integer
Raises:
ValueError: If value is invalid
"""
if not isinstance(value, int):
raise ValueError(f"{name} must be an integer")
if value <= 0:
raise ValueError(f"{name} must be positive")
if max_value and value > max_value:
raise ValueError(f"{name} must be <= {max_value}")
return value
def validate_deal_type(deal_type: int) -> int:
"""
Validate deal type parameter.
Args:
deal_type: Deal type (1=first hand/new, 2=second hand/used)
Returns:
Validated deal type
Raises:
ValueError: If deal type is invalid
"""
if deal_type not in (1, 2):
raise ValueError("deal_type must be 1 (first hand) or 2 (second hand)")
return deal_type