2026-02-15 17:21:55 +00:00
|
|
|
"""Configuration management for Video Summary application."""
|
|
|
|
|
|
2022-10-11 19:35:37 +00:00
|
|
|
import json
|
|
|
|
|
import os
|
2026-02-15 17:16:45 +00:00
|
|
|
from typing import Any, Optional
|
|
|
|
|
|
2026-02-15 17:21:55 +00:00
|
|
|
try:
|
|
|
|
|
import yaml
|
|
|
|
|
|
|
|
|
|
YAML_AVAILABLE = True
|
|
|
|
|
except ImportError:
|
|
|
|
|
YAML_AVAILABLE = False
|
|
|
|
|
|
2026-02-15 17:16:45 +00:00
|
|
|
from Application.Logger import get_logger
|
|
|
|
|
|
|
|
|
|
logger = get_logger(__name__)
|
2022-10-11 19:35:37 +00:00
|
|
|
|
|
|
|
|
|
2020-10-07 13:07:01 +00:00
|
|
|
class Config:
|
2026-02-15 17:21:55 +00:00
|
|
|
"""
|
|
|
|
|
Configuration management supporting JSON and YAML formats.
|
|
|
|
|
|
|
|
|
|
Supports loading configuration from JSON or YAML files, with fallback
|
|
|
|
|
to default values. Also supports environment variable overrides.
|
|
|
|
|
"""
|
|
|
|
|
|
2020-10-07 13:07:01 +00:00
|
|
|
c = {
|
2022-08-16 20:50:00 +00:00
|
|
|
"min_area": 300,
|
2022-01-09 19:25:44 +00:00
|
|
|
"max_area": 900000,
|
2022-10-11 19:35:37 +00:00
|
|
|
"threshold": 7,
|
2022-08-16 20:50:00 +00:00
|
|
|
"resizeWidth": 700,
|
2022-01-09 19:25:44 +00:00
|
|
|
"inputPath": None,
|
2020-10-11 15:09:49 +00:00
|
|
|
"outputPath": None,
|
2022-01-09 19:25:44 +00:00
|
|
|
"maxLayerLength": 5000,
|
|
|
|
|
"minLayerLength": 40,
|
2020-12-18 20:27:19 +00:00
|
|
|
"tolerance": 20,
|
2020-10-07 13:07:01 +00:00
|
|
|
"maxLength": None,
|
2020-12-22 12:58:47 +00:00
|
|
|
"ttolerance": 60,
|
2022-01-05 13:57:29 +00:00
|
|
|
"videoBufferLength": 250,
|
2020-12-18 20:27:19 +00:00
|
|
|
"LayersPerContour": 220,
|
2022-01-09 19:25:44 +00:00
|
|
|
"avgNum": 10,
|
|
|
|
|
}
|
2020-10-11 15:09:49 +00:00
|
|
|
|
2026-02-15 17:16:45 +00:00
|
|
|
def __init__(self, config_path: Optional[str]):
|
|
|
|
|
"""
|
|
|
|
|
Initialize configuration from file or use defaults.
|
|
|
|
|
|
|
|
|
|
Args:
|
2026-02-15 17:21:55 +00:00
|
|
|
config_path: Path to JSON or YAML configuration file.
|
|
|
|
|
If None or invalid, uses defaults.
|
|
|
|
|
Supports .json, .yaml, and .yml extensions.
|
2026-02-15 17:16:45 +00:00
|
|
|
"""
|
|
|
|
|
if config_path and os.path.isfile(config_path):
|
|
|
|
|
logger.info(f"Using supplied configuration at {config_path}")
|
|
|
|
|
try:
|
2026-02-15 17:21:55 +00:00
|
|
|
self.c = self._load_config_file(config_path)
|
|
|
|
|
except Exception as e:
|
2026-02-15 17:16:45 +00:00
|
|
|
logger.error(f"Failed to parse config file: {e}")
|
|
|
|
|
logger.warning("Falling back to default configuration")
|
2022-10-11 19:35:37 +00:00
|
|
|
else:
|
2026-02-15 17:16:45 +00:00
|
|
|
logger.info("Using default configuration")
|
2022-10-11 19:35:37 +00:00
|
|
|
|
2026-02-15 17:21:55 +00:00
|
|
|
# Apply environment variable overrides
|
|
|
|
|
self._apply_env_overrides()
|
|
|
|
|
|
2026-02-15 17:16:45 +00:00
|
|
|
logger.info("Current Configuration:")
|
2020-11-08 15:28:47 +00:00
|
|
|
for key, value in self.c.items():
|
2026-02-15 17:16:45 +00:00
|
|
|
logger.info(f" {key}: {value}")
|
2022-01-09 19:25:44 +00:00
|
|
|
|
2026-02-15 17:21:55 +00:00
|
|
|
def _load_config_file(self, config_path: str) -> dict:
|
|
|
|
|
"""
|
|
|
|
|
Load configuration from JSON or YAML file.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
config_path: Path to configuration file
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Dictionary with configuration values
|
|
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
|
ValueError: If file format is not supported
|
|
|
|
|
"""
|
|
|
|
|
ext = os.path.splitext(config_path)[1].lower()
|
|
|
|
|
|
|
|
|
|
with open(config_path, "r") as file:
|
|
|
|
|
if ext == ".json":
|
|
|
|
|
return json.load(file)
|
|
|
|
|
elif ext in [".yaml", ".yml"]:
|
|
|
|
|
if not YAML_AVAILABLE:
|
|
|
|
|
raise ValueError("PyYAML is not installed. Install with: pip install pyyaml")
|
|
|
|
|
return yaml.safe_load(file)
|
|
|
|
|
else:
|
|
|
|
|
# Try JSON first, then YAML
|
|
|
|
|
content = file.read()
|
|
|
|
|
file.seek(0)
|
|
|
|
|
try:
|
|
|
|
|
return json.loads(content)
|
|
|
|
|
except json.JSONDecodeError:
|
|
|
|
|
if YAML_AVAILABLE:
|
|
|
|
|
file.seek(0)
|
|
|
|
|
return yaml.safe_load(file)
|
|
|
|
|
else:
|
|
|
|
|
raise ValueError(f"Unsupported config file format: {ext}")
|
|
|
|
|
|
|
|
|
|
def _apply_env_overrides(self):
|
|
|
|
|
"""Apply environment variable overrides to configuration."""
|
|
|
|
|
env_prefix = "VIDEO_SUMMARY_"
|
|
|
|
|
for key in self.c.keys():
|
|
|
|
|
env_key = f"{env_prefix}{key.upper()}"
|
|
|
|
|
env_value = os.environ.get(env_key)
|
|
|
|
|
if env_value is not None:
|
|
|
|
|
# Try to convert to appropriate type
|
|
|
|
|
try:
|
|
|
|
|
# Try integer
|
|
|
|
|
self.c[key] = int(env_value)
|
|
|
|
|
except ValueError:
|
|
|
|
|
try:
|
|
|
|
|
# Try float
|
|
|
|
|
self.c[key] = float(env_value)
|
|
|
|
|
except ValueError:
|
|
|
|
|
# Use as string
|
|
|
|
|
self.c[key] = env_value
|
|
|
|
|
logger.info(f"Environment override: {key} = {self.c[key]}")
|
|
|
|
|
|
2026-02-15 17:16:45 +00:00
|
|
|
def __getitem__(self, key: str) -> Any:
|
2026-02-15 17:21:55 +00:00
|
|
|
"""Get configuration value by key."""
|
2020-10-16 08:36:52 +00:00
|
|
|
if key not in self.c:
|
|
|
|
|
return None
|
2022-01-09 19:25:44 +00:00
|
|
|
return self.c[key]
|
2020-10-07 13:07:01 +00:00
|
|
|
|
2026-02-15 17:16:45 +00:00
|
|
|
def __setitem__(self, key: str, value: Any) -> None:
|
2026-02-15 17:21:55 +00:00
|
|
|
"""Set configuration value by key."""
|
2020-10-11 15:09:49 +00:00
|
|
|
self.c[key] = value
|
2026-02-15 17:21:55 +00:00
|
|
|
|
|
|
|
|
def save(self, output_path: str):
|
|
|
|
|
"""
|
|
|
|
|
Save current configuration to file.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
output_path: Path to save configuration file.
|
|
|
|
|
Format is determined by extension (.json, .yaml, .yml)
|
|
|
|
|
"""
|
|
|
|
|
ext = os.path.splitext(output_path)[1].lower()
|
|
|
|
|
|
|
|
|
|
with open(output_path, "w") as file:
|
|
|
|
|
if ext == ".json":
|
|
|
|
|
json.dump(self.c, file, indent=2)
|
|
|
|
|
elif ext in [".yaml", ".yml"]:
|
|
|
|
|
if not YAML_AVAILABLE:
|
|
|
|
|
raise ValueError("PyYAML is not installed. Install with: pip install pyyaml")
|
|
|
|
|
yaml.dump(self.c, file, default_flow_style=False)
|
|
|
|
|
else:
|
|
|
|
|
# Default to JSON
|
|
|
|
|
json.dump(self.c, file, indent=2)
|