feat: Implement initial schema and add various API, service, and management command enhancements across the application.

This commit is contained in:
pacnpal
2026-01-01 15:13:01 -05:00
parent c95f99ca10
commit b243b17af7
413 changed files with 11164 additions and 17433 deletions

View File

@@ -160,19 +160,13 @@ def validate_email(value: str) -> bool:
def validate_type(value: Any, expected_type: type) -> bool:
"""Validate that a value is of the expected type."""
if expected_type == bool:
if expected_type is bool:
# Special handling for boolean strings
return isinstance(value, bool) or str(value).lower() in (
"true", "false", "1", "0", "yes", "no"
)
return isinstance(value, bool) or str(value).lower() in ("true", "false", "1", "0", "yes", "no")
return isinstance(value, expected_type)
def validate_range(
value: Any,
min_value: Any | None = None,
max_value: Any | None = None
) -> bool:
def validate_range(value: Any, min_value: Any | None = None, max_value: Any | None = None) -> bool:
"""Validate that a value is within a specified range."""
if min_value is not None and value < min_value:
return False
@@ -215,11 +209,11 @@ def validate_variable(name: str, rules: dict) -> list[str]:
var_type = rules.get("type", str)
default = rules.get("default")
if var_type == bool:
if var_type is bool:
value = config(name, default=default, cast=bool)
elif var_type == int:
elif var_type is int:
value = config(name, default=default, cast=int)
elif var_type == float:
elif var_type is float:
value = config(name, default=default, cast=float)
else:
value = config(name, default=default)
@@ -233,29 +227,21 @@ def validate_variable(name: str, rules: dict) -> list[str]:
# Type validation
if not validate_type(value, rules.get("type", str)):
errors.append(
f"{name}: Expected type {rules['type'].__name__}, "
f"got {type(value).__name__}"
)
errors.append(f"{name}: Expected type {rules['type'].__name__}, " f"got {type(value).__name__}")
# Length validation (for strings)
if isinstance(value, str):
min_length = rules.get("min_length", 0)
max_length = rules.get("max_length")
if not validate_length(value, min_length, max_length):
errors.append(
f"{name}: Length must be between {min_length} and "
f"{max_length or 'unlimited'}"
)
errors.append(f"{name}: Length must be between {min_length} and " f"{max_length or 'unlimited'}")
# Range validation (for numbers)
if isinstance(value, (int, float)):
if isinstance(value, int | float):
min_value = rules.get("min_value")
max_value = rules.get("max_value")
if not validate_range(value, min_value, max_value):
errors.append(
f"{name}: Value must be between {min_value} and {max_value}"
)
errors.append(f"{name}: Value must be between {min_value} and {max_value}")
# Custom validator
validator_name = rules.get("validator")
@@ -285,13 +271,9 @@ def validate_cross_rules() -> list[str]:
try:
value = config(var_name, default=None)
if value is not None and not check_fn(value):
errors.append(
f"{rule['name']}: {var_name} {message}"
)
errors.append(f"{rule['name']}: {var_name} {message}")
except Exception:
errors.append(
f"{rule['name']}: Could not validate {var_name}"
)
errors.append(f"{rule['name']}: Could not validate {var_name}")
except Exception as e:
errors.append(f"Cross-validation error for {rule['name']}: {e}")
@@ -343,9 +325,7 @@ def validate_all_settings(raise_on_error: bool = False) -> dict:
logger.error(f"Configuration error: {error}")
if raise_on_error:
raise ValueError(
f"Configuration validation failed: {result['errors']}"
)
raise ValueError(f"Configuration validation failed: {result['errors']}")
# Log warnings
for warning in result["warnings"]:
@@ -372,9 +352,7 @@ def run_startup_validation() -> None:
for error in result["errors"]:
warnings.warn(f"Configuration error: {error}", stacklevel=2)
else:
raise ValueError(
"Configuration validation failed. Check logs for details."
)
raise ValueError("Configuration validation failed. Check logs for details.")
# =============================================================================