Spaces:
Sleeping
Sleeping
| """JSON configuration loader for ITU document generation.""" | |
| import json | |
| import os | |
| import sys | |
| import datetime | |
| def load_config(config_path): | |
| """Load and validate a JSON configuration file. | |
| Returns a dict with all configuration values, with defaults applied. | |
| Relative paths (e.g. workProgramme) are resolved relative to the | |
| config file's directory. | |
| If 'end' date is not provided, it will be fetched from the ITU meeting page. | |
| """ | |
| try: | |
| with open(config_path, "r", encoding="utf-8") as fid: | |
| content = json.loads(fid.read()) | |
| except Exception as e: | |
| print(f"Error loading config {config_path}: {e}") | |
| sys.exit(1) | |
| # Study group | |
| group = _get_int(content, 'group', "group") | |
| # Start date (required) | |
| start_string = content.get('start') | |
| start = _parse_date(start_string, "start date") | |
| start_date = f"{start.year:04}{start.month:02}{start.day:02}" | |
| # End date and place - fetched from ITU meeting page | |
| from common.itu_api import get_meeting_info | |
| print(f"Fetching meeting info from ITU website...") | |
| meeting_info = get_meeting_info(group, start_date) | |
| if meeting_info: | |
| end = meeting_info['end'] | |
| place = meeting_info.get('place', '') | |
| country = meeting_info.get('country', '') | |
| print(f" Found: {meeting_info['start'].strftime('%Y-%m-%d')} to {end.strftime('%Y-%m-%d')}, {place} ({country})") | |
| else: | |
| print(" Warning: Could not fetch meeting info from ITU. Using defaults.") | |
| end = start | |
| place = '' | |
| country = '' | |
| config = { | |
| 'group': group, | |
| 'place': place, | |
| 'country': country, | |
| 'start': start, | |
| 'startString': start_string, | |
| 'startDate': start_date, | |
| 'end': end, | |
| '_raw': content, | |
| } | |
| return config | |
| def load_question_config(config_path): | |
| """Load config for a Question report. Adds the 'question' and 'next_meeting' fields.""" | |
| config = load_config(config_path) | |
| config['question'] = _get_int(config['_raw'], 'question', "question") | |
| # Optional next_meeting date for filtering candidate work items | |
| next_meeting_str = config['_raw'].get('next_meeting') | |
| if next_meeting_str: | |
| config['next_meeting'] = _parse_date(next_meeting_str, "next_meeting") | |
| else: | |
| config['next_meeting'] = None | |
| return config | |
| def load_wp_config(config_path): | |
| """Load config for a Working Party report. Adds the 'workingParty' and 'next_meeting' fields.""" | |
| config = load_config(config_path) | |
| config['workingParty'] = _get_int(config['_raw'], 'workingParty', "workingParty") | |
| # Optional next_meeting date for filtering candidate work items | |
| next_meeting_str = config['_raw'].get('next_meeting') | |
| if next_meeting_str: | |
| config['next_meeting'] = _parse_date(next_meeting_str, "next_meeting") | |
| else: | |
| config['next_meeting'] = None | |
| return config | |
| def _get_int(content, key, label): | |
| """Extract an integer value from config.""" | |
| val = content.get(key) | |
| if val is None: | |
| print(f"Missing required field: {label}") | |
| sys.exit(1) | |
| try: | |
| return int(val) | |
| except (ValueError, TypeError): | |
| print(f"Invalid {label}: {val}") | |
| sys.exit(1) | |
| def _parse_date(date_string, label): | |
| """Parse a YYYY/MM/DD date string.""" | |
| try: | |
| return datetime.datetime.strptime(date_string, "%Y/%m/%d") | |
| except Exception: | |
| print(f"Invalid {label}: {date_string}") | |
| sys.exit(1) | |