gen_example_config.py 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. """Generate an example config.json showing all available options with their defaults.
  2. Produces a merged document: dataclass defaults provide the full key schema,
  3. the bundled config.json supplies the real values (wins on conflict).
  4. Usage:
  5. python scripts/gen_example_config.py
  6. python scripts/gen_example_config.py > docs/example_config.json
  7. """
  8. import dataclasses
  9. import json
  10. import sys
  11. from importlib.resources import files
  12. sys.path.insert(0, str(__import__('pathlib').Path(__file__).parent.parent))
  13. from room_cal._utils import CalendarEntry, Config, ServiceConfig, _deep_merge
  14. def _strip_none(obj):
  15. """Recursively remove keys whose value is None."""
  16. if isinstance(obj, dict):
  17. return {k: _strip_none(v) for k, v in obj.items() if v is not None}
  18. if isinstance(obj, list):
  19. return [_strip_none(i) for i in obj]
  20. return obj
  21. def _defaults_dict() -> dict:
  22. raw = dataclasses.asdict(Config())
  23. raw['global'] = raw.pop('global_')
  24. raw.pop('api_url', None)
  25. raw.pop('services', None)
  26. raw.pop('calendars', None)
  27. raw['rules'].pop('pipelines', None)
  28. return _strip_none(raw)
  29. def _expand_service(key: str, d: dict) -> dict:
  30. """Round-trip a service dict through ServiceConfig so all dataclass fields appear."""
  31. full = dataclasses.asdict(ServiceConfig.from_dict(key, d))
  32. full.pop('key', None)
  33. return _strip_none(full)
  34. def generate() -> str:
  35. defaults = _defaults_dict()
  36. stock = json.loads(files('room_cal').joinpath('config.json').read_text(encoding='utf-8'))
  37. merged = _deep_merge(defaults, stock)
  38. merged['services'] = {k: _expand_service(k, v) for k, v in merged.get('services', {}).items()}
  39. merged['calendars'] = [dataclasses.asdict(CalendarEntry.from_dict(e)) for e in merged.get('calendars', [])]
  40. return json.dumps(merged, indent=2)
  41. def main():
  42. print(generate())
  43. if __name__ == '__main__':
  44. main()