111 lines
3.1 KiB
Python
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
|